blob: cf417bd70385073d8f5a7651c355940be6685d66 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluez/bluetooth_adapter_bluez.h"
#include "device/bluetooth/bluez/bluetooth_device_bluez.h"
#include "device/bluetooth/bluez/bluetooth_pairing_bluez.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
#include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
#include "device/bluetooth/test/test_pairing_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using device::BluetoothAdapter;
using device::BluetoothAdapterFactory;
using device::BluetoothDevice;
using device::BluetoothDeviceType;
using device::BluetoothDiscoveryFilter;
using device::BluetoothDiscoverySession;
using device::BluetoothUUID;
using device::TestBluetoothAdapterObserver;
using device::TestPairingDelegate;
namespace bluez {
namespace {
// Callback for BluetoothDevice::GetConnectionInfo() that simply saves the
// connection info to the bound argument.
void SaveConnectionInfo(BluetoothDevice::ConnectionInfo* out,
const BluetoothDevice::ConnectionInfo& conn_info) {
*out = conn_info;
}
// Find |address| in |devices|, if found returns the index otherwise returns -1.
int GetDeviceIndexByAddress(const BluetoothAdapter::DeviceList& devices,
const char* address) {
int idx = -1;
for (auto* device : devices) {
++idx;
if (device->GetAddress().compare(address) == 0)
return idx;
}
return -1;
}
class FakeBluetoothProfileServiceProviderDelegate
: public bluez::BluetoothProfileServiceProvider::Delegate {
public:
FakeBluetoothProfileServiceProviderDelegate() = default;
// bluez::BluetoothProfileServiceProvider::Delegate:
void Released() override {}
void NewConnection(
const dbus::ObjectPath&,
base::ScopedFD,
const bluez::BluetoothProfileServiceProvider::Delegate::Options&,
const ConfirmationCallback&) override {}
void RequestDisconnection(const dbus::ObjectPath&,
const ConfirmationCallback&) override {}
void Cancel() override {}
};
} // namespace
class BluetoothBlueZTest : public testing::Test {
public:
static const char kGapUuid[];
static const char kGattUuid[];
static const char kPnpUuid[];
static const char kHeadsetUuid[];
void SetUp() override {
std::unique_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
bluez::BluezDBusManager::GetSetterForTesting();
// We need to initialize BluezDBusManager early to prevent
// Bluetooth*::Create() methods from picking the real instead of fake
// implementations.
fake_bluetooth_adapter_client_ = new bluez::FakeBluetoothAdapterClient;
dbus_setter->SetBluetoothAdapterClient(
std::unique_ptr<bluez::BluetoothAdapterClient>(
fake_bluetooth_adapter_client_));
fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient;
// Use the original fake behavior for these tests.
fake_bluetooth_device_client_->set_delay_start_discovery(true);
dbus_setter->SetBluetoothDeviceClient(
std::unique_ptr<bluez::BluetoothDeviceClient>(
fake_bluetooth_device_client_));
dbus_setter->SetBluetoothInputClient(
std::unique_ptr<bluez::BluetoothInputClient>(
new bluez::FakeBluetoothInputClient));
dbus_setter->SetBluetoothAgentManagerClient(
std::unique_ptr<bluez::BluetoothAgentManagerClient>(
new bluez::FakeBluetoothAgentManagerClient));
dbus_setter->SetBluetoothGattServiceClient(
std::unique_ptr<bluez::BluetoothGattServiceClient>(
new bluez::FakeBluetoothGattServiceClient));
fake_bluetooth_adapter_client_->SetSimulationIntervalMs(10);
callback_count_ = 0;
error_callback_count_ = 0;
last_connect_error_ = BluetoothDevice::ERROR_UNKNOWN;
last_client_error_ = "";
}
void TearDown() override {
for (const auto& session : discovery_sessions_) {
if (!session->IsActive())
continue;
callback_count_ = 0;
session->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
ASSERT_EQ(1, callback_count_);
}
discovery_sessions_.clear();
adapter_ = nullptr;
bluez::BluezDBusManager::Shutdown();
}
// Generic callbacks
void Callback() {
++callback_count_;
QuitMessageLoop();
}
base::Closure GetCallback() {
return base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this));
}
void AdapterCallback() { QuitMessageLoop(); }
void DiscoverySessionCallback(
std::unique_ptr<BluetoothDiscoverySession> discovery_session) {
++callback_count_;
discovery_sessions_.push_back(std::move(discovery_session));
QuitMessageLoop();
}
void ProfileRegisteredCallback(BluetoothAdapterProfileBlueZ* profile) {
adapter_profile_ = profile;
++callback_count_;
QuitMessageLoop();
}
void ErrorCallback() {
++error_callback_count_;
QuitMessageLoop();
}
void DiscoveryErrorCallback(device::UMABluetoothDiscoverySessionOutcome) {
ErrorCallback();
}
base::Closure GetErrorCallback() {
return base::Bind(&BluetoothBlueZTest::ErrorCallback,
base::Unretained(this));
}
base::Callback<void(device::UMABluetoothDiscoverySessionOutcome)>
GetDiscoveryErrorCallback() {
return base::Bind(&BluetoothBlueZTest::DiscoveryErrorCallback,
base::Unretained(this));
}
void DBusErrorCallback(const std::string& error_name,
const std::string& error_message) {
++error_callback_count_;
last_client_error_ = error_name;
QuitMessageLoop();
}
void ConnectErrorCallback(BluetoothDevice::ConnectErrorCode error) {
++error_callback_count_;
last_connect_error_ = error;
}
void ErrorCompletionCallback(const std::string& error_message) {
++error_callback_count_;
QuitMessageLoop();
}
// Call to fill the adapter_ member with a BluetoothAdapter instance.
void GetAdapter() {
adapter_ = new BluetoothAdapterBlueZ(base::Bind(
&BluetoothBlueZTest::AdapterCallback, base::Unretained(this)));
base::RunLoop().Run();
ASSERT_TRUE(adapter_.get() != nullptr);
ASSERT_TRUE(adapter_->IsInitialized());
}
// Run a discovery phase until the named device is detected, or if the named
// device is not created, the discovery process ends without finding it.
//
// The correct behavior of discovery is tested by the "Discovery" test case
// without using this function.
void DiscoverDevice(const std::string& address) {
ASSERT_TRUE(adapter_.get() != nullptr);
ASSERT_TRUE(base::MessageLoopCurrent::IsSet());
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
ASSERT_EQ(2, callback_count_);
ASSERT_EQ(0, error_callback_count_);
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
while (!observer.device_removed_count() &&
observer.last_device_address() != address)
base::RunLoop().Run();
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
ASSERT_EQ(1, callback_count_);
ASSERT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_FALSE(adapter_->IsDiscovering());
}
// Run a discovery phase so we have devices that can be paired with.
void DiscoverDevices() {
// Pass an invalid address for the device so that the discovery process
// completes with all devices.
DiscoverDevice("does not exist");
}
protected:
base::MessageLoop message_loop_;
bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_;
bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
scoped_refptr<BluetoothAdapter> adapter_;
int callback_count_;
int error_callback_count_;
enum BluetoothDevice::ConnectErrorCode last_connect_error_;
std::string last_client_error_;
std::vector<std::unique_ptr<BluetoothDiscoverySession>> discovery_sessions_;
BluetoothAdapterProfileBlueZ* adapter_profile_;
private:
// Some tests use a message loop since background processing is simulated;
// break out of those loops.
void QuitMessageLoop() {
if (base::RunLoop::IsRunningOnCurrentThread())
base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
};
const char BluetoothBlueZTest::kGapUuid[] =
"00001800-0000-1000-8000-00805f9b34fb";
const char BluetoothBlueZTest::kGattUuid[] =
"00001801-0000-1000-8000-00805f9b34fb";
const char BluetoothBlueZTest::kPnpUuid[] =
"00001200-0000-1000-8000-00805f9b34fb";
const char BluetoothBlueZTest::kHeadsetUuid[] =
"00001112-0000-1000-8000-00805f9b34fb";
TEST_F(BluetoothBlueZTest, AlreadyPresent) {
GetAdapter();
// This verifies that the class gets the list of adapters when created;
// and initializes with an existing adapter if there is one.
EXPECT_TRUE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress,
adapter_->GetAddress());
EXPECT_FALSE(adapter_->IsDiscovering());
// There should be 2 devices
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
EXPECT_EQ(2U, devices.size());
// |devices| are not ordered, verify it contains the 2 device addresses.
EXPECT_NE(
-1, GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
EXPECT_NE(
-1,
GetDeviceIndexByAddress(
devices,
bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress));
}
TEST_F(BluetoothBlueZTest, BecomePresent) {
fake_bluetooth_adapter_client_->SetVisible(false);
GetAdapter();
ASSERT_FALSE(adapter_->IsPresent());
// Install an observer; expect the AdapterPresentChanged to be called
// with true, and IsPresent() to return true.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(true);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_TRUE(observer.last_present());
EXPECT_TRUE(adapter_->IsPresent());
// We should have had a device announced.
EXPECT_EQ(2, observer.device_added_count());
EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
observer.last_device_address());
// Other callbacks shouldn't be called if the values are false.
EXPECT_EQ(0, observer.powered_changed_count());
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(adapter_->IsPowered());
EXPECT_FALSE(adapter_->IsDiscovering());
}
TEST_F(BluetoothBlueZTest, BecomeNotPresent) {
GetAdapter();
ASSERT_TRUE(adapter_->IsPresent());
// Install an observer; expect the AdapterPresentChanged to be called
// with false, and IsPresent() to return false.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
// We should have had 2 devices removed.
EXPECT_EQ(2, observer.device_removed_count());
// 2 possibilities for the last device here.
std::string address = observer.last_device_address();
EXPECT_TRUE(address.compare(bluez::FakeBluetoothDeviceClient::
kPairedUnconnectableDeviceAddress) == 0 ||
address.compare(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0);
// DiscoveringChanged() should be triggered regardless of the current value
// of Discovering property.
EXPECT_EQ(1, observer.discovering_changed_count());
// Other callbacks shouldn't be called since the values are false.
EXPECT_EQ(0, observer.powered_changed_count());
EXPECT_FALSE(adapter_->IsPowered());
EXPECT_FALSE(adapter_->IsDiscovering());
}
TEST_F(BluetoothBlueZTest, SecondAdapter) {
GetAdapter();
ASSERT_TRUE(adapter_->IsPresent());
// Install an observer, then add a second adapter. Nothing should change,
// we ignore the second adapter.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetSecondVisible(true);
EXPECT_EQ(0, observer.present_changed_count());
EXPECT_TRUE(adapter_->IsPresent());
EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress,
adapter_->GetAddress());
// Try removing the first adapter, we should now act as if the adapter
// is no longer present rather than fall back to the second.
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
// We should have had 2 devices removed.
EXPECT_EQ(2, observer.device_removed_count());
// As BluetoothAdapter devices removal does not keep the order of adding them,
// 2 possibilities for the last device here.
std::string address = observer.last_device_address();
EXPECT_TRUE(address.compare(bluez::FakeBluetoothDeviceClient::
kPairedUnconnectableDeviceAddress) == 0 ||
address.compare(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress) == 0);
// DiscoveringChanged() should be triggered regardless of the current value
// of Discovering property.
EXPECT_EQ(1, observer.discovering_changed_count());
// Other callbacks shouldn't be called since the values are false.
EXPECT_EQ(0, observer.powered_changed_count());
EXPECT_FALSE(adapter_->IsPowered());
EXPECT_FALSE(adapter_->IsDiscovering());
observer.Reset();
// Removing the second adapter shouldn't set anything either.
fake_bluetooth_adapter_client_->SetSecondVisible(false);
EXPECT_EQ(0, observer.device_removed_count());
EXPECT_EQ(0, observer.powered_changed_count());
EXPECT_EQ(0, observer.discovering_changed_count());
}
TEST_F(BluetoothBlueZTest, BecomePowered) {
GetAdapter();
ASSERT_FALSE(adapter_->IsPowered());
// Install an observer; expect the AdapterPoweredChanged to be called
// with true, and IsPowered() to return true.
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.powered_changed_count());
EXPECT_TRUE(observer.last_powered());
EXPECT_TRUE(adapter_->IsPowered());
}
TEST_F(BluetoothBlueZTest, BecomeNotPowered) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
// Install an observer; expect the AdapterPoweredChanged to be called
// with false, and IsPowered() to return false.
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetPowered(false, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.powered_changed_count());
EXPECT_FALSE(observer.last_powered());
EXPECT_FALSE(adapter_->IsPowered());
}
TEST_F(BluetoothBlueZTest, SetPoweredWhenNotPresent) {
GetAdapter();
ASSERT_TRUE(adapter_->IsPresent());
// Install an observer; expect the AdapterPresentChanged to be called
// with false, and IsPresent() to return false.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(0, observer.powered_changed_count());
EXPECT_FALSE(observer.last_powered());
EXPECT_FALSE(adapter_->IsPowered());
}
TEST_F(BluetoothBlueZTest, ChangeAdapterName) {
GetAdapter();
const std::string new_name(".__.");
adapter_->SetName(new_name, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(new_name, adapter_->GetName());
}
TEST_F(BluetoothBlueZTest, ChangeAdapterNameWhenNotPresent) {
GetAdapter();
ASSERT_TRUE(adapter_->IsPresent());
// Install an observer; expect the AdapterPresentChanged to be called
// with false, and IsPresent() to return false.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
adapter_->SetName("^o^", GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ("", adapter_->GetName());
}
TEST_F(BluetoothBlueZTest, GetUUIDs) {
std::vector<std::string> adapterUuids;
GetAdapter();
adapterUuids.push_back(kGapUuid);
adapterUuids.push_back(kGattUuid);
adapterUuids.push_back(kPnpUuid);
adapterUuids.push_back(kHeadsetUuid);
fake_bluetooth_adapter_client_->SetUUIDs(adapterUuids);
BluetoothAdapter::UUIDList uuids = adapter_->GetUUIDs();
ASSERT_EQ(4U, uuids.size());
// Check that the UUIDs match those from above - in order, GAP, GATT, PnP, and
// headset.
EXPECT_EQ(uuids[0], BluetoothUUID("1800"));
EXPECT_EQ(uuids[1], BluetoothUUID("1801"));
EXPECT_EQ(uuids[2], BluetoothUUID("1200"));
EXPECT_EQ(uuids[3], BluetoothUUID("1112"));
}
TEST_F(BluetoothBlueZTest, BecomeDiscoverable) {
GetAdapter();
ASSERT_FALSE(adapter_->IsDiscoverable());
// Install an observer; expect the AdapterDiscoverableChanged to be called
// with true, and IsDiscoverable() to return true.
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetDiscoverable(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.discoverable_changed_count());
EXPECT_TRUE(adapter_->IsDiscoverable());
}
TEST_F(BluetoothBlueZTest, BecomeNotDiscoverable) {
GetAdapter();
adapter_->SetDiscoverable(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsDiscoverable());
// Install an observer; expect the AdapterDiscoverableChanged to be called
// with false, and IsDiscoverable() to return false.
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetDiscoverable(false, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.discoverable_changed_count());
EXPECT_FALSE(adapter_->IsDiscoverable());
}
TEST_F(BluetoothBlueZTest, SetDiscoverableWhenNotPresent) {
GetAdapter();
ASSERT_TRUE(adapter_->IsPresent());
ASSERT_FALSE(adapter_->IsDiscoverable());
// Install an observer; expect the AdapterDiscoverableChanged to be called
// with true, and IsDiscoverable() to return true.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsDiscoverable());
adapter_->SetDiscoverable(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(0, observer.discoverable_changed_count());
EXPECT_FALSE(adapter_->IsDiscoverable());
}
TEST_F(BluetoothBlueZTest, StopDiscovery) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
// Install an observer; aside from the callback, expect the
// AdapterDiscoveringChanged method to be called and no longer to be
// discovering,
TestBluetoothAdapterObserver observer(adapter_);
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
discovery_sessions_.clear();
callback_count_ = 0;
// Test that the Stop callbacks get called even if the
// BluetoothDiscoverySession objects gets deleted
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
discovery_sessions_.clear();
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
TEST_F(BluetoothBlueZTest, StopDiscoveryInProgress) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
callback_count_ = 0;
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
// First call to Stop() should succeed.
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
// Second call to Stop() while the first is in progress should fail.
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(1, error_callback_count_);
discovery_sessions_.clear();
callback_count_ = 0;
error_callback_count_ = 0;
}
TEST_F(BluetoothBlueZTest, Discovery) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
// First two devices to appear.
base::RunLoop().Run();
EXPECT_EQ(2, observer.device_added_count());
EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress,
observer.last_device_address());
// Next we should get another two devices...
base::RunLoop().Run();
EXPECT_EQ(4, observer.device_added_count());
// Okay, let's run forward until a device is actually removed...
while (!observer.device_removed_count())
base::RunLoop().Run();
EXPECT_EQ(1, observer.device_removed_count());
EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress,
observer.last_device_address());
}
TEST_F(BluetoothBlueZTest, PoweredAndDiscovering) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
// Stop the timers that the simulation uses
fake_bluetooth_device_client_->EndDiscoverySimulation(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
fake_bluetooth_adapter_client_->SetVisible(false);
ASSERT_FALSE(adapter_->IsPresent());
ASSERT_FALSE(discovery_sessions_[0]->IsActive());
// Install an observer; expect the AdapterPresentChanged,
// AdapterPoweredChanged and AdapterDiscoveringChanged methods to be called
// with true, and IsPresent(), IsPowered() and IsDiscovering() to all
// return true.
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_adapter_client_->SetVisible(true);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_TRUE(observer.last_present());
EXPECT_TRUE(adapter_->IsPresent());
EXPECT_EQ(1, observer.powered_changed_count());
EXPECT_TRUE(observer.last_powered());
EXPECT_TRUE(adapter_->IsPowered());
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
observer.Reset();
// Now mark the adapter not present again. Expect the methods to be called
// again, to reset the properties back to false
fake_bluetooth_adapter_client_->SetVisible(false);
EXPECT_EQ(1, observer.present_changed_count());
EXPECT_FALSE(observer.last_present());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_EQ(1, observer.powered_changed_count());
EXPECT_FALSE(observer.last_powered());
EXPECT_FALSE(adapter_->IsPowered());
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
}
// This unit test asserts that the basic reference counting logic works
// correctly for discovery requests done via the BluetoothAdapter.
TEST_F(BluetoothBlueZTest, MultipleDiscoverySessions) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// Request device discovery 3 times.
for (int i = 0; i < 3; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
// The observer should have received the discovering changed event exactly
// once, the success callback should have been called 3 times and the adapter
// should be discovering.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
// Request to stop discovery twice.
for (int i = 0; i < 2; i++) {
discovery_sessions_[i]->Stop(GetCallback(), GetErrorCallback());
}
// The observer should have received no additional discovering changed events,
// the success callback should have been called 2 times and the adapter should
// still be discovering.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(5, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
EXPECT_FALSE(discovery_sessions_[1]->IsActive());
EXPECT_TRUE(discovery_sessions_[2]->IsActive());
// Request device discovery 3 times.
for (int i = 0; i < 3; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
// The observer should have received no additional discovering changed events,
// the success callback should have been called 3 times and the adapter should
// still be discovering.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(8, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)6, discovery_sessions_.size());
// Request to stop discovery 4 times.
for (int i = 2; i < 6; i++) {
discovery_sessions_[i]->Stop(GetCallback(), GetErrorCallback());
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
// The observer should have received the discovering changed event exactly
// once, the success callback should have been called 4 times and the adapter
// should no longer be discovering.
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_EQ(12, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// All discovery sessions should be inactive.
for (int i = 0; i < 6; i++)
EXPECT_FALSE(discovery_sessions_[i]->IsActive());
// Request to stop discovery on of the inactive sessions.
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
// The call should have failed.
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_EQ(12, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
}
// This unit test asserts that the reference counting logic works correctly in
// the cases when the adapter gets reset and D-Bus calls are made outside of
// the BluetoothAdapter.
TEST_F(BluetoothBlueZTest, UnexpectedChangesDuringMultipleDiscoverySessions) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// Request device discovery 3 times.
for (int i = 0; i < 3; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
// The observer should have received the discovering changed event exactly
// once, the success callback should have been called 3 times and the adapter
// should be discovering.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
for (int i = 0; i < 3; i++)
EXPECT_TRUE(discovery_sessions_[i]->IsActive());
// Stop the timers that the simulation uses
fake_bluetooth_device_client_->EndDiscoverySimulation(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
// Stop device discovery behind the adapter. The adapter and the observer
// should be notified of the change and the reference count should be reset.
// Even though bluez::FakeBluetoothAdapterClient does its own reference
// counting and
// we called 3 BluetoothAdapter::StartDiscoverySession 3 times, the
// bluez::FakeBluetoothAdapterClient's count should be only 1 and a single
// call to
// bluez::FakeBluetoothAdapterClient::StopDiscovery should work.
fake_bluetooth_adapter_client_->StopDiscovery(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_EQ(4, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// All discovery session instances should have been updated.
for (int i = 0; i < 3; i++)
EXPECT_FALSE(discovery_sessions_[i]->IsActive());
discovery_sessions_.clear();
// It should be possible to successfully start discovery.
for (int i = 0; i < 2; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
EXPECT_EQ(3, observer.discovering_changed_count());
EXPECT_EQ(6, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)2, discovery_sessions_.size());
for (int i = 0; i < 2; i++)
EXPECT_TRUE(discovery_sessions_[i]->IsActive());
fake_bluetooth_device_client_->EndDiscoverySimulation(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
// Make the adapter disappear and appear. This will make it come back as
// discovering. When this happens, the reference count should become and
// remain 0 as no new request was made through the BluetoothAdapter.
fake_bluetooth_adapter_client_->SetVisible(false);
ASSERT_FALSE(adapter_->IsPresent());
EXPECT_EQ(4, observer.discovering_changed_count());
EXPECT_EQ(6, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
for (int i = 0; i < 2; i++)
EXPECT_FALSE(discovery_sessions_[i]->IsActive());
discovery_sessions_.clear();
fake_bluetooth_adapter_client_->SetVisible(true);
ASSERT_TRUE(adapter_->IsPresent());
EXPECT_EQ(5, observer.discovering_changed_count());
EXPECT_EQ(6, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
// Start and stop discovery. At this point, bluez::FakeBluetoothAdapterClient
// has
// a reference count that is equal to 1. Pretend that this was done by an
// application other than us. Starting and stopping discovery will succeed
// but it won't cause the discovery state to change.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
// Run the loop, as there should have been a D-Bus call.
base::RunLoop().Run();
EXPECT_EQ(5, observer.discovering_changed_count());
EXPECT_EQ(7, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
// Run the loop, as there should have been a D-Bus call.
base::RunLoop().Run();
EXPECT_EQ(5, observer.discovering_changed_count());
EXPECT_EQ(8, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
discovery_sessions_.clear();
// Start discovery again.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
// Run the loop, as there should have been a D-Bus call.
base::RunLoop().Run();
EXPECT_EQ(5, observer.discovering_changed_count());
EXPECT_EQ(9, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
// Stop discovery via D-Bus. The fake client's reference count will drop but
// the discovery state won't change since our BluetoothAdapter also just
// requested it via D-Bus.
fake_bluetooth_adapter_client_->StopDiscovery(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(5, observer.discovering_changed_count());
EXPECT_EQ(10, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
// Now end the discovery session. This should change the adapter's discovery
// state.
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(6, observer.discovering_changed_count());
EXPECT_EQ(11, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
}
TEST_F(BluetoothBlueZTest, InvalidatedDiscoverySessions) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// Request device discovery 3 times.
for (int i = 0; i < 3; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
// The observer should have received the discovering changed event exactly
// once, the success callback should have been called 3 times and the adapter
// should be discovering.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
for (int i = 0; i < 3; i++)
EXPECT_TRUE(discovery_sessions_[i]->IsActive());
// Stop the timers that the simulation uses
fake_bluetooth_device_client_->EndDiscoverySimulation(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
// Delete all but one discovery session.
discovery_sessions_.pop_back();
discovery_sessions_.pop_back();
ASSERT_EQ((size_t)1, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
EXPECT_TRUE(adapter_->IsDiscovering());
// Stop device discovery behind the adapter. The one active discovery session
// should become inactive, but more importantly, we shouldn't run into any
// memory errors as the sessions that we explicitly deleted should get
// cleaned up.
fake_bluetooth_adapter_client_->StopDiscovery(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_EQ(4, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
}
TEST_F(BluetoothBlueZTest, QueuedDiscoveryRequests) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
// Request to start discovery. The call should be pending.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
EXPECT_EQ(0, callback_count_);
fake_bluetooth_device_client_->EndDiscoverySimulation(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
// The underlying adapter has started discovery, but our call hasn't returned
// yet.
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_TRUE(discovery_sessions_.empty());
// Request to start discovery twice. These should get queued and there should
// be no change in state.
for (int i = 0; i < 2; i++) {
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
}
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_TRUE(discovery_sessions_.empty());
// Process the pending call. The queued calls should execute and the discovery
// session reference count should increase.
base::RunLoop().Run();
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
// Verify the reference count by removing sessions 3 times. The last request
// should remain pending.
for (int i = 0; i < 3; i++) {
discovery_sessions_[i]->Stop(GetCallback(), GetErrorCallback());
}
EXPECT_EQ(5, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
EXPECT_FALSE(discovery_sessions_[1]->IsActive());
EXPECT_TRUE(discovery_sessions_[2]->IsActive());
// Request to stop the session whose call is pending should fail.
discovery_sessions_[2]->Stop(GetCallback(), GetErrorCallback());
EXPECT_EQ(5, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_TRUE(discovery_sessions_[2]->IsActive());
// Request to start should get queued.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
EXPECT_EQ(5, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
// Run the pending request.
base::RunLoop().Run();
EXPECT_EQ(6, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(3, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
EXPECT_FALSE(discovery_sessions_[2]->IsActive());
// The queued request to start discovery should have been issued but is still
// pending. Run the loop and verify.
base::RunLoop().Run();
EXPECT_EQ(7, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(3, observer.discovering_changed_count());
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)4, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[3]->IsActive());
}
TEST_F(BluetoothBlueZTest, StartDiscoverySession) {
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
EXPECT_EQ(0, observer.discovering_changed_count());
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_TRUE(discovery_sessions_.empty());
// Request a new discovery session.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
// Start another session. A new one should be returned in the callback, which
// in turn will destroy the previous session. Adapter should still be
// discovering and the reference count should be 1.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)2, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
// Request a new session.
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
EXPECT_TRUE(discovery_sessions_[1]->IsActive());
EXPECT_NE(discovery_sessions_[0], discovery_sessions_[1]);
// Stop the previous discovery session. The session should end but discovery
// should continue.
discovery_sessions_[0]->Stop(GetCallback(), GetErrorCallback());
base::RunLoop().Run();
EXPECT_EQ(1, observer.discovering_changed_count());
EXPECT_EQ(4, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(observer.last_discovering());
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
EXPECT_TRUE(discovery_sessions_[1]->IsActive());
// Delete the current active session. Discovery should eventually stop.
discovery_sessions_.clear();
while (observer.last_discovering())
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, observer.discovering_changed_count());
EXPECT_EQ(4, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(observer.last_discovering());
EXPECT_FALSE(adapter_->IsDiscovering());
}
TEST_F(BluetoothBlueZTest, SetDiscoveryFilterBeforeStartDiscovery) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
ASSERT_TRUE(df->Equals(*discovery_sessions_[0]->GetDiscoveryFilter()));
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_NE(nullptr, filter);
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-60, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
discovery_sessions_[0]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_FALSE(discovery_sessions_[0]->IsActive());
ASSERT_EQ(discovery_sessions_[0]->GetDiscoveryFilter(),
(BluetoothDiscoveryFilter*)nullptr);
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
TEST_F(BluetoothBlueZTest, SetDiscoveryFilterBeforeStartDiscoveryFail) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
callback_count_ = 0;
fake_bluetooth_adapter_client_->MakeSetDiscoveryFilterFail();
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(1, error_callback_count_);
error_callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)0, discovery_sessions_.size());
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
// This test queues two requests to StartDiscovery with pre set filter. This
// should result in SetDiscoveryFilter, then StartDiscovery, and SetDiscovery
// DBus calls
TEST_F(BluetoothBlueZTest, QueuedSetDiscoveryFilterBeforeStartDiscovery) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
BluetoothDiscoveryFilter* df2 =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_CLASSIC);
df2->SetRSSI(-65);
df2->AddUUID(BluetoothUUID("1002"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter2(df2);
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
// Queue two requests to start discovery session with filter.
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter2),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
// Run requests, on DBus level there should be call SetDiscoveryFilter, then
// StartDiscovery, then SetDiscoveryFilter again.
base::RunLoop().Run();
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)2, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
ASSERT_TRUE(df->Equals(*discovery_sessions_[0]->GetDiscoveryFilter()));
ASSERT_TRUE(discovery_sessions_[1]->IsActive());
ASSERT_TRUE(df2->Equals(*discovery_sessions_[1]->GetDiscoveryFilter()));
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_NE(nullptr, filter);
EXPECT_EQ("auto", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
auto uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1002"));
discovery_sessions_[0]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
discovery_sessions_[1]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_FALSE(discovery_sessions_[0]->IsActive());
ASSERT_EQ(discovery_sessions_[0]->GetDiscoveryFilter(),
(BluetoothDiscoveryFilter*)nullptr);
ASSERT_FALSE(discovery_sessions_[1]->IsActive());
ASSERT_EQ(discovery_sessions_[1]->GetDiscoveryFilter(),
(BluetoothDiscoveryFilter*)nullptr);
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
// Call StartFilteredDiscovery twice (2nd time while 1st call is still pending).
// Make the first SetDiscoveryFilter fail and the second one succeed. It should
// end up with one active discovery session.
TEST_F(BluetoothBlueZTest, QueuedSetDiscoveryFilterBeforeStartDiscoveryFail) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
BluetoothDiscoveryFilter* df2 =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_CLASSIC);
df2->SetRSSI(-65);
df2->AddUUID(BluetoothUUID("1002"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter2(df2);
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
fake_bluetooth_adapter_client_->MakeSetDiscoveryFilterFail();
// Queue two requests to start discovery session with filter.
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter2),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
// First request to SetDiscoveryFilter should fail, resulting in no session
// being created.
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
error_callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)0, discovery_sessions_.size());
base::RunLoop().Run();
// Second request should succeed
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
ASSERT_TRUE(df2->Equals(*discovery_sessions_[0]->GetDiscoveryFilter()));
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_NE(nullptr, filter);
EXPECT_EQ("bredr", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
auto uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1002"));
discovery_sessions_[0]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_FALSE(discovery_sessions_[0]->IsActive());
ASSERT_EQ(discovery_sessions_[0]->GetDiscoveryFilter(),
(BluetoothDiscoveryFilter*)nullptr);
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
TEST_F(BluetoothBlueZTest, SetDiscoveryFilterAfterStartDiscovery) {
// Test a simulated discovery session.
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestBluetoothAdapterObserver observer(adapter_);
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_TRUE(discovery_sessions_[0]->IsActive());
EXPECT_EQ(1, observer.discovering_changed_count());
observer.Reset();
auto null_instance = std::unique_ptr<BluetoothDiscoveryFilter>();
null_instance.reset();
ASSERT_EQ(discovery_sessions_[0]->GetDiscoveryFilter(), null_instance.get());
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
discovery_sessions_[0]->SetDiscoveryFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(df->Equals(*discovery_sessions_[0]->GetDiscoveryFilter()));
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_NE(nullptr, filter);
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-60, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
discovery_sessions_[0]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_FALSE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)1, discovery_sessions_.size());
ASSERT_FALSE(discovery_sessions_[0]->IsActive());
ASSERT_EQ(discovery_sessions_[0]->GetDiscoveryFilter(),
(BluetoothDiscoveryFilter*)nullptr);
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
// This unit test asserts that the basic reference counting, and filter merging
// works correctly for discovery requests done via the BluetoothAdapter.
TEST_F(BluetoothBlueZTest, SetDiscoveryFilterBeforeStartDiscoveryMultiple) {
GetAdapter();
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsPowered());
callback_count_ = 0;
TestBluetoothAdapterObserver observer(adapter_);
// Request device discovery with pre-set filter 3 times.
for (int i = 0; i < 3; i++) {
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter;
if (i == 0) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-85);
df->AddUUID(BluetoothUUID("1000"));
discovery_filter.reset(df);
} else if (i == 1) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1020"));
df->AddUUID(BluetoothUUID("1001"));
discovery_filter.reset(df);
} else if (i == 2) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-65);
df->AddUUID(BluetoothUUID("1020"));
df->AddUUID(BluetoothUUID("1003"));
discovery_filter.reset(df);
}
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
if (i == 0) {
EXPECT_EQ(1, observer.discovering_changed_count());
observer.Reset();
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-85, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
} else if (i == 1) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-85, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
} else if (i == 2) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-85, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
}
}
// the success callback should have been called 3 times and the adapter should
// be discovering.
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)3, discovery_sessions_.size());
callback_count_ = 0;
// Request to stop discovery twice.
for (int i = 0; i < 2; i++) {
discovery_sessions_[i]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
if (i == 0) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_EQ(3UL, uuids.size());
EXPECT_FALSE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
} else if (i == 1) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_EQ(2UL, uuids.size());
EXPECT_FALSE(base::ContainsValue(uuids, "1000"));
EXPECT_FALSE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
} else if (i == 2) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_EQ(0UL, uuids.size());
}
}
// The success callback should have been called 2 times and the adapter should
// still be discovering.
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_FALSE(discovery_sessions_[0]->IsActive());
EXPECT_FALSE(discovery_sessions_[1]->IsActive());
EXPECT_TRUE(discovery_sessions_[2]->IsActive());
callback_count_ = 0;
// Request device discovery 3 times.
for (int i = 0; i < 3; i++) {
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter;
if (i == 0) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-85);
df->AddUUID(BluetoothUUID("1000"));
discovery_filter.reset(df);
} else if (i == 1) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1020"));
df->AddUUID(BluetoothUUID("1001"));
discovery_filter.reset(df);
} else if (i == 2) {
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-65);
df->AddUUID(BluetoothUUID("1020"));
df->AddUUID(BluetoothUUID("1003"));
discovery_filter.reset(df);
}
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
// each result in 1 requests.
base::RunLoop().Run();
if (i == 0) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-85, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
} else if (i == 1 || i == 2) {
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-85, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
}
}
// The success callback should have been called 3 times and the adapter should
// still be discovering.
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_TRUE(adapter_->IsDiscovering());
ASSERT_EQ((size_t)6, discovery_sessions_.size());
callback_count_ = 0;
// Request to stop discovery 4 times.
for (int i = 2; i < 6; i++) {
discovery_sessions_[i]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
// filter no 2 is same as filter no 5, so removing it shouldn't cause any
// filter update
if (i != 2 && i != 5)
base::RunLoop().Run();
}
// Run only once, as there should have been one D-Bus call.
base::RunLoop().Run();
// The success callback should have been called 4 times and the adapter should
// no longer be discovering.
EXPECT_EQ(4, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(adapter_->IsDiscovering());
EXPECT_EQ(1, observer.discovering_changed_count());
// All discovery sessions should be inactive.
for (int i = 0; i < 6; i++)
EXPECT_FALSE(discovery_sessions_[i]->IsActive());
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ(nullptr, filter);
}
// This unit test asserts that filter merging logic works correctly for filtered
// discovery requests done via the BluetoothAdapter.
TEST_F(BluetoothBlueZTest, SetDiscoveryFilterMergingTest) {
GetAdapter();
adapter_->SetPowered(
true, base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
BluetoothDiscoveryFilter* df =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-15);
df->AddUUID(BluetoothUUID("1000"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df);
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
auto* filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-15, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
std::vector<std::string> uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
df = new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE);
df->SetRSSI(-60);
df->AddUUID(BluetoothUUID("1020"));
df->AddUUID(BluetoothUUID("1001"));
discovery_filter = std::unique_ptr<BluetoothDiscoveryFilter>(df);
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("le", *filter->transport);
EXPECT_EQ(-60, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
BluetoothDiscoveryFilter* df3 =
new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_CLASSIC);
df3->SetRSSI(-65);
df3->AddUUID(BluetoothUUID("1020"));
df3->AddUUID(BluetoothUUID("1003"));
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter3(df3);
adapter_->StartDiscoverySessionWithFilter(
std::move(discovery_filter3),
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("auto", *filter->transport);
EXPECT_EQ(-65, *filter->rssi);
EXPECT_EQ(nullptr, filter->pathloss.get());
uuids = *filter->uuids;
EXPECT_TRUE(base::ContainsValue(uuids, "1000"));
EXPECT_TRUE(base::ContainsValue(uuids, "1001"));
EXPECT_TRUE(base::ContainsValue(uuids, "1003"));
EXPECT_TRUE(base::ContainsValue(uuids, "1020"));
// start additionally classic scan
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
base::RunLoop().Run();
filter = fake_bluetooth_adapter_client_->GetDiscoveryFilter();
EXPECT_EQ("auto", *filter->transport);
EXPECT_EQ(nullptr, filter->rssi.get());
EXPECT_EQ(nullptr, filter->pathloss.get());
EXPECT_EQ(nullptr, filter->uuids.get());
// Request to stop discovery 4 times.
for (int i = 3; i >= 0; i--) {
discovery_sessions_[i]->Stop(
base::Bind(&BluetoothBlueZTest::Callback, base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCallback, base::Unretained(this)));
// Every session stopping would trigger filter update
base::RunLoop().Run();
}
}
TEST_F(BluetoothBlueZTest, DeviceProperties) {
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
// Verify the other device properties.
EXPECT_EQ(
base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
devices[idx]->GetNameForDisplay());
EXPECT_EQ(BluetoothDeviceType::COMPUTER, devices[idx]->GetDeviceType());
EXPECT_TRUE(devices[idx]->IsPaired());
EXPECT_FALSE(devices[idx]->IsConnected());
EXPECT_FALSE(devices[idx]->IsConnecting());
// Non HID devices are always connectable.
EXPECT_TRUE(devices[idx]->IsConnectable());
BluetoothDevice::UUIDSet uuids = devices[idx]->GetUUIDs();
EXPECT_EQ(2U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800")));
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801")));
EXPECT_EQ(BluetoothDevice::VENDOR_ID_USB, devices[idx]->GetVendorIDSource());
EXPECT_EQ(0x05ac, devices[idx]->GetVendorID());
EXPECT_EQ(0x030d, devices[idx]->GetProductID());
EXPECT_EQ(0x0306, devices[idx]->GetDeviceID());
}
TEST_F(BluetoothBlueZTest, DeviceClassChanged) {
// Simulate a change of class of a device, as sometimes occurs
// during discovery.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(BluetoothDeviceType::COMPUTER, devices[idx]->GetDeviceType());
// Install an observer; expect the DeviceChanged method to be called when
// we change the class of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
properties->bluetooth_class.ReplaceValue(0x002580);
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(BluetoothDeviceType::MOUSE, devices[idx]->GetDeviceType());
}
TEST_F(BluetoothBlueZTest, DeviceAppearance) {
// Simulate a device with appearance.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(BluetoothDeviceType::COMPUTER, devices[idx]->GetDeviceType());
// Install an observer; expect the DeviceChanged method to be called when
// we change the appearance of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
// Let the device come without bluetooth_class.
properties->appearance.ReplaceValue(0); // DeviceChanged method called
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
// Set the device appearance as keyboard (961).
properties->appearance.ReplaceValue(961); // DeviceChanged method called
properties->appearance.set_valid(true);
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(961, devices[idx]->GetAppearance());
// When discovery is over, the value should be invalidated.
properties->appearance.set_valid(false);
// DeviceChanged method called by NotifyPropertyChanged()
properties->NotifyPropertyChanged(properties->appearance.name());
EXPECT_EQ(3, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ((int)BluetoothDevice::kAppearanceNotPresent,
devices[idx]->GetAppearance());
// Change the device appearance to mouse (962).
properties->appearance.ReplaceValue(962); // DeviceChanged method called
properties->appearance.set_valid(true);
EXPECT_EQ(4, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(962, devices[idx]->GetAppearance());
// When discovery is over, the value should be invalidated.
properties->appearance.set_valid(false);
// DeviceChanged method called by NotifyPropertyChanged()
properties->NotifyPropertyChanged(properties->appearance.name());
EXPECT_EQ(5, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ((int)BluetoothDevice::kAppearanceNotPresent,
devices[idx]->GetAppearance());
}
TEST_F(BluetoothBlueZTest, DeviceTypebyAppearanceNotBluetoothClass) {
// Test device type of a device with appearance but without bluetooth class.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(BluetoothDeviceType::COMPUTER, devices[idx]->GetDeviceType());
// Install an observer; expect the DeviceChanged method to be called when
// we change the appearance of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
// Let the device come without bluetooth_class.
properties->bluetooth_class.ReplaceValue(0); // DeviceChanged method called
properties->appearance.ReplaceValue(0); // DeviceChanged method called
EXPECT_EQ(BluetoothDeviceType::UNKNOWN, devices[idx]->GetDeviceType());
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
// Set the device appearance as keyboard.
properties->appearance.ReplaceValue(961); // DeviceChanged method called
properties->appearance.set_valid(true);
EXPECT_EQ(BluetoothDeviceType::KEYBOARD, devices[idx]->GetDeviceType());
EXPECT_EQ(3, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
// When discovery is over, the value should be invalidated.
properties->appearance.set_valid(false);
// DeviceChanged method called by NotifyPropertyChanged()
properties->NotifyPropertyChanged(properties->appearance.name());
EXPECT_EQ(4, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(BluetoothDeviceType::UNKNOWN, devices[idx]->GetDeviceType());
// Change the device appearance to mouse.
properties->appearance.ReplaceValue(962); // DeviceChanged method called
properties->appearance.set_valid(true);
EXPECT_EQ(BluetoothDeviceType::MOUSE, devices[idx]->GetDeviceType());
EXPECT_EQ(5, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
// When discovery is over, the value should be invalidated.
properties->appearance.set_valid(false);
// DeviceChanged method called by NotifyPropertyChanged()
properties->NotifyPropertyChanged(properties->appearance.name());
EXPECT_EQ(6, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(BluetoothDeviceType::UNKNOWN, devices[idx]->GetDeviceType());
}
TEST_F(BluetoothBlueZTest, DeviceNameChanged) {
// Simulate a change of name of a device.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
ASSERT_EQ(
base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
devices[idx]->GetNameForDisplay());
// Install an observer; expect the DeviceChanged method to be called when
// we change the alias of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
const std::string new_name("New Device Name");
properties->name.ReplaceValue(new_name);
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(base::UTF8ToUTF16(new_name), devices[idx]->GetNameForDisplay());
}
TEST_F(BluetoothBlueZTest, DeviceAddressChanged) {
// Simulate a change of address of a device.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
ASSERT_EQ(
base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
devices[idx]->GetNameForDisplay());
// Install an observer; expect the DeviceAddressChanged method to be called
// when we change the alias of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
static const char* kNewAddress = "D9:1F:FC:11:22:33";
properties->address.ReplaceValue(kNewAddress);
EXPECT_EQ(1, observer.device_address_changed_count());
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_EQ(std::string(kNewAddress), devices[idx]->GetAddress());
}
#if defined(OS_CHROMEOS) || defined(OS_LINUX)
TEST_F(BluetoothBlueZTest, DevicePairedChanged) {
// Simulate a change of paired state of a device.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
ASSERT_EQ(true, devices[idx]->IsPaired());
// Install an observer; expect the DevicePairedChanged method to be called
// when we change the paired state of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
properties->paired.ReplaceValue(false);
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(1, observer.device_paired_changed_count());
EXPECT_FALSE(observer.device_new_paired_status());
EXPECT_EQ(devices[idx], observer.last_device());
// Change the paired state back to true to examine the consistent behavior of
// DevicePairedChanged method.
properties->paired.ReplaceValue(true);
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(2, observer.device_paired_changed_count());
EXPECT_TRUE(observer.device_new_paired_status());
EXPECT_EQ(devices[idx], observer.last_device());
}
TEST_F(BluetoothBlueZTest, DeviceMTUChanged) {
// Simulate a change of MTU of a device.
GetAdapter();
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
BluetoothDevice* device =
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
ASSERT_TRUE(device);
// Install an observer; expect DeviceMTUChanged method to be called with the
// updated MTU values.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
ASSERT_EQ(0, observer.device_mtu_changed_count());
properties->mtu.ReplaceValue(258);
EXPECT_EQ(1, observer.device_mtu_changed_count());
EXPECT_EQ(258, observer.last_mtu_value());
properties->mtu.ReplaceValue(128);
EXPECT_EQ(2, observer.device_mtu_changed_count());
EXPECT_EQ(128, observer.last_mtu_value());
}
#endif
TEST_F(BluetoothBlueZTest, DeviceUuidsChanged) {
// Simulate a change of advertised services of a device.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
BluetoothDevice::UUIDSet uuids = devices[idx]->GetUUIDs();
ASSERT_EQ(2U, uuids.size());
ASSERT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800")));
ASSERT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801")));
// Install an observer; expect the DeviceChanged method to be called when
// we change the class of the device.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
std::vector<std::string> new_uuids;
new_uuids.push_back(BluetoothUUID("1800").canonical_value());
new_uuids.push_back(BluetoothUUID("1801").canonical_value());
new_uuids.push_back("0000110c-0000-1000-8000-00805f9b34fb");
new_uuids.push_back("0000110e-0000-1000-8000-00805f9b34fb");
new_uuids.push_back("0000110a-0000-1000-8000-00805f9b34fb");
properties->uuids.ReplaceValue(new_uuids);
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
// Fetching the value should give the new one.
uuids = devices[idx]->GetUUIDs();
EXPECT_EQ(5U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1800")));
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1801")));
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110c")));
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110e")));
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("110a")));
}
TEST_F(BluetoothBlueZTest, DeviceInquiryRSSIInvalidated) {
// Simulate invalidation of inquiry RSSI of a device, as it occurs
// when discovery is finished.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
// During discovery, rssi is a valid value (-75)
properties->rssi.ReplaceValue(-75);
properties->rssi.set_valid(true);
ASSERT_EQ(-75, devices[idx]->GetInquiryRSSI().value());
properties->rssi.ReplaceValue(INT8_MAX + 1);
ASSERT_EQ(INT8_MAX, devices[idx]->GetInquiryRSSI().value());
properties->rssi.ReplaceValue(INT8_MIN - 1);
ASSERT_EQ(INT8_MIN, devices[idx]->GetInquiryRSSI().value());
// Install an observer; expect the DeviceChanged method to be called when
// we invalidate the RSSI of the device.
TestBluetoothAdapterObserver observer(adapter_);
// When discovery is over, the value should be invalidated.
properties->rssi.set_valid(false);
properties->NotifyPropertyChanged(properties->rssi.name());
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_FALSE(devices[idx]->GetInquiryRSSI());
}
TEST_F(BluetoothBlueZTest, DeviceInquiryTxPowerInvalidated) {
// Simulate invalidation of inquiry TxPower of a device, as it occurs
// when discovery is finished.
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
// During discovery, tx_power is a valid value (0)
properties->tx_power.ReplaceValue(0);
properties->tx_power.set_valid(true);
ASSERT_EQ(0, devices[idx]->GetInquiryTxPower().value());
properties->tx_power.ReplaceValue(INT8_MAX + 1);
ASSERT_EQ(INT8_MAX, devices[idx]->GetInquiryTxPower().value());
properties->tx_power.ReplaceValue(INT8_MIN - 1);
ASSERT_EQ(INT8_MIN, devices[idx]->GetInquiryTxPower().value());
// Install an observer; expect the DeviceChanged method to be called when
// we invalidate the tx_power of the device.
TestBluetoothAdapterObserver observer(adapter_);
// When discovery is over, the value should be invalidated.
properties->tx_power.set_valid(false);
properties->NotifyPropertyChanged(properties->tx_power.name());
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(devices[idx], observer.last_device());
EXPECT_FALSE(devices[idx]->GetInquiryTxPower());
}
TEST_F(BluetoothBlueZTest, ForgetDevice) {
GetAdapter();
BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
ASSERT_EQ(2U, devices.size());
int idx = GetDeviceIndexByAddress(
devices, bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_NE(-1, idx);
ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
devices[idx]->GetAddress());
std::string address = devices[idx]->GetAddress();
// Install an observer; expect the DeviceRemoved method to be called
// with the device we remove.
TestBluetoothAdapterObserver observer(adapter_);
devices[idx]->Forget(base::DoNothing(), GetErrorCallback());
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.device_removed_count());
EXPECT_EQ(address, observer.last_device_address());
// GetDevices shouldn't return the device either.
devices = adapter_->GetDevices();
ASSERT_EQ(1U, devices.size());
}
TEST_F(BluetoothBlueZTest, ForgetUnpairedDevice) {
GetAdapter();
DiscoverDevices();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
// Connect the device so it becomes trusted and remembered.
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
ASSERT_EQ(1, callback_count_);
ASSERT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(device->IsConnected());
ASSERT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath));
ASSERT_TRUE(properties->trusted.value());
// Install an observer; expect the DeviceRemoved method to be called
// with the device we remove.
TestBluetoothAdapterObserver observer(adapter_);
device->Forget(base::DoNothing(), GetErrorCallback());
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.device_removed_count());
EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress,
observer.last_device_address());
// GetDevices shouldn't return the device either.
device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
EXPECT_FALSE(device != nullptr);
}
TEST_F(BluetoothBlueZTest, ConnectPairedDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_TRUE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
// Connect without a pairing delegate; since the device is already Paired
// this should succeed and the device should become connected.
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one for connected and one for for trusted
// after connecting.
EXPECT_EQ(4, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, ConnectUnpairableDevice) {
GetAdapter();
DiscoverDevices();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
// Connect without a pairing delegate; since the device does not require
// pairing, this should succeed and the device should become connected.
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one for connected, one for for trusted after
// connection, and one for the reconnect mode (IsConnectable).
EXPECT_EQ(5, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath));
EXPECT_TRUE(properties->trusted.value());
// Verify is a HID device and is not connectable.
BluetoothDevice::UUIDSet uuids = device->GetUUIDs();
EXPECT_EQ(1U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124")));
EXPECT_FALSE(device->IsConnectable());
}
TEST_F(BluetoothBlueZTest, ConnectConnectedDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_TRUE(device->IsPaired());
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
ASSERT_EQ(1, callback_count_);
ASSERT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(device->IsConnected());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
// Connect again; since the device is already Connected, this shouldn't do
// anything to initiate the connection.
TestBluetoothAdapterObserver observer(adapter_);
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// The observer will be called because Connecting will toggle true and false,
// and the trusted property will be updated to true.
EXPECT_EQ(3, observer.device_changed_count());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(2, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(2, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, ConnectDeviceFails) {
GetAdapter();
DiscoverDevices();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
// Connect without a pairing delegate; since the device requires pairing,
// this should fail with an error.
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_);
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
// Tests that discovery is unpaused if the device gets removed during a
// connection.
TEST_F(BluetoothBlueZTest, RemoveDeviceDuringConnection) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
fake_bluetooth_device_client_->LeaveConnectionsPending();
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
// We pause discovery before connecting.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_FALSE(device->IsConnected());
EXPECT_TRUE(device->IsConnecting());
// Install an observer; expect the DeviceRemoved method to be called
// with the device we remove.
TestBluetoothAdapterObserver observer(adapter_);
device->Forget(base::DoNothing(), GetErrorCallback());
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.device_removed_count());
// If the device gets removed, we should still unpause discovery.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, DisconnectDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_TRUE(device->IsPaired());
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
ASSERT_EQ(1, callback_count_);
ASSERT_EQ(0, error_callback_count_);
callback_count_ = 0;
ASSERT_TRUE(device->IsConnected());
ASSERT_FALSE(device->IsConnecting());
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
// Disconnect the device, we should see the observer method fire and the
// device get dropped.
TestBluetoothAdapterObserver observer(adapter_);
device->Disconnect(GetCallback(), GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_FALSE(device->IsConnected());
}
TEST_F(BluetoothBlueZTest, DisconnectUnconnectedDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_TRUE(device->IsPaired());
ASSERT_FALSE(device->IsConnected());
// Disconnect the device, we should see the observer method fire and the
// device get dropped.
TestBluetoothAdapterObserver observer(adapter_);
device->Disconnect(GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
}
TEST_F(BluetoothBlueZTest, PairTrustedDevice) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::
kConnectedTrustedNotPairedDevicePath));
BluetoothDevice* device =
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::
kConnectedTrustedNotPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::
kConnectedTrustedNotPairedDevicePath));
EXPECT_FALSE(properties->paired.value());
EXPECT_TRUE(properties->trusted.value());
ASSERT_FALSE(device->IsPaired());
// The |kConnectedTrustedNotPairedDevicePath| requests a passkey confirmation.
// Obs.: This is the flow when CrOS triggers pairing with a iOS device.
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
device->Pair(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
// Confirm the passkey.
device->ConfirmPairing();
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Make sure the paired property has been set to true.
properties = fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath));
EXPECT_TRUE(properties->paired.value());
}
TEST_F(BluetoothBlueZTest, PairAlreadyPairedDevice) {
GetAdapter();
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
ASSERT_TRUE(device != nullptr);
// On the DBus level a device can be trusted but not paired.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
EXPECT_TRUE(properties->paired.value());
EXPECT_TRUE(properties->trusted.value());
ASSERT_TRUE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
device->Pair(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
// For already paired devices a call to |Pair| should succeed without calling
// the pairing delegate.
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
TEST_F(BluetoothBlueZTest, PairLegacyAutopair) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// The Legacy Autopair device requires no PIN or Passkey to pair because
// the daemon provides 0000 to the device for us.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_TRUE(device->IsConnecting());
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired,
// two for trusted (after pairing and connection), and one for the reconnect
// mode (IsConnectable).
EXPECT_EQ(7, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Verify is a HID device and is connectable.
BluetoothDevice::UUIDSet uuids = device->GetUUIDs();
EXPECT_EQ(1U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124")));
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairDisplayPinCode) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Requires that we display a randomly generated PIN on the screen.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kDisplayPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.display_pincode_count_);
EXPECT_EQ("123456", pairing_delegate.last_pincode_);
EXPECT_TRUE(device->IsConnecting());
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired,
// two for trusted (after pairing and connection), and one for the reconnect
// mode (IsConnectable).
EXPECT_EQ(7, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Verify is a HID device and is connectable.
BluetoothDevice::UUIDSet uuids = device->GetUUIDs();
EXPECT_EQ(1U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124")));
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairDisplayPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Requires that we display a randomly generated Passkey on the screen,
// and notifies us as it's typed in.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kDisplayPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
// One call for DisplayPasskey() and one for KeysEntered().
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.display_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
EXPECT_EQ(1, pairing_delegate.keys_entered_count_);
EXPECT_EQ(0U, pairing_delegate.last_entered_);
EXPECT_TRUE(device->IsConnecting());
// One call to KeysEntered() for each key, including [enter].
for (int i = 1; i <= 7; ++i) {
base::RunLoop().Run();
EXPECT_EQ(2 + i, pairing_delegate.call_count_);
EXPECT_EQ(1 + i, pairing_delegate.keys_entered_count_);
EXPECT_EQ(static_cast<uint32_t>(i), pairing_delegate.last_entered_);
}
base::RunLoop().Run();
// 8 KeysEntered notifications (0 to 7, inclusive) and one aditional call for
// DisplayPasskey().
EXPECT_EQ(9, pairing_delegate.call_count_);
EXPECT_EQ(8, pairing_delegate.keys_entered_count_);
EXPECT_EQ(7U, pairing_delegate.last_entered_);
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired,
// two for trusted (after pairing and connection), and one for the reconnect
// mode (IsConnectable).
EXPECT_EQ(7, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Verify is a HID device.
BluetoothDevice::UUIDSet uuids = device->GetUUIDs();
EXPECT_EQ(1U, uuids.size());
EXPECT_TRUE(base::ContainsKey(uuids, BluetoothUUID("1124")));
// And usually not connectable.
EXPECT_FALSE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kDisplayPasskeyPath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairRequestPinCode) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Requires that the user enters a PIN for them.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_pincode_count_);
EXPECT_TRUE(device->IsConnecting());
// Set the PIN.
device->SetPinCode("1234");
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired and
// two for trusted (after pairing and connection).
EXPECT_EQ(6, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Verify is not a HID device.
BluetoothDevice::UUIDSet uuids = device->GetUUIDs();
EXPECT_EQ(0U, uuids.size());
// Non HID devices are always connectable.
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairConfirmPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Requests that we confirm a displayed passkey.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
EXPECT_TRUE(device->IsConnecting());
// Confirm the passkey.
device->ConfirmPairing();
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired and
// two for trusted (after pairing and connection).
EXPECT_EQ(6, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Non HID devices are always connectable.
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairRequestPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Requires that the user enters a Passkey, this would be some kind of
// device that has a display, but doesn't use "just works" - maybe a car?
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
EXPECT_TRUE(device->IsConnecting());
// Set the Passkey.
device->SetPasskey(1234);
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired and
// two for trusted (after pairing and connection).
EXPECT_EQ(6, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Non HID devices are always connectable.
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairJustWorks) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Uses just-works pairing, since this is an outgoing pairing, no delegate
// interaction is required.
BluetoothDevice* device =
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Two changes for connecting, one change for connected, one for paired and
// two for trusted (after pairing and connection).
EXPECT_EQ(6, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Non HID devices are always connectable.
EXPECT_TRUE(device->IsConnectable());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairUnpairableDeviceFails) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevice(bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kUnpairableDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_TRUE(device->IsConnecting());
// Run the loop to get the error..
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_);
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingFails) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevice(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress);
// The vanishing device times out during pairing
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_TRUE(device->IsConnecting());
// Run the loop to get the error..
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_TIMEOUT, last_connect_error_);
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingFailsAtConnection) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Everything seems to go according to plan with the unconnectable device;
// it pairs, but then you can't make connections to it after.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_TRUE(device->IsConnecting());
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_FAILED, last_connect_error_);
// Two changes for connecting, one for paired and one for trusted after
// pairing. The device should not be connected.
EXPECT_EQ(4, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
// Connect after pair.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
EXPECT_TRUE(device->IsPaired());
// Make sure the trusted property has been set to true still (since pairing
// worked).
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kUnconnectableDevicePath));
EXPECT_TRUE(properties->trusted.value());
}
TEST_F(BluetoothBlueZTest, PairingRejectedAtPinCode) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Reject the pairing after we receive a request for the PIN code.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_pincode_count_);
EXPECT_TRUE(device->IsConnecting());
// Reject the pairing.
device->RejectPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_REJECTED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingCancelledAtPinCode) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Cancel the pairing after we receive a request for the PIN code.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_pincode_count_);
EXPECT_TRUE(device->IsConnecting());
// Cancel the pairing.
device->CancelPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_CANCELED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingRejectedAtPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Reject the pairing after we receive a request for the passkey.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
EXPECT_TRUE(device->IsConnecting());
// Reject the pairing.
device->RejectPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_REJECTED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingCancelledAtPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Cancel the pairing after we receive a request for the passkey.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
EXPECT_TRUE(device->IsConnecting());
// Cancel the pairing.
device->CancelPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_CANCELED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingRejectedAtConfirmation) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Reject the pairing after we receive a request for passkey confirmation.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
EXPECT_TRUE(device->IsConnecting());
// Reject the pairing.
device->RejectPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_REJECTED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingCancelledAtConfirmation) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Cancel the pairing after we receive a request for the passkey.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
EXPECT_TRUE(device->IsConnecting());
// Cancel the pairing.
device->CancelPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_CANCELED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, PairingCancelledInFlight) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
DiscoverDevices();
// Cancel the pairing while we're waiting for the remote host.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
TestPairingDelegate pairing_delegate;
device->Connect(&pairing_delegate, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(0, pairing_delegate.call_count_);
EXPECT_TRUE(device->IsConnecting());
// Cancel the pairing.
device->CancelPairing();
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(BluetoothDevice::ERROR_AUTH_CANCELED, last_connect_error_);
// Should be no changes except connecting going true and false.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_FALSE(device->IsConnected());
EXPECT_FALSE(device->IsConnecting());
EXPECT_FALSE(device->IsPaired());
// No connection.
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(0, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, IncomingPairRequestPinCode) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Requires that we provide a PIN code.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_pincode_count_);
// Set the PIN.
device->SetPinCode("1234");
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// One change for paired, and one for trusted.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsPaired());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
ASSERT_TRUE(properties->trusted.value());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairConfirmPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Requests that we confirm a displayed passkey.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
// Confirm the passkey.
device->ConfirmPairing();
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// One change for paired, and one for trusted.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsPaired());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
ASSERT_TRUE(properties->trusted.value());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairRequestPasskey) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Requests that we provide a Passkey.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
// Set the Passkey.
device->SetPasskey(1234);
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// One change for paired, and one for trusted.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsPaired());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
ASSERT_TRUE(properties->trusted.value());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairJustWorks) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Uses just-works pairing so, sinec this an incoming pairing, require
// authorization from the user.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
BluetoothDevice* device =
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true,
GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.authorize_pairing_count_);
// Confirm the pairing.
device->ConfirmPairing();
base::RunLoop().Run();
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// One change for paired, and one for trusted.
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->IsPaired());
// Make sure the trusted property has been set to true.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
ASSERT_TRUE(properties->trusted.value());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairRequestPinCodeWithoutDelegate) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
// Requires that we provide a PIN Code, without a pairing delegate,
// that will be rejected.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(bluetooth_device::kErrorAuthenticationRejected, last_client_error_);
// No changes should be observer.
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsPaired());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairConfirmPasskeyWithoutDelegate) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
// Requests that we confirm a displayed passkey, without a pairing delegate,
// that will be rejected.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(bluetooth_device::kErrorAuthenticationRejected, last_client_error_);
// No changes should be observer.
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsPaired());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairRequestPasskeyWithoutDelegate) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
// Requests that we provide a displayed passkey, without a pairing delegate,
// that will be rejected.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(bluetooth_device::kErrorAuthenticationRejected, last_client_error_);
// No changes should be observer.
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsPaired());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, IncomingPairJustWorksWithoutDelegate) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
// Uses just-works pairing and thus requires authorization for incoming
// pairings, without a pairing delegate, that will be rejected.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
BluetoothDevice* device =
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true,
GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_);
EXPECT_EQ(bluetooth_device::kErrorAuthenticationRejected, last_client_error_);
// No changes should be observer.
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsPaired());
// No pairing context should remain on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
}
TEST_F(BluetoothBlueZTest, RemovePairingDelegateDuringPairing) {
fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
GetAdapter();
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Requests that we provide a Passkey.
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
ASSERT_TRUE(device != nullptr);
ASSERT_FALSE(device->IsPaired());
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_device_client_->SimulatePairing(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
true, GetCallback(), base::Bind(&BluetoothBlueZTest::DBusErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
// A pairing context should now be set on the device.
BluetoothDeviceBlueZ* device_bluez =
static_cast<BluetoothDeviceBlueZ*>(device);
ASSERT_TRUE(device_bluez->GetPairing() != nullptr);
// Removing the pairing delegate should remove that pairing context.
adapter_->RemovePairingDelegate(&pairing_delegate);
EXPECT_TRUE(device_bluez->GetPairing() == nullptr);
// Set the Passkey, this should now have no effect since the pairing has
// been, in-effect, cancelled
device->SetPasskey(1234);
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.device_changed_count());
EXPECT_FALSE(device->IsPaired());
}
TEST_F(BluetoothBlueZTest, DeviceId) {
GetAdapter();
// Use the built-in paired device for this test, grab its Properties
// structure so we can adjust the underlying modalias property.
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
ASSERT_TRUE(device != nullptr);
ASSERT_TRUE(properties != nullptr);
// Valid USB IF-assigned identifier.
ASSERT_EQ("usb:v05ACp030Dd0306", properties->modalias.value());
EXPECT_EQ(BluetoothDevice::VENDOR_ID_USB, device->GetVendorIDSource());
EXPECT_EQ(0x05ac, device->GetVendorID());
EXPECT_EQ(0x030d, device->GetProductID());
EXPECT_EQ(0x0306, device->GetDeviceID());
// Valid Bluetooth SIG-assigned identifier.
properties->modalias.ReplaceValue("bluetooth:v00E0p2400d0400");
EXPECT_EQ(BluetoothDevice::VENDOR_ID_BLUETOOTH, device->GetVendorIDSource());
EXPECT_EQ(0x00e0, device->GetVendorID());
EXPECT_EQ(0x2400, device->GetProductID());
EXPECT_EQ(0x0400, device->GetDeviceID());
// Invalid USB IF-assigned identifier.
properties->modalias.ReplaceValue("usb:x00E0p2400d0400");
EXPECT_EQ(BluetoothDevice::VENDOR_ID_UNKNOWN, device->GetVendorIDSource());
EXPECT_EQ(0, device->GetVendorID());
EXPECT_EQ(0, device->GetProductID());
EXPECT_EQ(0, device->GetDeviceID());
// Invalid Bluetooth SIG-assigned identifier.
properties->modalias.ReplaceValue("bluetooth:x00E0p2400d0400");
EXPECT_EQ(BluetoothDevice::VENDOR_ID_UNKNOWN, device->GetVendorIDSource());
EXPECT_EQ(0, device->GetVendorID());
EXPECT_EQ(0, device->GetProductID());
EXPECT_EQ(0, device->GetDeviceID());
// Unknown vendor specification identifier.
properties->modalias.ReplaceValue("chrome:v00E0p2400d0400");
EXPECT_EQ(BluetoothDevice::VENDOR_ID_UNKNOWN, device->GetVendorIDSource());
EXPECT_EQ(0, device->GetVendorID());
EXPECT_EQ(0, device->GetProductID());
EXPECT_EQ(0, device->GetDeviceID());
}
TEST_F(BluetoothBlueZTest, GetConnectionInfoForDisconnectedDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
// Calling GetConnectionInfo for an unconnected device should return a result
// in which all fields are filled with BluetoothDevice::kUnknownPower.
BluetoothDevice::ConnectionInfo conn_info(0, 0, 0);
device->GetConnectionInfo(base::Bind(&SaveConnectionInfo, &conn_info));
int unknown_power = BluetoothDevice::kUnknownPower;
EXPECT_NE(0, unknown_power);
EXPECT_EQ(unknown_power, conn_info.rssi);
EXPECT_EQ(unknown_power, conn_info.transmit_power);
EXPECT_EQ(unknown_power, conn_info.max_transmit_power);
}
TEST_F(BluetoothBlueZTest, GetConnectionInfoForConnectedDevice) {
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
device->Connect(nullptr, GetCallback(),
base::Bind(&BluetoothBlueZTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_TRUE(device->IsConnected());
// Calling GetConnectionInfo for a connected device should return valid
// results.
fake_bluetooth_device_client_->UpdateConnectionInfo(-10, 3, 4);
BluetoothDevice::ConnectionInfo conn_info;
device->GetConnectionInfo(base::Bind(&SaveConnectionInfo, &conn_info));
EXPECT_EQ(-10, conn_info.rssi);
EXPECT_EQ(3, conn_info.transmit_power);
EXPECT_EQ(4, conn_info.max_transmit_power);
// Pause discovery to connect without pair.
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetPauseCount());
EXPECT_EQ(1, fake_bluetooth_adapter_client_->GetUnpauseCount());
}
TEST_F(BluetoothBlueZTest, GetDiscoverableTimeout) {
constexpr uint32_t kShortDiscoverableTimeout = 30;
constexpr uint32_t kLongDiscoverableTimeout = 240;
GetAdapter();
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
fake_bluetooth_adapter_client_->SetDiscoverableTimeout(
kShortDiscoverableTimeout);
EXPECT_EQ(kShortDiscoverableTimeout, adapter_bluez->GetDiscoverableTimeout());
fake_bluetooth_adapter_client_->SetDiscoverableTimeout(
kLongDiscoverableTimeout);
EXPECT_EQ(kLongDiscoverableTimeout, adapter_bluez->GetDiscoverableTimeout());
}
// Verifies Shutdown shuts down the adapter as expected.
TEST_F(BluetoothBlueZTest, Shutdown) {
// Set up adapter. Set powered & discoverable, start discovery.
GetAdapter();
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
adapter_->SetDiscoverable(true, GetCallback(), GetErrorCallback());
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
base::RunLoop().Run();
ASSERT_EQ(3, callback_count_);
ASSERT_EQ(0, error_callback_count_);
callback_count_ = 0;
TestPairingDelegate pairing_delegate;
adapter_->AddPairingDelegate(
&pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
// Validate running adapter state.
EXPECT_NE("", adapter_->GetAddress());
EXPECT_NE("", adapter_->GetName());
EXPECT_TRUE(adapter_->IsInitialized());
EXPECT_TRUE(adapter_->IsPresent());
EXPECT_TRUE(adapter_->IsPowered());
EXPECT_TRUE(adapter_->IsDiscoverable());
EXPECT_TRUE(adapter_->IsDiscovering());
EXPECT_EQ(2U, adapter_->GetDevices().size());
EXPECT_NE(nullptr,
adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
EXPECT_NE(dbus::ObjectPath(""),
static_cast<BluetoothAdapterBlueZ*>(adapter_.get())->object_path());
// Shutdown
adapter_->Shutdown();
// Validate post shutdown state by calling all BluetoothAdapterBlueZ
// members, in declaration order:
adapter_->Shutdown();
// DeleteOnCorrectThread omitted as we don't want to delete in this test.
{
TestBluetoothAdapterObserver observer(adapter_); // Calls AddObserver
} // ~TestBluetoothAdapterObserver calls RemoveObserver.
EXPECT_EQ("", adapter_->GetAddress());
EXPECT_EQ("", adapter_->GetName());
adapter_->SetName("", GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_--) << "SetName error";
EXPECT_TRUE(adapter_->IsInitialized());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
adapter_->SetPowered(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_--) << "SetPowered error";
EXPECT_FALSE(adapter_->IsDiscoverable());
adapter_->SetDiscoverable(true, GetCallback(), GetErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1, error_callback_count_--) << "SetDiscoverable error";
EXPECT_FALSE(adapter_->IsDiscovering());
// CreateRfcommService will DCHECK after Shutdown().
// CreateL2capService will DCHECK after Shutdown().
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
EXPECT_EQ(nullptr, adapter_bluez->GetDeviceWithPath(dbus::ObjectPath("")));
// Notify methods presume objects exist that are owned by the adapter and
// destroyed in Shutdown(). Mocks are not attempted here that won't exist,
// as verified below by EXPECT_EQ(0U, adapter_->GetDevices().size());
// NotifyDeviceChanged
// NotifyGattServiceAdded
// NotifyGattServiceRemoved
// NotifyGattServiceChanged
// NotifyGattDiscoveryComplete
// NotifyGattCharacteristicAdded
// NotifyGattCharacteristicRemoved
// NotifyGattDescriptorAdded
// NotifyGattDescriptorRemoved
// NotifyGattCharacteristicValueChanged
// NotifyGattDescriptorValueChanged
EXPECT_EQ(dbus::ObjectPath(""), adapter_bluez->object_path());
adapter_profile_ = nullptr;
FakeBluetoothProfileServiceProviderDelegate profile_delegate;
adapter_bluez->UseProfile(
BluetoothUUID(), dbus::ObjectPath(""),
bluez::BluetoothProfileManagerClient::Options(), &profile_delegate,
base::Bind(&BluetoothBlueZTest::ProfileRegisteredCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCompletionCallback,
base::Unretained(this)));
EXPECT_FALSE(adapter_profile_) << "UseProfile error";
EXPECT_EQ(0, callback_count_) << "UseProfile error";
EXPECT_EQ(1, error_callback_count_--) << "UseProfile error";
// Protected and private methods:
adapter_bluez->RemovePairingDelegateInternal(&pairing_delegate);
// AdapterAdded() invalid post Shutdown because it calls SetAdapter.
adapter_bluez->AdapterRemoved(dbus::ObjectPath("x"));
adapter_bluez->AdapterPropertyChanged(dbus::ObjectPath("x"), "");
adapter_bluez->DeviceAdded(dbus::ObjectPath(""));
adapter_bluez->DeviceRemoved(dbus::ObjectPath(""));
adapter_bluez->DevicePropertyChanged(dbus::ObjectPath(""), "");
adapter_bluez->InputPropertyChanged(dbus::ObjectPath(""), "");
// bluez::BluetoothAgentServiceProvider::Delegate omitted, dbus will be
// shutdown,
// with the exception of Released.
adapter_bluez->Released();
adapter_bluez->OnRegisterAgent();
adapter_bluez->OnRegisterAgentError("", "");
adapter_bluez->OnRequestDefaultAgent();
adapter_bluez->OnRequestDefaultAgentError("", "");
// GetPairing will DCHECK after Shutdown().
// SetAdapter will DCHECK after Shutdown().
// SetDefaultAdapterName will DCHECK after Shutdown().
// RemoveAdapter will DCHECK after Shutdown().
adapter_bluez->NotifyAdapterPoweredChanged(false);
adapter_bluez->DiscoverableChanged(false);
adapter_bluez->DiscoveringChanged(false);
adapter_bluez->PresentChanged(false);
adapter_bluez->OnSetDiscoverable(GetCallback(), GetErrorCallback(), true);
EXPECT_EQ(0, callback_count_) << "OnSetDiscoverable error";
EXPECT_EQ(1, error_callback_count_--) << "OnSetDiscoverable error";
adapter_bluez->OnPropertyChangeCompleted(GetCallback(), GetErrorCallback(),
true);
EXPECT_EQ(0, callback_count_) << "OnPropertyChangeCompleted error";
EXPECT_EQ(1, error_callback_count_--) << "OnPropertyChangeCompleted error";
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
EXPECT_EQ(0, callback_count_) << "AddDiscoverySession error";
EXPECT_EQ(1, error_callback_count_--) << "AddDiscoverySession error";
adapter_bluez->RemoveDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
EXPECT_EQ(0, callback_count_) << "RemoveDiscoverySession error";
EXPECT_EQ(1, error_callback_count_--) << "RemoveDiscoverySession error";
// OnStartDiscovery tested in Shutdown_OnStartDiscovery
// OnStartDiscoveryError tested in Shutdown_OnStartDiscoveryError
// OnStopDiscovery tested in Shutdown_OnStopDiscovery
// OnStopDiscoveryError tested in Shutdown_OnStopDiscoveryError
adapter_profile_ = nullptr;
// OnRegisterProfile SetProfileDelegate, OnRegisterProfileError, require
// UseProfile to be set first, do so again here just before calling them.
adapter_bluez->UseProfile(
BluetoothUUID(), dbus::ObjectPath(""),
bluez::BluetoothProfileManagerClient::Options(), &profile_delegate,
base::Bind(&BluetoothBlueZTest::ProfileRegisteredCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCompletionCallback,
base::Unretained(this)));
EXPECT_FALSE(adapter_profile_) << "UseProfile error";
EXPECT_EQ(0, callback_count_) << "UseProfile error";
EXPECT_EQ(1, error_callback_count_--) << "UseProfile error";
adapter_bluez->SetProfileDelegate(
BluetoothUUID(), dbus::ObjectPath(""), &profile_delegate,
base::Bind(&BluetoothBlueZTest::ProfileRegisteredCallback,
base::Unretained(this)),
base::Bind(&BluetoothBlueZTest::ErrorCompletionCallback,
base::Unretained(this)));
EXPECT_EQ(0, callback_count_) << "SetProfileDelegate error";
EXPECT_EQ(1, error_callback_count_--) << "SetProfileDelegate error";
adapter_bluez->OnRegisterProfileError(BluetoothUUID(), "", "");
EXPECT_EQ(0, callback_count_) << "OnRegisterProfileError error";
EXPECT_EQ(0, error_callback_count_) << "OnRegisterProfileError error";
adapter_bluez->ProcessQueuedDiscoveryRequests();
// From BluetoothAdapater:
adapter_->StartDiscoverySession(
base::Bind(&BluetoothBlueZTest::DiscoverySessionCallback,
base::Unretained(this)),
GetErrorCallback());
EXPECT_EQ(0, callback_count_) << "StartDiscoverySession error";
EXPECT_EQ(1, error_callback_count_--) << "StartDiscoverySession error";
EXPECT_EQ(0U, adapter_->GetDevices().size());
EXPECT_EQ(nullptr,
adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
TestPairingDelegate pairing_delegate2;
adapter_->AddPairingDelegate(
&pairing_delegate2, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
adapter_->RemovePairingDelegate(&pairing_delegate2);
}
// Verifies post-Shutdown of discovery sessions and OnStartDiscovery.
TEST_F(BluetoothBlueZTest, Shutdown_OnStartDiscovery) {
const int kNumberOfDiscoverySessions = 10;
GetAdapter();
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
for (int i = 0; i < kNumberOfDiscoverySessions; i++) {
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
}
adapter_->Shutdown();
adapter_bluez->OnStartDiscovery(GetCallback(), GetDiscoveryErrorCallback());
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(kNumberOfDiscoverySessions, error_callback_count_);
}
// Verifies post-Shutdown of discovery sessions and OnStartDiscoveryError.
TEST_F(BluetoothBlueZTest, Shutdown_OnStartDiscoveryError) {
const int kNumberOfDiscoverySessions = 10;
GetAdapter();
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
for (int i = 0; i < kNumberOfDiscoverySessions; i++) {
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
}
adapter_->Shutdown();
adapter_bluez->OnStartDiscoveryError(GetCallback(),
GetDiscoveryErrorCallback(), "", "");
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(kNumberOfDiscoverySessions, error_callback_count_);
}
// Verifies post-Shutdown of discovery sessions and OnStartDiscovery.
TEST_F(BluetoothBlueZTest, Shutdown_OnStopDiscovery) {
const int kNumberOfDiscoverySessions = 10;
GetAdapter();
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
// In order to queue up discovery sessions before an OnStopDiscovery call
// RemoveDiscoverySession must be called, so Add, Start, and Remove:
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
adapter_bluez->OnStartDiscovery(GetCallback(), GetDiscoveryErrorCallback());
adapter_bluez->RemoveDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
callback_count_ = 0;
error_callback_count_ = 0;
// Can now queue discovery sessions while waiting for OnStopDiscovery.
for (int i = 0; i < kNumberOfDiscoverySessions; i++) {
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
}
adapter_->Shutdown();
adapter_bluez->OnStopDiscovery(GetCallback());
// 1 successful stopped discovery from RemoveDiscoverySession, and
// kNumberOfDiscoverySessions errors from AddDiscoverySession/OnStopDiscovery.
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(kNumberOfDiscoverySessions, error_callback_count_);
}
// Verifies post-Shutdown of discovery sessions and OnStopDiscoveryError.
TEST_F(BluetoothBlueZTest, Shutdown_OnStopDiscoveryError) {
const int kNumberOfDiscoverySessions = 10;
GetAdapter();
BluetoothAdapterBlueZ* adapter_bluez =
static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
// In order to queue up discovery sessions before an OnStopDiscoveryError call
// RemoveDiscoverySession must be called, so Add, Start, and Remove:
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
adapter_bluez->OnStartDiscovery(GetCallback(), GetDiscoveryErrorCallback());
adapter_bluez->RemoveDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
callback_count_ = 0;
error_callback_count_ = 0;
// Can now queue discovery sessions while waiting for OnStopDiscoveryError.
for (int i = 0; i < kNumberOfDiscoverySessions; i++) {
adapter_bluez->AddDiscoverySession(nullptr, GetCallback(),
GetDiscoveryErrorCallback());
}
adapter_->Shutdown();
adapter_bluez->OnStopDiscoveryError(GetDiscoveryErrorCallback(), "", "");
// 1 error reported to RemoveDiscoverySession because of OnStopDiscoveryError,
// and kNumberOfDiscoverySessions errors queued with AddDiscoverySession.
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(1 + kNumberOfDiscoverySessions, error_callback_count_);
}
TEST_F(BluetoothBlueZTest, ManufacturerDataChanged) {
const BluetoothDevice::ManufacturerId kManufacturerId1 = 0x1234;
const BluetoothDevice::ManufacturerId kManufacturerId2 = 0x2345;
const BluetoothDevice::ManufacturerId kManufacturerId3 = 0x3456;
// Simulate a change of manufacturer data of a device.
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
// Install an observer; expect the DeviceChanged method to be called
// when we change the service data.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
properties->manufacturer_data.set_valid(true);
// Check that ManufacturerDataChanged is correctly invoke.
properties->manufacturer_data.ReplaceValue({{kManufacturerId1, {1, 2, 3}}});
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_EQ(
BluetoothDevice::ManufacturerDataMap({{kManufacturerId1, {1, 2, 3}}}),
device->GetManufacturerData());
EXPECT_EQ(BluetoothDevice::ManufacturerIDSet({kManufacturerId1}),
device->GetManufacturerDataIDs());
EXPECT_EQ(std::vector<uint8_t>({1, 2, 3}),
*(device->GetManufacturerDataForID(kManufacturerId1)));
// Check that we can update service data with same uuid / add more uuid.
properties->manufacturer_data.ReplaceValue(
{{kManufacturerId1, {3, 2, 1}}, {kManufacturerId2, {1}}});
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_EQ(BluetoothDevice::ManufacturerDataMap(
{{kManufacturerId1, {3, 2, 1}}, {kManufacturerId2, {1}}}),
device->GetManufacturerData());
EXPECT_EQ(
BluetoothDevice::ManufacturerIDSet({kManufacturerId1, kManufacturerId2}),
device->GetManufacturerDataIDs());
EXPECT_EQ(std::vector<uint8_t>({3, 2, 1}),
*(device->GetManufacturerDataForID(kManufacturerId1)));
EXPECT_EQ(std::vector<uint8_t>({1}),
*(device->GetManufacturerDataForID(kManufacturerId2)));
// Check that we can remove uuid / change uuid with same data.
properties->manufacturer_data.ReplaceValue({{kManufacturerId3, {3, 2, 1}}});
EXPECT_EQ(3, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_EQ(
BluetoothDevice::ManufacturerDataMap({{kManufacturerId3, {3, 2, 1}}}),
device->GetManufacturerData());
EXPECT_EQ(BluetoothDevice::ManufacturerIDSet({kManufacturerId3}),
device->GetManufacturerDataIDs());
EXPECT_EQ(std::vector<uint8_t>({3, 2, 1}),
*(device->GetManufacturerDataForID(kManufacturerId3)));
EXPECT_EQ(nullptr, device->GetManufacturerDataForID(kManufacturerId1));
EXPECT_EQ(nullptr, device->GetManufacturerDataForID(kManufacturerId2));
}
TEST_F(BluetoothBlueZTest, AdvertisingDataFlagsChanged) {
// Simulate a change of advertising data flags of a device.
GetAdapter();
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
// Install an observer; expect the DeviceChanged method to be called
// when we change the service data.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
properties->advertising_data_flags.set_valid(true);
// Check that AdvertisingDataFlagsChanged is correctly invoke.
properties->advertising_data_flags.ReplaceValue(std::vector<uint8_t>({0x12}));
EXPECT_EQ(1, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
EXPECT_EQ(0x12u, device->GetAdvertisingDataFlags().value());
// Check that we can update advertising data flags.
properties->advertising_data_flags.ReplaceValue(std::vector<uint8_t>({0x23}));
EXPECT_EQ(2, observer.device_changed_count());
EXPECT_EQ(device, observer.last_device());
EXPECT_TRUE(device->GetAdvertisingDataFlags().has_value());
EXPECT_EQ(0x23u, device->GetAdvertisingDataFlags().value());
}
TEST_F(BluetoothBlueZTest, SetConnectionLatency) {
GetAdapter();
DiscoverDevices();
// SetConnectionLatency is supported on LE devices.
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath));
properties->type.ReplaceValue(BluetoothDeviceClient::kTypeLe);
BluetoothDevice* device = adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
ASSERT_TRUE(device);
device->SetConnectionLatency(
BluetoothDevice::ConnectionLatency::CONNECTION_LATENCY_LOW, GetCallback(),
GetErrorCallback());
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
device->SetConnectionLatency(
BluetoothDevice::ConnectionLatency::CONNECTION_LATENCY_HIGH,
GetCallback(), GetErrorCallback());
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// Dual mode devices should be supported as well.
properties->type.ReplaceValue(BluetoothDeviceClient::kTypeDual);
device->SetConnectionLatency(
BluetoothDevice::ConnectionLatency::CONNECTION_LATENCY_MEDIUM,
GetCallback(), GetErrorCallback());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(0, error_callback_count_);
// This API is not supported for BR/EDR devices.
properties->type.ReplaceValue(BluetoothDeviceClient::kTypeBredr);
device->SetConnectionLatency(
BluetoothDevice::ConnectionLatency::CONNECTION_LATENCY_MEDIUM,
GetCallback(), GetErrorCallback());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(1, error_callback_count_);
// Return an error if the type is not valid.
properties->type.set_valid(false);
device->SetConnectionLatency(
BluetoothDevice::ConnectionLatency::CONNECTION_LATENCY_MEDIUM,
GetCallback(), GetErrorCallback());
EXPECT_EQ(3, callback_count_);
EXPECT_EQ(2, error_callback_count_);
}
} // namespace bluez