| // Copyright (c) 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 "base/message_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chromeos/dbus/fake_bluetooth_adapter_client.h" |
| #include "chromeos/dbus/fake_bluetooth_device_client.h" |
| #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h" |
| #include "dbus/object_path.h" |
| #include "device/bluetooth/bluetooth_adapter.h" |
| #include "device/bluetooth/bluetooth_adapter_experimental_chromeos.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| #include "device/bluetooth/bluetooth_device.h" |
| #include "device/bluetooth/bluetooth_device_experimental_chromeos.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using device::BluetoothAdapter; |
| using device::BluetoothAdapterFactory; |
| using device::BluetoothDevice; |
| |
| namespace chromeos { |
| |
| class TestObserver : public BluetoothAdapter::Observer { |
| public: |
| TestObserver(scoped_refptr<BluetoothAdapter> adapter) |
| : present_changed_count_(0), |
| powered_changed_count_(0), |
| discovering_changed_count_(0), |
| last_present_(false), |
| last_powered_(false), |
| last_discovering_(false), |
| device_added_count_(0), |
| device_changed_count_(0), |
| device_removed_count_(0), |
| last_device_(NULL), |
| adapter_(adapter) { |
| } |
| virtual ~TestObserver() {} |
| |
| virtual void AdapterPresentChanged(BluetoothAdapter* adapter, |
| bool present) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++present_changed_count_; |
| last_present_ = present; |
| } |
| |
| virtual void AdapterPoweredChanged(BluetoothAdapter* adapter, |
| bool powered) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++powered_changed_count_; |
| last_powered_ = powered; |
| } |
| |
| virtual void AdapterDiscoveringChanged(BluetoothAdapter* adapter, |
| bool discovering) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++discovering_changed_count_; |
| last_discovering_ = discovering; |
| } |
| |
| virtual void DeviceAdded(BluetoothAdapter* adapter, |
| BluetoothDevice* device) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++device_added_count_; |
| last_device_ = device; |
| last_device_address_ = device->GetAddress(); |
| |
| QuitMessageLoop(); |
| } |
| |
| virtual void DeviceChanged(BluetoothAdapter* adapter, |
| BluetoothDevice* device) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++device_changed_count_; |
| last_device_ = device; |
| last_device_address_ = device->GetAddress(); |
| |
| QuitMessageLoop(); |
| } |
| |
| virtual void DeviceRemoved(BluetoothAdapter* adapter, |
| BluetoothDevice* device) OVERRIDE { |
| EXPECT_EQ(adapter_, adapter); |
| |
| ++device_removed_count_; |
| // Can't save device, it may be freed |
| last_device_address_ = device->GetAddress(); |
| |
| QuitMessageLoop(); |
| } |
| |
| int present_changed_count_; |
| int powered_changed_count_; |
| int discovering_changed_count_; |
| bool last_present_; |
| bool last_powered_; |
| bool last_discovering_; |
| int device_added_count_; |
| int device_changed_count_; |
| int device_removed_count_; |
| BluetoothDevice* last_device_; |
| std::string last_device_address_; |
| |
| private: |
| // Some tests use a message loop since background processing is simulated; |
| // break out of those loops. |
| void QuitMessageLoop() { |
| if (base::MessageLoop::current() && |
| base::MessageLoop::current()->is_running()) |
| base::MessageLoop::current()->Quit(); |
| } |
| |
| scoped_refptr<BluetoothAdapter> adapter_; |
| }; |
| |
| class TestPairingDelegate : public BluetoothDevice::PairingDelegate { |
| public: |
| TestPairingDelegate() |
| : call_count_(0), |
| request_pincode_count_(0), |
| request_passkey_count_(0), |
| display_pincode_count_(0), |
| display_passkey_count_(0), |
| keys_entered_count_(0), |
| confirm_passkey_count_(0), |
| dismiss_count_(0), |
| last_passkey_(9999999U), |
| last_entered_(999U) {} |
| virtual ~TestPairingDelegate() {} |
| |
| virtual void RequestPinCode(BluetoothDevice* device) OVERRIDE { |
| ++call_count_; |
| ++request_pincode_count_; |
| QuitMessageLoop(); |
| } |
| |
| virtual void RequestPasskey(BluetoothDevice* device) OVERRIDE { |
| ++call_count_; |
| ++request_passkey_count_; |
| QuitMessageLoop(); |
| } |
| |
| virtual void DisplayPinCode(BluetoothDevice* device, |
| const std::string& pincode) OVERRIDE { |
| ++call_count_; |
| ++display_pincode_count_; |
| last_pincode_ = pincode; |
| QuitMessageLoop(); |
| } |
| |
| virtual void DisplayPasskey(BluetoothDevice* device, |
| uint32 passkey) OVERRIDE { |
| ++call_count_; |
| ++display_passkey_count_; |
| last_passkey_ = passkey; |
| QuitMessageLoop(); |
| } |
| |
| virtual void KeysEntered(BluetoothDevice* device, uint32 entered) OVERRIDE { |
| ++call_count_; |
| ++keys_entered_count_; |
| last_entered_ = entered; |
| QuitMessageLoop(); |
| } |
| |
| virtual void ConfirmPasskey(BluetoothDevice* device, |
| uint32 passkey) OVERRIDE { |
| ++call_count_; |
| ++confirm_passkey_count_; |
| last_passkey_ = passkey; |
| QuitMessageLoop(); |
| } |
| |
| virtual void DismissDisplayOrConfirm() OVERRIDE { |
| ++call_count_; |
| ++dismiss_count_; |
| QuitMessageLoop(); |
| } |
| |
| int call_count_; |
| int request_pincode_count_; |
| int request_passkey_count_; |
| int display_pincode_count_; |
| int display_passkey_count_; |
| int keys_entered_count_; |
| int confirm_passkey_count_; |
| int dismiss_count_; |
| uint32 last_passkey_; |
| uint32 last_entered_; |
| std::string last_pincode_; |
| |
| private: |
| // Some tests use a message loop since background processing is simulated; |
| // break out of those loops. |
| void QuitMessageLoop() { |
| if (base::MessageLoop::current() && |
| base::MessageLoop::current()->is_running()) |
| base::MessageLoop::current()->Quit(); |
| } |
| }; |
| |
| class BluetoothExperimentalChromeOSTest : public testing::Test { |
| public: |
| virtual void SetUp() { |
| mock_dbus_thread_manager_ = |
| new MockDBusThreadManagerWithoutGMock(); |
| DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager_); |
| |
| fake_bluetooth_adapter_client_ = |
| mock_dbus_thread_manager_->fake_bluetooth_adapter_client(); |
| fake_bluetooth_device_client_ = |
| mock_dbus_thread_manager_->fake_bluetooth_device_client(); |
| |
| callback_count_ = 0; |
| error_callback_count_ = 0; |
| last_connect_error_ = BluetoothDevice::ERROR_UNKNOWN; |
| } |
| |
| virtual void TearDown() { |
| adapter_ = NULL; |
| DBusThreadManager::Shutdown(); |
| } |
| |
| // Generic callbacks |
| void Callback() { |
| ++callback_count_; |
| } |
| |
| void ErrorCallback() { |
| ++error_callback_count_; |
| } |
| |
| void ConnectErrorCallback(enum BluetoothDevice::ConnectErrorCode error) { |
| ++error_callback_count_; |
| last_connect_error_ = error; |
| } |
| |
| // Call to fill the adapter_ member with a BluetoothAdapter instance. |
| void GetAdapter() { |
| adapter_ = new BluetoothAdapterExperimentalChromeOS(); |
| ASSERT_TRUE(adapter_ != NULL); |
| 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_ != NULL); |
| |
| if (base::MessageLoop::current() == NULL) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| DiscoverDevices(); |
| return; |
| } |
| |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| ASSERT_EQ(2, callback_count_); |
| ASSERT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_TRUE(adapter_->IsPowered()); |
| ASSERT_TRUE(adapter_->IsDiscovering()); |
| |
| while (!observer.device_removed_count_ && |
| observer.last_device_address_ != address) |
| base::MessageLoop::current()->Run(); |
| |
| adapter_->StopDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| ASSERT_EQ(1, callback_count_); |
| ASSERT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_FALSE(adapter_->IsDiscovering()); |
| |
| adapter_->RemoveObserver(&observer); |
| } |
| |
| // 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: |
| FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_; |
| FakeBluetoothDeviceClient* fake_bluetooth_device_client_; |
| MockDBusThreadManagerWithoutGMock* mock_dbus_thread_manager_; |
| scoped_refptr<BluetoothAdapter> adapter_; |
| |
| int callback_count_; |
| int error_callback_count_; |
| enum BluetoothDevice::ConnectErrorCode last_connect_error_; |
| }; |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, 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(FakeBluetoothAdapterClient::kAdapterAddress, |
| adapter_->GetAddress()); |
| EXPECT_FALSE(adapter_->IsDiscovering()); |
| |
| // There should be a device |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| EXPECT_EQ(1U, devices.size()); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, 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. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| 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(1, observer.device_added_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| 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(BluetoothExperimentalChromeOSTest, BecomeNotPresent) { |
| GetAdapter(); |
| ASSERT_TRUE(adapter_->IsPresent()); |
| |
| // Install an observer; expect the AdapterPresentChanged to be called |
| // with false, and IsPresent() to return false. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| 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 a device removed. |
| EXPECT_EQ(1, observer.device_removed_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| observer.last_device_address_); |
| |
| // Other callbacks shouldn't be called since 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(BluetoothExperimentalChromeOSTest, SecondAdapter) { |
| GetAdapter(); |
| ASSERT_TRUE(adapter_->IsPresent()); |
| |
| // Install an observer, then add a second adapter. Nothing should change, |
| // we ignore the second adapter. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| fake_bluetooth_adapter_client_->SetSecondVisible(true); |
| |
| EXPECT_EQ(0, observer.present_changed_count_); |
| |
| EXPECT_TRUE(adapter_->IsPresent()); |
| EXPECT_EQ(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 a device removed. |
| EXPECT_EQ(1, observer.device_removed_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| observer.last_device_address_); |
| |
| // Other callbacks shouldn't be called since 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()); |
| |
| observer.device_removed_count_ = 0; |
| |
| // 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(BluetoothExperimentalChromeOSTest, BecomePowered) { |
| GetAdapter(); |
| ASSERT_FALSE(adapter_->IsPowered()); |
| |
| // Install an observer; expect the AdapterPoweredChanged to be called |
| // with true, and IsPowered() to return true. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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(BluetoothExperimentalChromeOSTest, BecomeNotPowered) { |
| GetAdapter(); |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->SetPowered( |
| false, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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(BluetoothExperimentalChromeOSTest, StopDiscovery) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| |
| GetAdapter(); |
| |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(2, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_TRUE(adapter_->IsPowered()); |
| ASSERT_TRUE(adapter_->IsDiscovering()); |
| |
| // Install an observer; aside from the callback, expect the |
| // AdapterDiscoveringChanged method to be called and no longer to be |
| // discovering, |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->StopDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, StopDiscoveryAfterTwoStarts) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| |
| GetAdapter(); |
| |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(2, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_TRUE(adapter_->IsPowered()); |
| ASSERT_TRUE(adapter_->IsDiscovering()); |
| |
| // Install an observer and start discovering again; only the callback |
| // should be called since we were already discovering to begin with. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(1, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| EXPECT_EQ(0, observer.discovering_changed_count_); |
| |
| // Stop discovering; only the callback should be called since we're still |
| // discovering. The adapter should be still discovering. |
| adapter_->StopDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(1, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| EXPECT_EQ(0, observer.discovering_changed_count_); |
| |
| EXPECT_TRUE(adapter_->IsDiscovering()); |
| |
| // Stop discovering one more time; aside from the callback, expect the |
| // AdapterDiscoveringChanged method to be called and no longer to be |
| // discovering, |
| adapter_->StopDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, Discovery) { |
| // Test a simulated discovery session. |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| GetAdapter(); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(2, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_TRUE(adapter_->IsPowered()); |
| ASSERT_TRUE(adapter_->IsDiscovering()); |
| |
| // First device to appear should be an Apple Mouse. |
| message_loop.Run(); |
| |
| EXPECT_EQ(1, observer.device_added_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kAppleMouseAddress, |
| observer.last_device_address_); |
| |
| // Next we should get another two devices... |
| message_loop.Run(); |
| EXPECT_EQ(3, observer.device_added_count_); |
| |
| // Okay, let's run forward until a device is actually removed... |
| while (!observer.device_removed_count_) |
| message_loop.Run(); |
| |
| EXPECT_EQ(1, observer.device_removed_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kVanishingDeviceAddress, |
| observer.last_device_address_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PoweredAndDiscovering) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| |
| GetAdapter(); |
| adapter_->SetPowered( |
| true, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| adapter_->StartDiscovering( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(2, callback_count_); |
| EXPECT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| // Stop the timers that the simulation uses |
| fake_bluetooth_device_client_->EndDiscoverySimulation( |
| dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); |
| |
| ASSERT_TRUE(adapter_->IsPowered()); |
| ASSERT_TRUE(adapter_->IsDiscovering()); |
| |
| fake_bluetooth_adapter_client_->SetVisible(false); |
| ASSERT_FALSE(adapter_->IsPresent()); |
| |
| // Install an observer; expect the AdapterPresentChanged, |
| // AdapterPoweredChanged and AdapterDiscoveringChanged methods to be called |
| // with true, and IsPresent(), IsPowered() and IsDiscovering() to all |
| // return true. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| 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.present_changed_count_ = 0; |
| observer.powered_changed_count_ = 0; |
| observer.discovering_changed_count_ = 0; |
| |
| // 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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, DeviceProperties) { |
| GetAdapter(); |
| |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| ASSERT_EQ(1U, devices.size()); |
| ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| |
| // Verify the other device properties. |
| EXPECT_EQ(UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName), |
| devices[0]->GetName()); |
| EXPECT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[0]->GetDeviceType()); |
| EXPECT_TRUE(devices[0]->IsPaired()); |
| EXPECT_FALSE(devices[0]->IsConnected()); |
| EXPECT_FALSE(devices[0]->IsConnecting()); |
| |
| // Non HID devices are always connectable. |
| EXPECT_TRUE(devices[0]->IsConnectable()); |
| |
| BluetoothDevice::ServiceList uuids = devices[0]->GetServices(); |
| ASSERT_EQ(2U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001800-0000-1000-8000-00805f9b34fb"); |
| EXPECT_EQ(uuids[1], "00001801-0000-1000-8000-00805f9b34fb"); |
| |
| EXPECT_EQ(0x05ac, devices[0]->GetVendorID()); |
| EXPECT_EQ(0x030d, devices[0]->GetProductID()); |
| EXPECT_EQ(0x0306, devices[0]->GetDeviceID()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, DeviceClassChanged) { |
| // Simulate a change of class of a device, as sometimes occurs |
| // during discovery. |
| GetAdapter(); |
| |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| ASSERT_EQ(1U, devices.size()); |
| ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| ASSERT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[0]->GetDeviceType()); |
| |
| // Install an observer; expect the DeviceChanged method to be called when |
| // we change the class of the device. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); |
| |
| properties->bluetooth_class.ReplaceValue(0x002580); |
| |
| EXPECT_EQ(1, observer.device_changed_count_); |
| EXPECT_EQ(devices[0], observer.last_device_); |
| |
| EXPECT_EQ(BluetoothDevice::DEVICE_MOUSE, devices[0]->GetDeviceType()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, DeviceNameChanged) { |
| // Simulate a change of name of a device. |
| GetAdapter(); |
| |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| ASSERT_EQ(1U, devices.size()); |
| ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| ASSERT_EQ(UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName), |
| devices[0]->GetName()); |
| |
| // Install an observer; expect the DeviceChanged method to be called when |
| // we change the alias of the device. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); |
| |
| static const std::string new_name("New Device Name"); |
| properties->alias.ReplaceValue(new_name); |
| |
| EXPECT_EQ(1, observer.device_changed_count_); |
| EXPECT_EQ(devices[0], observer.last_device_); |
| |
| EXPECT_EQ(UTF8ToUTF16(new_name), devices[0]->GetName()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, DeviceUuidsChanged) { |
| // Simulate a change of advertised services of a device. |
| GetAdapter(); |
| |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| ASSERT_EQ(1U, devices.size()); |
| ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| |
| BluetoothDevice::ServiceList uuids = devices[0]->GetServices(); |
| ASSERT_EQ(2U, uuids.size()); |
| ASSERT_EQ(uuids[0], "00001800-0000-1000-8000-00805f9b34fb"); |
| ASSERT_EQ(uuids[1], "00001801-0000-1000-8000-00805f9b34fb"); |
| |
| // Install an observer; expect the DeviceChanged method to be called when |
| // we change the class of the device. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath)); |
| |
| uuids.push_back("0000110c-0000-1000-8000-00805f9b34fb"); |
| uuids.push_back("0000110e-0000-1000-8000-00805f9b34fb"); |
| uuids.push_back("0000110a-0000-1000-8000-00805f9b34fb"); |
| |
| properties->uuids.ReplaceValue(uuids); |
| |
| EXPECT_EQ(1, observer.device_changed_count_); |
| EXPECT_EQ(devices[0], observer.last_device_); |
| |
| // Fetching the value should give the new one. |
| uuids = devices[0]->GetServices(); |
| ASSERT_EQ(5U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001800-0000-1000-8000-00805f9b34fb"); |
| EXPECT_EQ(uuids[1], "00001801-0000-1000-8000-00805f9b34fb"); |
| EXPECT_EQ(uuids[2], "0000110c-0000-1000-8000-00805f9b34fb"); |
| EXPECT_EQ(uuids[3], "0000110e-0000-1000-8000-00805f9b34fb"); |
| EXPECT_EQ(uuids[4], "0000110a-0000-1000-8000-00805f9b34fb"); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ForgetDevice) { |
| GetAdapter(); |
| |
| BluetoothAdapter::DeviceList devices = adapter_->GetDevices(); |
| ASSERT_EQ(1U, devices.size()); |
| ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress, |
| devices[0]->GetAddress()); |
| |
| std::string address = devices[0]->GetAddress(); |
| |
| // Install an observer; expect the DeviceRemoved method to be called |
| // with the device we remove. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| devices[0]->Forget( |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| 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(0U, devices.size()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ForgetUnpairedDevice) { |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kMicrosoftMouseAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| // Connect the device so it becomes trusted and remembered. |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kMicrosoftMousePath)); |
| ASSERT_TRUE(properties->trusted.value()); |
| |
| // Install an observer; expect the DeviceRemoved method to be called |
| // with the device we remove. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| device->Forget( |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| EXPECT_EQ(0, error_callback_count_); |
| |
| EXPECT_EQ(1, observer.device_removed_count_); |
| EXPECT_EQ(FakeBluetoothDeviceClient::kMicrosoftMouseAddress, |
| observer.last_device_address_); |
| |
| // GetDevices shouldn't return the device either. |
| device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kMicrosoftMouseAddress); |
| EXPECT_FALSE(device != NULL); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ConnectPairedDevice) { |
| GetAdapter(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPairedDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_TRUE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| // Connect without a pairing delegate; since the device is already Paired |
| // this should succeed and the device should become connected. |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ConnectUnpairableDevice) { |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kMicrosoftMouseAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| // Connect without a pairing delegate; since the device does not require |
| // pairing, this should succeed and the device should become connected. |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kMicrosoftMousePath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| |
| // Verify is a HID device and is not connectable. |
| BluetoothDevice::ServiceList uuids = device->GetServices(); |
| ASSERT_EQ(1U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); |
| EXPECT_FALSE(device->IsConnectable()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ConnectConnectedDevice) { |
| GetAdapter(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPairedDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_TRUE(device->IsPaired()); |
| |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| ASSERT_EQ(1, callback_count_); |
| ASSERT_EQ(0, error_callback_count_); |
| callback_count_ = 0; |
| |
| ASSERT_TRUE(device->IsConnected()); |
| |
| // Connect again; since the device is already Connected, this shouldn't do |
| // anything to initiate the connection. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, ConnectDeviceFails) { |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kAppleMouseAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| // Connect without a pairing delegate; since the device requires pairing, |
| // this should fail with an error. |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, DisconnectDevice) { |
| GetAdapter(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPairedDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_TRUE(device->IsPaired()); |
| |
| device->Connect( |
| NULL, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| |
| // Disconnect the device, we should see the observer method fire and the |
| // device get dropped. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| device->Disconnect( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| |
| 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(BluetoothExperimentalChromeOSTest, DisconnectUnconnectedDevice) { |
| GetAdapter(); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPairedDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_TRUE(device->IsPaired()); |
| ASSERT_FALSE(device->IsConnected()); |
| |
| // Disconnect the device, we should see the observer method fire and the |
| // device get dropped. |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| device->Disconnect( |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, callback_count_); |
| EXPECT_EQ(1, error_callback_count_); |
| |
| EXPECT_EQ(0, observer.device_changed_count_); |
| |
| EXPECT_FALSE(device->IsConnected()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairAppleMouse) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // The Apple Mouse requires no PIN or Passkey to pair; this is equivalent |
| // to Simple Secure Pairing or a device with a fixed 0000 PIN. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kAppleMouseAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, pairing_delegate.call_count_); |
| EXPECT_TRUE(device->IsConnecting()); |
| |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Verify is a HID device and is connectable. |
| BluetoothDevice::ServiceList uuids = device->GetServices(); |
| ASSERT_EQ(1U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); |
| EXPECT_TRUE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kAppleMousePath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairAppleKeyboard) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // The Apple Keyboard requires that we display a randomly generated |
| // PIN on the screen. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kAppleKeyboardAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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()); |
| |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Verify is a HID device and is connectable. |
| BluetoothDevice::ServiceList uuids = device->GetServices(); |
| ASSERT_EQ(1U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); |
| EXPECT_TRUE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kAppleKeyboardPath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // The Motorola Keyboard requires that we display a randomly generated |
| // Passkey on the screen, and notifies us as it's typed in. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kMotorolaKeyboardAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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) { |
| message_loop.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_); |
| } |
| |
| message_loop.Run(); |
| |
| // 8 KeysEntered notifications (0 to 7, inclusive). Two aditional calls for |
| // DisplayPasskey() and DismissDisplayOrConfirm(). |
| EXPECT_EQ(10, 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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Verify is a HID device. |
| BluetoothDevice::ServiceList uuids = device->GetServices(); |
| ASSERT_EQ(1U, uuids.size()); |
| EXPECT_EQ(uuids[0], "00001124-0000-1000-8000-00805f9b34fb"); |
| |
| // Fake MotorolaKeyboard is not connectable. |
| EXPECT_FALSE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kMotorolaKeyboardPath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairSonyHeadphones) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // The Sony Headphones fake requires that the user enters a PIN for them. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kSonyHeadphonesAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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"); |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Verify is not a HID device. |
| BluetoothDevice::ServiceList uuids = device->GetServices(); |
| ASSERT_EQ(0U, uuids.size()); |
| |
| // Non HID devices are always connectable. |
| EXPECT_TRUE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kSonyHeadphonesPath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairPhone) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // The fake phone requests that we confirm a displayed passkey. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPhoneAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Non HID devices are always connectable. |
| EXPECT_TRUE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kPhonePath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairWeirdDevice) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Use the "weird device" fake that 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( |
| FakeBluetoothDeviceClient::kWeirdDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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); |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Non HID devices are always connectable. |
| EXPECT_TRUE(device->IsConnectable()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true. |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath(FakeBluetoothDeviceClient::kWeirdDevicePath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairUnpairableDeviceFails) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevice(FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); |
| |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kUnpairableDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, pairing_delegate.call_count_); |
| EXPECT_TRUE(device->IsConnecting()); |
| |
| // Run the loop to get the error.. |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingFails) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevice(FakeBluetoothDeviceClient::kVanishingDeviceAddress); |
| |
| // The vanishing device times out during pairing |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kVanishingDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, pairing_delegate.call_count_); |
| EXPECT_TRUE(device->IsConnecting()); |
| |
| // Run the loop to get the error.. |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingFailsAtConnection) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| 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( |
| FakeBluetoothDeviceClient::kUnconnectableDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, pairing_delegate.call_count_); |
| EXPECT_TRUE(device->IsConnecting()); |
| |
| message_loop.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()); |
| |
| EXPECT_TRUE(device->IsPaired()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| |
| // Make sure the trusted property has been set to true still (since pairing |
| // worked). |
| FakeBluetoothDeviceClient::Properties* properties = |
| fake_bluetooth_device_client_->GetProperties( |
| dbus::ObjectPath( |
| FakeBluetoothDeviceClient::kUnconnectableDevicePath)); |
| EXPECT_TRUE(properties->trusted.value()); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingRejectedAtPinCode) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Reject the pairing after we receive a request for the PIN code. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kSonyHeadphonesAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingCancelledAtPinCode) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Cancel the pairing after we receive a request for the PIN code. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kSonyHeadphonesAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingRejectedAtPasskey) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Reject the pairing after we receive a request for the passkey. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kWeirdDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingCancelledAtPasskey) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Cancel the pairing after we receive a request for the passkey. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kWeirdDeviceAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingRejectedAtConfirmation) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Reject the pairing after we receive a request for passkey confirmation. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPhoneAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingCancelledAtConfirmation) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Cancel the pairing after we receive a request for the passkey. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kPhoneAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::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(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(2, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| TEST_F(BluetoothExperimentalChromeOSTest, PairingCancelledInFlight) { |
| base::MessageLoop message_loop(base::MessageLoop::TYPE_DEFAULT); |
| fake_bluetooth_device_client_->SetSimulationIntervalMs(10); |
| |
| GetAdapter(); |
| DiscoverDevices(); |
| |
| // Cancel the pairing while we're waiting for the remote host. |
| BluetoothDevice* device = adapter_->GetDevice( |
| FakeBluetoothDeviceClient::kAppleMouseAddress); |
| ASSERT_TRUE(device != NULL); |
| ASSERT_FALSE(device->IsPaired()); |
| |
| TestObserver observer(adapter_); |
| adapter_->AddObserver(&observer); |
| |
| TestPairingDelegate pairing_delegate; |
| device->Connect( |
| &pairing_delegate, |
| base::Bind(&BluetoothExperimentalChromeOSTest::Callback, |
| base::Unretained(this)), |
| base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, |
| base::Unretained(this))); |
| |
| EXPECT_EQ(0, pairing_delegate.call_count_); |
| EXPECT_TRUE(device->IsConnecting()); |
| |
| // Cancel the pairing. |
| device->CancelPairing(); |
| message_loop.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()); |
| |
| // Pairing dialog should be dismissed |
| EXPECT_EQ(1, pairing_delegate.call_count_); |
| EXPECT_EQ(1, pairing_delegate.dismiss_count_); |
| } |
| |
| } // namespace chromeos |