Chromium Code Reviews| 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 |