Index: components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc |
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..136a67bcd9b5c3f6929032dc0bc3abc8cb457a0c |
--- /dev/null |
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc |
@@ -0,0 +1,309 @@ |
+// Copyright 2015 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 "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" |
+ |
+#include "base/bind.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/time/time.h" |
+#include "components/proximity_auth/connection.h" |
+#include "components/proximity_auth/remote_device.h" |
+#include "components/proximity_auth/wire_message.h" |
+#include "device/bluetooth/bluetooth_adapter_factory.h" |
+#include "device/bluetooth/bluetooth_uuid.h" |
+#include "device/bluetooth/test/mock_bluetooth_adapter.h" |
+#include "device/bluetooth/test/mock_bluetooth_device.h" |
+#include "device/bluetooth/test/mock_bluetooth_discovery_session.h" |
+#include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using testing::_; |
+using testing::NiceMock; |
+using testing::Return; |
+using testing::StrictMock; |
+using testing::SaveArg; |
+ |
+namespace proximity_auth { |
+namespace { |
+ |
+const char kDeviceName[] = "Device name"; |
+const char kBluetoothAddress[] = "11:22:33:44:55:66"; |
+const RemoteDevice kRemoteDevice = {kDeviceName, kBluetoothAddress}; |
+ |
+const char kServiceUUID[] = "1EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; |
+const char kToPeripheralCharUUID[] = "2EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; |
+const char kFromPeripheralCharUUID[] = "3EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; |
+ |
+const char kOtherUUID[] = "AAAAAAAA-AAAA-AAAA-AAAA-D15EA5EBEEEF"; |
+const char kOtherBluetoothAddress[] = "00:00:00:00:00:00"; |
+ |
+class MockConnection : public Connection { |
+ public: |
+ MockConnection() : Connection(kRemoteDevice) {} |
+ ~MockConnection() override {} |
+ |
+ MOCK_METHOD0(Connect, void()); |
+ |
+ using Connection::SetStatus; |
+ |
+ private: |
+ void Disconnect() override {} |
+ void SendMessageImpl(scoped_ptr<WireMessage> message) override {} |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MockConnection); |
+}; |
+ |
+class MockBluetoothLowEnergyConnectionFinder |
+ : public BluetoothLowEnergyConnectionFinder { |
+ public: |
+ MockBluetoothLowEnergyConnectionFinder() |
+ : BluetoothLowEnergyConnectionFinder(kServiceUUID, |
+ kToPeripheralCharUUID, |
+ kFromPeripheralCharUUID) {} |
+ ~MockBluetoothLowEnergyConnectionFinder() override {} |
+ |
+ MOCK_METHOD0(CreateConnectionProxy, Connection*()); |
Tim Song
2015/05/20 07:47:01
Why not just have CreateConnectionProxy() return s
sacomoto
2015/05/20 22:34:22
Mock methods don't support return type of scoped_p
|
+ |
+ // Creates a mock connection and sets an expectation that the mock connection |
+ // finder's CreateConnection() method will be called and will return the |
+ // created connection. Returns a reference to the created connection. |
+ // NOTE: The returned connection's lifetime is managed by the connection |
+ // finder. |
+ MockConnection* ExpectCreateConnection() { |
+ scoped_ptr<MockConnection> connection(new NiceMock<MockConnection>()); |
+ MockConnection* connection_alias = connection.get(); |
+ EXPECT_CALL(*this, CreateConnectionProxy()) |
+ .WillOnce(Return(connection.release())); |
+ return connection_alias; |
+ } |
+ |
+ protected: |
+ scoped_ptr<Connection> CreateConnection( |
+ scoped_ptr<device::BluetoothGattConnection> gatt_connection) override { |
+ return make_scoped_ptr(CreateConnectionProxy()); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MockBluetoothLowEnergyConnectionFinder); |
+}; |
+ |
+} // namespace |
+ |
+class ProximityAuthBluetoothLowEnergyConnectionFinderTest |
+ : public testing::Test { |
+ protected: |
+ ProximityAuthBluetoothLowEnergyConnectionFinderTest() |
+ : adapter_(new NiceMock<device::MockBluetoothAdapter>), |
+ connection_callback_( |
+ base::Bind(&ProximityAuthBluetoothLowEnergyConnectionFinderTest:: |
+ OnConnectionFound, |
+ base::Unretained(this))), |
+ device_(new NiceMock<device::MockBluetoothDevice>(adapter_.get(), |
+ 0, |
+ kDeviceName, |
+ kBluetoothAddress, |
+ false, |
+ false)) { |
+ device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_); |
+ |
+ ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true)); |
+ ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true)); |
+ } |
+ |
+ MOCK_METHOD1(OnConnectionFoundProxy, void(Connection* connection)); |
Tim Song
2015/05/20 07:47:01
nit: add a new line here
sacomoto
2015/05/20 22:34:21
Done.
|
+ void OnConnectionFound(scoped_ptr<Connection> connection) { |
+ OnConnectionFoundProxy(connection.get()); |
+ last_found_connection_ = connection.Pass(); |
+ } |
+ |
+ scoped_refptr<device::MockBluetoothAdapter> adapter_; |
+ ConnectionFinder::ConnectionCallback connection_callback_; |
+ |
+ protected: |
+ scoped_ptr<device::MockBluetoothDevice> device_; |
+ |
+ private: |
+ // Save a pointer to the last found connection, to extend its lifetime. |
+ scoped_ptr<Connection> last_found_connection_; |
+}; |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ ConstructAndDestroyDoesntCrash) { |
+ // Destroying a BluetoothConnectionFinder for which Find() has not been called |
+ // should not crash. |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_StartsDiscoverySession) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ EXPECT_CALL(*adapter_, StartDiscoverySession(_, _)); |
+ EXPECT_CALL(*adapter_, AddObserver(_)); |
+ connection_finder.Find(connection_callback_); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_StopsDiscoverySessionBeforeDestroying) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ device::BluetoothAdapter::DiscoverySessionCallback discovery_callback; |
+ scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session( |
+ new NiceMock<device::MockBluetoothDiscoverySession>()); |
+ device::MockBluetoothDiscoverySession* discovery_session_alias = |
+ discovery_session.get(); |
+ |
+ EXPECT_CALL(*adapter_, StartDiscoverySession(_, _)) |
+ .WillOnce(SaveArg<0>(&discovery_callback)); |
+ ON_CALL(*discovery_session_alias, IsActive()).WillByDefault(Return(true)); |
+ EXPECT_CALL(*adapter_, AddObserver(_)); |
+ connection_finder.Find(connection_callback_); |
+ |
+ EXPECT_CALL(*discovery_session_alias, Stop(_, _)); |
+ ASSERT_FALSE(discovery_callback.is_null()); |
+ discovery_callback.Run(discovery_session.Pass()); |
+ |
+ EXPECT_CALL(*adapter_, RemoveObserver(_)); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_CreatesGattConnectionWhenRightDeviceIsAdded) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kServiceUUID)); |
+ |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)); |
+ connection_finder.DeviceAdded(adapter_.get(), device_.get()); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_DoesntCreateGattConnectionWhenWrongDeviceIsAdded) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kOtherUUID)); |
+ |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)).Times(0); |
+ connection_finder.DeviceAdded(adapter_.get(), device_.get()); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_CreatesGattConnectionWhenRightDeviceIsChanged) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kServiceUUID)); |
+ |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)); |
+ connection_finder.DeviceChanged(adapter_.get(), device_.get()); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_DoesntCreateGattConnectionWhenWrongDeviceIsChanged) { |
+ BluetoothLowEnergyConnectionFinder connection_finder( |
+ kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); |
+ |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kOtherUUID)); |
+ |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)).Times(0); |
+ connection_finder.DeviceChanged(adapter_.get(), device_.get()); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_CreatesTwoGattConnections) { |
+ StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder; |
+ connection_finder.ExpectCreateConnection(); |
+ connection_finder.Find(connection_callback_); |
+ |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kServiceUUID)); |
+ NiceMock<device::MockBluetoothDevice> other_device( |
+ adapter_.get(), 0, kDeviceName, kOtherBluetoothAddress, false, false); |
+ |
+ ON_CALL(other_device, GetUUIDs()).WillByDefault((Return(uuids))); |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ |
+ device::BluetoothDevice::GattConnectionCallback gatt_connection_callback, |
+ other_gatt_connection_callback; |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)) |
+ .WillOnce(SaveArg<0>(&gatt_connection_callback)); |
+ EXPECT_CALL(other_device, CreateGattConnection(_, _)) |
+ .WillOnce(SaveArg<0>(&other_gatt_connection_callback)); |
+ |
+ connection_finder.DeviceAdded(adapter_.get(), device_.get()); |
+ connection_finder.DeviceAdded(adapter_.get(), &other_device); |
+ |
+ ASSERT_FALSE(gatt_connection_callback.is_null()); |
+ ASSERT_FALSE(other_gatt_connection_callback.is_null()); |
+ |
+ gatt_connection_callback.Run(make_scoped_ptr( |
+ new NiceMock<device::MockBluetoothGattConnection>(kBluetoothAddress))); |
+ |
+ // The second device should be forget |
+ EXPECT_CALL(*adapter_, GetDevice(std::string(kOtherBluetoothAddress))) |
+ .WillOnce(Return(&other_device)); |
+ EXPECT_CALL(other_device, Forget(_)); |
+ other_gatt_connection_callback.Run( |
+ make_scoped_ptr(new NiceMock<device::MockBluetoothGattConnection>( |
+ kOtherBluetoothAddress))); |
+} |
+ |
+TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, |
+ Find_ConnectionSucceeds) { |
+ StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder; |
+ |
+ device::BluetoothAdapter::DiscoverySessionCallback discovery_callback; |
+ scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session( |
+ new NiceMock<device::MockBluetoothDiscoverySession>()); |
+ device::MockBluetoothDiscoverySession* discovery_session_alias = |
+ discovery_session.get(); |
+ |
+ // Starting a discovery session |
+ EXPECT_CALL(*adapter_, StartDiscoverySession(_, _)) |
Tim Song
2015/05/20 07:47:01
We should refactor this block to a method and star
sacomoto
2015/05/20 22:34:22
Done.
|
+ .WillOnce(SaveArg<0>(&discovery_callback)); |
+ EXPECT_CALL(*adapter_, AddObserver(_)); |
+ ON_CALL(*discovery_session_alias, IsActive()).WillByDefault(Return(true)); |
+ connection_finder.Find(connection_callback_); |
+ ASSERT_FALSE(discovery_callback.is_null()); |
+ discovery_callback.Run(discovery_session.Pass()); |
+ |
+ // Finding and creating a GATT connection to the right device |
+ std::vector<device::BluetoothUUID> uuids; |
+ uuids.push_back(device::BluetoothUUID(kServiceUUID)); |
+ device::BluetoothDevice::GattConnectionCallback gatt_connection_callback; |
+ |
+ ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); |
+ EXPECT_CALL(*device_, CreateGattConnection(_, _)) |
+ .WillOnce(SaveArg<0>(&gatt_connection_callback)); |
+ connection_finder.DeviceAdded(adapter_.get(), device_.get()); |
Tim Song
2015/05/20 07:47:01
Same here. It may be worth while to refactor this
sacomoto
2015/05/20 22:34:21
Done.
|
+ |
+ // Creating a connection |
+ MockConnection* connection = connection_finder.ExpectCreateConnection(); |
+ ASSERT_FALSE(gatt_connection_callback.is_null()); |
+ gatt_connection_callback.Run(make_scoped_ptr( |
+ new NiceMock<device::MockBluetoothGattConnection>(kBluetoothAddress))); |
+ connection->SetStatus(Connection::IN_PROGRESS); |
+ EXPECT_CALL(*this, OnConnectionFoundProxy(_)); |
Tim Song
2015/05/20 07:47:01
Do you really need this proxy function? Can't you
sacomoto
2015/05/20 22:34:22
Yes, you are right. I changed and removed the OnCo
|
+ connection->SetStatus(Connection::CONNECTED); |
+ |
+ // Cleaning up |
+ EXPECT_CALL(*discovery_session_alias, Stop(_, _)); |
+ EXPECT_CALL(*adapter_, RemoveObserver(_)); |
+} |
+ |
+} // namespace proximity_auth |