Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / proximity_auth / ble / bluetooth_low_energy_connection_finder_unittest.cc
blob4cb745cf3b12a58ca9a4c17f35a0c9c0a493bcfb
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "components/proximity_auth/ble/bluetooth_low_energy_device_whitelist.h"
16 #include "components/proximity_auth/connection.h"
17 #include "components/proximity_auth/remote_device.h"
18 #include "components/proximity_auth/wire_message.h"
19 #include "device/bluetooth/bluetooth_adapter_factory.h"
20 #include "device/bluetooth/bluetooth_uuid.h"
21 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
22 #include "device/bluetooth/test/mock_bluetooth_device.h"
23 #include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
24 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 using testing::_;
29 using testing::AtLeast;
30 using testing::NiceMock;
31 using testing::Return;
32 using testing::StrictMock;
33 using testing::SaveArg;
35 namespace proximity_auth {
36 namespace {
38 const char kDeviceName[] = "Device name";
39 const char kPublicKey[] = "Public key";
40 const char kBluetoothAddress[] = "11:22:33:44:55:66";
41 const char kPersistentSymmetricKey[] = "PSK";
43 const char kServiceUUID[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF";
44 const char kToPeripheralCharUUID[] = "FBAE09F2-0482-11E5-8418-1697F925EC7B";
45 const char kFromPeripheralCharUUID[] = "5539ED10-0483-11E5-8418-1697F925EC7B";
47 const char kOtherUUID[] = "AAAAAAAA-AAAA-AAAA-AAAA-D15EA5EBEEEF";
48 const char kOtherBluetoothAddress[] = "00:00:00:00:00:00";
50 const int kMaxNumberOfAttempts = 2;
52 class MockConnection : public Connection {
53 public:
54 MockConnection() : Connection(CreateRemoteDevice()) {}
55 ~MockConnection() override {}
57 MOCK_METHOD0(Connect, void());
59 using Connection::SetStatus;
61 private:
62 void Disconnect() override {}
63 void SendMessageImpl(scoped_ptr<WireMessage> message) override {}
65 RemoteDevice CreateRemoteDevice() {
66 return RemoteDevice(kDeviceName, kPublicKey, kBluetoothAddress,
67 kPersistentSymmetricKey);
70 DISALLOW_COPY_AND_ASSIGN(MockConnection);
73 class MockBluetoothLowEnergyDeviceWhitelist
74 : public BluetoothLowEnergyDeviceWhitelist {
75 public:
76 MockBluetoothLowEnergyDeviceWhitelist()
77 : BluetoothLowEnergyDeviceWhitelist(nullptr) {}
78 ~MockBluetoothLowEnergyDeviceWhitelist() override {}
80 MOCK_CONST_METHOD1(HasDeviceWithAddress, bool(const std::string&));
83 class MockBluetoothLowEnergyConnectionFinder
84 : public BluetoothLowEnergyConnectionFinder {
85 public:
86 MockBluetoothLowEnergyConnectionFinder(
87 const BluetoothLowEnergyDeviceWhitelist* device_whitelist)
88 : BluetoothLowEnergyConnectionFinder(kServiceUUID,
89 kToPeripheralCharUUID,
90 kFromPeripheralCharUUID,
91 device_whitelist,
92 nullptr,
93 kMaxNumberOfAttempts) {}
95 ~MockBluetoothLowEnergyConnectionFinder() override {}
97 // Mock methods don't support return type scoped_ptr<>. This is a possible
98 // workaround: mock a proxy method to be called by the target overrided method
99 // (CreateConnection).
100 MOCK_METHOD0(CreateConnectionProxy, Connection*());
102 // Creates a mock connection and sets an expectation that the mock connection
103 // finder's CreateConnection() method will be called and will return the
104 // created connection. Returns a reference to the created connection.
105 // NOTE: The returned connection's lifetime is managed by the connection
106 // finder.
107 MockConnection* ExpectCreateConnection() {
108 scoped_ptr<MockConnection> connection(new NiceMock<MockConnection>());
109 MockConnection* connection_alias = connection.get();
110 EXPECT_CALL(*this, CreateConnectionProxy())
111 .WillOnce(Return(connection.release()));
112 return connection_alias;
115 MOCK_METHOD0(CloseGattConnectionProxy, void(void));
117 protected:
118 scoped_ptr<Connection> CreateConnection(
119 const std::string& device_address) override {
120 return make_scoped_ptr(CreateConnectionProxy());
123 private:
124 DISALLOW_COPY_AND_ASSIGN(MockBluetoothLowEnergyConnectionFinder);
127 } // namespace
129 class ProximityAuthBluetoothLowEnergyConnectionFinderTest
130 : public testing::Test {
131 protected:
132 ProximityAuthBluetoothLowEnergyConnectionFinderTest()
133 : adapter_(new NiceMock<device::MockBluetoothAdapter>),
134 connection_callback_(
135 base::Bind(&ProximityAuthBluetoothLowEnergyConnectionFinderTest::
136 OnConnectionFound,
137 base::Unretained(this))),
138 device_(new NiceMock<device::MockBluetoothDevice>(adapter_.get(),
140 kDeviceName,
141 kBluetoothAddress,
142 false,
143 false)),
144 device_whitelist_(new MockBluetoothLowEnergyDeviceWhitelist()),
145 last_discovery_session_alias_(nullptr) {
146 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
148 std::vector<const device::BluetoothDevice*> devices;
149 ON_CALL(*adapter_, GetDevices()).WillByDefault(Return(devices));
151 ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true));
152 ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true));
154 ON_CALL(*device_whitelist_, HasDeviceWithAddress(_))
155 .WillByDefault(Return(false));
158 void OnConnectionFound(scoped_ptr<Connection> connection) {
159 last_found_connection_ = connection.Pass();
162 void FindAndExpectStartDiscovery(
163 BluetoothLowEnergyConnectionFinder& connection_finder) {
164 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback;
165 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session(
166 new NiceMock<device::MockBluetoothDiscoverySession>());
167 last_discovery_session_alias_ = discovery_session.get();
169 // Starting a discovery session. StartDiscoveryWithFilterRaw is a proxy for
170 // StartDiscoveryWithFilter.
171 EXPECT_CALL(*adapter_, StartDiscoverySessionWithFilterRaw(_, _, _))
172 .WillOnce(SaveArg<1>(&discovery_callback));
173 EXPECT_CALL(*adapter_, AddObserver(_));
174 ON_CALL(*last_discovery_session_alias_, IsActive())
175 .WillByDefault(Return(true));
176 connection_finder.Find(connection_callback_);
177 ASSERT_FALSE(discovery_callback.is_null());
178 discovery_callback.Run(discovery_session.Pass());
181 void ExpectStopDiscoveryAndRemoveObserver() {
182 EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
183 EXPECT_CALL(*adapter_, RemoveObserver(_)).Times(AtLeast(1));
186 // Prepare |device_| with |uuid|.
187 void PrepareDevice(const std::string& uuid) {
188 std::vector<device::BluetoothUUID> uuids;
189 uuids.push_back(device::BluetoothUUID(uuid));
190 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids));
193 // Prepare expectations to add/change a right device.
194 void PrepareForNewRightDevice(const std::string& uuid) {
195 PrepareDevice(uuid);
196 ON_CALL(*device_, IsPaired()).WillByDefault(Return(true));
199 // Prepare expectations to add/change a wrong device.
200 void PrepareForNewWrongDevice(const std::string& uuid) {
201 PrepareDevice(uuid);
202 ON_CALL(*device_, IsPaired()).WillByDefault(Return(true));
205 scoped_refptr<device::MockBluetoothAdapter> adapter_;
206 ConnectionFinder::ConnectionCallback connection_callback_;
207 scoped_ptr<device::MockBluetoothDevice> device_;
208 scoped_ptr<Connection> last_found_connection_;
209 scoped_ptr<MockBluetoothLowEnergyDeviceWhitelist> device_whitelist_;
210 device::MockBluetoothDiscoverySession* last_discovery_session_alias_;
212 private:
213 base::MessageLoop message_loop_;
216 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
217 ConstructAndDestroyDoesntCrash) {
218 // Destroying a BluetoothConnectionFinder for which Find() has not been called
219 // should not crash.
220 BluetoothLowEnergyConnectionFinder connection_finder(
221 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID,
222 device_whitelist_.get(), nullptr, kMaxNumberOfAttempts);
225 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
226 Find_StartsDiscoverySession) {
227 BluetoothLowEnergyConnectionFinder connection_finder(
228 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID,
229 device_whitelist_.get(), nullptr, kMaxNumberOfAttempts);
231 EXPECT_CALL(*adapter_, StartDiscoverySessionWithFilterRaw(_, _, _));
232 EXPECT_CALL(*adapter_, AddObserver(_));
233 connection_finder.Find(connection_callback_);
236 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
237 Find_StopsDiscoverySessionBeforeDestroying) {
238 BluetoothLowEnergyConnectionFinder connection_finder(
239 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID,
240 device_whitelist_.get(), nullptr, kMaxNumberOfAttempts);
242 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback;
243 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session(
244 new NiceMock<device::MockBluetoothDiscoverySession>());
245 device::MockBluetoothDiscoverySession* discovery_session_alias =
246 discovery_session.get();
248 EXPECT_CALL(*adapter_, StartDiscoverySessionWithFilterRaw(_, _, _))
249 .WillOnce(SaveArg<1>(&discovery_callback));
250 ON_CALL(*discovery_session_alias, IsActive()).WillByDefault(Return(true));
251 EXPECT_CALL(*adapter_, AddObserver(_));
252 connection_finder.Find(connection_callback_);
254 EXPECT_CALL(*discovery_session_alias, Stop(_, _));
255 ASSERT_FALSE(discovery_callback.is_null());
256 discovery_callback.Run(discovery_session.Pass());
258 EXPECT_CALL(*adapter_, RemoveObserver(_));
261 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
262 Find_CreatesConnectionWhenWhitelistedDeviceIsAdded) {
263 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
264 device_whitelist_.get());
265 FindAndExpectStartDiscovery(connection_finder);
266 ExpectStopDiscoveryAndRemoveObserver();
268 std::vector<device::BluetoothUUID> uuids;
269 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids));
270 ON_CALL(*device_, IsPaired()).WillByDefault(Return(true));
271 ON_CALL(*device_whitelist_, HasDeviceWithAddress(_))
272 .WillByDefault(Return(true));
274 connection_finder.ExpectCreateConnection();
275 connection_finder.DeviceAdded(adapter_.get(), device_.get());
278 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
279 Find_CreatesConnectionWhenRightDeviceIsAdded) {
280 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
281 device_whitelist_.get());
283 FindAndExpectStartDiscovery(connection_finder);
284 ExpectStopDiscoveryAndRemoveObserver();
286 PrepareForNewRightDevice(kServiceUUID);
287 connection_finder.ExpectCreateConnection();
288 connection_finder.DeviceAdded(adapter_.get(), device_.get());
291 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
292 Find_DoesntCreateConnectionWhenWrongDeviceIsAdded) {
293 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
294 device_whitelist_.get());
295 FindAndExpectStartDiscovery(connection_finder);
296 ExpectStopDiscoveryAndRemoveObserver();
298 PrepareForNewWrongDevice(kOtherUUID);
299 EXPECT_CALL(connection_finder, CreateConnectionProxy()).Times(0);
300 connection_finder.DeviceAdded(adapter_.get(), device_.get());
303 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
304 Find_CreatesConnectionWhenRightDeviceIsChanged) {
305 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
306 device_whitelist_.get());
308 FindAndExpectStartDiscovery(connection_finder);
309 ExpectStopDiscoveryAndRemoveObserver();
311 PrepareForNewRightDevice(kServiceUUID);
312 connection_finder.ExpectCreateConnection();
313 connection_finder.DeviceChanged(adapter_.get(), device_.get());
316 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
317 Find_DoesntCreateConnectionWhenWrongDeviceIsChanged) {
318 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
319 device_whitelist_.get());
321 FindAndExpectStartDiscovery(connection_finder);
322 ExpectStopDiscoveryAndRemoveObserver();
324 PrepareForNewWrongDevice(kOtherUUID);
325 EXPECT_CALL(connection_finder, CreateConnectionProxy()).Times(0);
326 connection_finder.DeviceChanged(adapter_.get(), device_.get());
329 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
330 Find_CreatesOnlyOneConnection) {
331 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
332 device_whitelist_.get());
333 FindAndExpectStartDiscovery(connection_finder);
334 ExpectStopDiscoveryAndRemoveObserver();
336 // Prepare to add |device_|.
337 PrepareForNewRightDevice(kServiceUUID);
339 // Prepare to add |other_device|.
340 NiceMock<device::MockBluetoothDevice> other_device(
341 adapter_.get(), 0, kDeviceName, kOtherBluetoothAddress, false, false);
342 std::vector<device::BluetoothUUID> uuids;
343 uuids.push_back(device::BluetoothUUID(kServiceUUID));
344 ON_CALL(other_device, IsPaired()).WillByDefault(Return(true));
345 ON_CALL(other_device, GetUUIDs()).WillByDefault((Return(uuids)));
347 // Only one connection should be created.
348 connection_finder.ExpectCreateConnection();
350 // Add the devices.
351 connection_finder.DeviceAdded(adapter_.get(), device_.get());
352 connection_finder.DeviceAdded(adapter_.get(), &other_device);
355 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
356 Find_ConnectionSucceeds) {
357 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
358 device_whitelist_.get());
359 // Starting discovery.
360 FindAndExpectStartDiscovery(connection_finder);
361 ExpectStopDiscoveryAndRemoveObserver();
363 // Finding and creating a connection to the right device.
364 MockConnection* connection = connection_finder.ExpectCreateConnection();
365 PrepareForNewRightDevice(kServiceUUID);
366 connection_finder.DeviceAdded(adapter_.get(), device_.get());
368 // Creating a connection.
369 base::RunLoop run_loop;
370 EXPECT_FALSE(last_found_connection_);
371 connection->SetStatus(Connection::IN_PROGRESS);
372 connection->SetStatus(Connection::CONNECTED);
373 run_loop.RunUntilIdle();
374 EXPECT_TRUE(last_found_connection_);
377 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
378 Find_ConnectionFails_RestartDiscoveryAndConnectionSucceeds) {
379 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
380 device_whitelist_.get());
382 // Starting discovery.
383 FindAndExpectStartDiscovery(connection_finder);
384 base::Closure stop_discovery_session_callback;
385 EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _))
386 .WillOnce(SaveArg<0>(&stop_discovery_session_callback));
388 // Preparing to create a GATT connection to the right device.
389 PrepareForNewRightDevice(kServiceUUID);
390 MockConnection* connection = connection_finder.ExpectCreateConnection();
392 // Trying to create a connection.
393 connection_finder.DeviceAdded(adapter_.get(), device_.get());
394 ASSERT_FALSE(last_found_connection_);
395 connection->SetStatus(Connection::IN_PROGRESS);
397 // Stopping the discovery session.
398 ASSERT_FALSE(stop_discovery_session_callback.is_null());
399 stop_discovery_session_callback.Run();
401 // Preparing to restart the discovery session.
402 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback;
403 std::vector<const device::BluetoothDevice*> devices;
404 ON_CALL(*adapter_, GetDevices()).WillByDefault(Return(devices));
405 EXPECT_CALL(*adapter_, StartDiscoverySessionWithFilterRaw(_, _, _))
406 .WillOnce(SaveArg<1>(&discovery_callback));
408 // Connection fails.
409 connection->SetStatus(Connection::DISCONNECTED);
411 // Restarting the discovery session.
412 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session(
413 new NiceMock<device::MockBluetoothDiscoverySession>());
414 last_discovery_session_alias_ = discovery_session.get();
415 ON_CALL(*last_discovery_session_alias_, IsActive())
416 .WillByDefault(Return(true));
417 ASSERT_FALSE(discovery_callback.is_null());
418 discovery_callback.Run(discovery_session.Pass());
420 // Preparing to create a GATT connection to the right device.
421 PrepareForNewRightDevice(kServiceUUID);
422 connection = connection_finder.ExpectCreateConnection();
424 // Trying to create a connection.
425 connection_finder.DeviceAdded(adapter_.get(), device_.get());
426 EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
428 // Completing the connection.
429 base::RunLoop run_loop;
430 EXPECT_FALSE(last_found_connection_);
431 connection->SetStatus(Connection::IN_PROGRESS);
432 connection->SetStatus(Connection::CONNECTED);
433 run_loop.RunUntilIdle();
434 EXPECT_TRUE(last_found_connection_);
437 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest,
438 Find_AdapterRemoved_RestartDiscoveryAndConnectionSucceeds) {
439 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
440 device_whitelist_.get());
442 // Starting discovery.
443 FindAndExpectStartDiscovery(connection_finder);
445 // Removing the adapter.
446 ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(false));
447 ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(false));
448 ON_CALL(*last_discovery_session_alias_, IsActive())
449 .WillByDefault(Return(false));
450 connection_finder.AdapterPoweredChanged(adapter_.get(), false);
451 connection_finder.AdapterPresentChanged(adapter_.get(), false);
453 // Adding the adapter.
454 ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true));
455 ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true));
457 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback;
458 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session(
459 new NiceMock<device::MockBluetoothDiscoverySession>());
460 last_discovery_session_alias_ = discovery_session.get();
462 // Restarting the discovery session.
463 EXPECT_CALL(*adapter_, StartDiscoverySessionWithFilterRaw(_, _, _))
464 .WillOnce(SaveArg<1>(&discovery_callback));
465 connection_finder.AdapterPresentChanged(adapter_.get(), true);
466 connection_finder.AdapterPoweredChanged(adapter_.get(), true);
467 ON_CALL(*last_discovery_session_alias_, IsActive())
468 .WillByDefault(Return(true));
470 ASSERT_FALSE(discovery_callback.is_null());
471 discovery_callback.Run(discovery_session.Pass());
473 // Preparing to create a GATT connection to the right device.
474 PrepareForNewRightDevice(kServiceUUID);
475 MockConnection* connection = connection_finder.ExpectCreateConnection();
477 // Trying to create a connection.
478 connection_finder.DeviceAdded(adapter_.get(), device_.get());
479 EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
481 // Completing the connection.
482 base::RunLoop run_loop;
483 ASSERT_FALSE(last_found_connection_);
484 connection->SetStatus(Connection::IN_PROGRESS);
485 connection->SetStatus(Connection::CONNECTED);
486 run_loop.RunUntilIdle();
487 EXPECT_TRUE(last_found_connection_);
490 } // namespace proximity_auth