OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h " | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/time/time.h" | |
11 #include "components/proximity_auth/connection.h" | |
12 #include "components/proximity_auth/remote_device.h" | |
13 #include "components/proximity_auth/wire_message.h" | |
14 #include "device/bluetooth/bluetooth_adapter_factory.h" | |
15 #include "device/bluetooth/bluetooth_uuid.h" | |
16 #include "device/bluetooth/test/mock_bluetooth_adapter.h" | |
17 #include "device/bluetooth/test/mock_bluetooth_device.h" | |
18 #include "device/bluetooth/test/mock_bluetooth_discovery_session.h" | |
19 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::_; | |
24 using testing::NiceMock; | |
25 using testing::Return; | |
26 using testing::StrictMock; | |
27 using testing::SaveArg; | |
28 | |
29 namespace proximity_auth { | |
30 namespace { | |
31 | |
32 const char kDeviceName[] = "Device name"; | |
33 const char kBluetoothAddress[] = "11:22:33:44:55:66"; | |
34 const RemoteDevice kRemoteDevice = {kDeviceName, kBluetoothAddress}; | |
35 | |
36 const char kServiceUUID[] = "1EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; | |
37 const char kToPeripheralCharUUID[] = "2EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; | |
38 const char kFromPeripheralCharUUID[] = "3EADBEEF-CAFE-FEED-FOOD-D15EA5EBEEEF"; | |
39 | |
40 const char kOtherUUID[] = "AAAAAAAA-AAAA-AAAA-AAAA-D15EA5EBEEEF"; | |
41 const char kOtherBluetoothAddress[] = "00:00:00:00:00:00"; | |
42 | |
43 class MockConnection : public Connection { | |
44 public: | |
45 MockConnection() : Connection(kRemoteDevice) {} | |
46 ~MockConnection() override {} | |
47 | |
48 MOCK_METHOD0(Connect, void()); | |
49 | |
50 using Connection::SetStatus; | |
51 | |
52 private: | |
53 void Disconnect() override {} | |
54 void SendMessageImpl(scoped_ptr<WireMessage> message) override {} | |
55 | |
56 DISALLOW_COPY_AND_ASSIGN(MockConnection); | |
57 }; | |
58 | |
59 class MockBluetoothLowEnergyConnectionFinder | |
60 : public BluetoothLowEnergyConnectionFinder { | |
61 public: | |
62 MockBluetoothLowEnergyConnectionFinder() | |
63 : BluetoothLowEnergyConnectionFinder(kServiceUUID, | |
64 kToPeripheralCharUUID, | |
65 kFromPeripheralCharUUID) {} | |
66 ~MockBluetoothLowEnergyConnectionFinder() override {} | |
67 | |
68 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
| |
69 | |
70 // Creates a mock connection and sets an expectation that the mock connection | |
71 // finder's CreateConnection() method will be called and will return the | |
72 // created connection. Returns a reference to the created connection. | |
73 // NOTE: The returned connection's lifetime is managed by the connection | |
74 // finder. | |
75 MockConnection* ExpectCreateConnection() { | |
76 scoped_ptr<MockConnection> connection(new NiceMock<MockConnection>()); | |
77 MockConnection* connection_alias = connection.get(); | |
78 EXPECT_CALL(*this, CreateConnectionProxy()) | |
79 .WillOnce(Return(connection.release())); | |
80 return connection_alias; | |
81 } | |
82 | |
83 protected: | |
84 scoped_ptr<Connection> CreateConnection( | |
85 scoped_ptr<device::BluetoothGattConnection> gatt_connection) override { | |
86 return make_scoped_ptr(CreateConnectionProxy()); | |
87 } | |
88 | |
89 private: | |
90 DISALLOW_COPY_AND_ASSIGN(MockBluetoothLowEnergyConnectionFinder); | |
91 }; | |
92 | |
93 } // namespace | |
94 | |
95 class ProximityAuthBluetoothLowEnergyConnectionFinderTest | |
96 : public testing::Test { | |
97 protected: | |
98 ProximityAuthBluetoothLowEnergyConnectionFinderTest() | |
99 : adapter_(new NiceMock<device::MockBluetoothAdapter>), | |
100 connection_callback_( | |
101 base::Bind(&ProximityAuthBluetoothLowEnergyConnectionFinderTest:: | |
102 OnConnectionFound, | |
103 base::Unretained(this))), | |
104 device_(new NiceMock<device::MockBluetoothDevice>(adapter_.get(), | |
105 0, | |
106 kDeviceName, | |
107 kBluetoothAddress, | |
108 false, | |
109 false)) { | |
110 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_); | |
111 | |
112 ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true)); | |
113 ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true)); | |
114 } | |
115 | |
116 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.
| |
117 void OnConnectionFound(scoped_ptr<Connection> connection) { | |
118 OnConnectionFoundProxy(connection.get()); | |
119 last_found_connection_ = connection.Pass(); | |
120 } | |
121 | |
122 scoped_refptr<device::MockBluetoothAdapter> adapter_; | |
123 ConnectionFinder::ConnectionCallback connection_callback_; | |
124 | |
125 protected: | |
126 scoped_ptr<device::MockBluetoothDevice> device_; | |
127 | |
128 private: | |
129 // Save a pointer to the last found connection, to extend its lifetime. | |
130 scoped_ptr<Connection> last_found_connection_; | |
131 }; | |
132 | |
133 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
134 ConstructAndDestroyDoesntCrash) { | |
135 // Destroying a BluetoothConnectionFinder for which Find() has not been called | |
136 // should not crash. | |
137 BluetoothLowEnergyConnectionFinder connection_finder( | |
138 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
139 } | |
140 | |
141 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
142 Find_StartsDiscoverySession) { | |
143 BluetoothLowEnergyConnectionFinder connection_finder( | |
144 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
145 | |
146 EXPECT_CALL(*adapter_, StartDiscoverySession(_, _)); | |
147 EXPECT_CALL(*adapter_, AddObserver(_)); | |
148 connection_finder.Find(connection_callback_); | |
149 } | |
150 | |
151 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
152 Find_StopsDiscoverySessionBeforeDestroying) { | |
153 BluetoothLowEnergyConnectionFinder connection_finder( | |
154 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
155 | |
156 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback; | |
157 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session( | |
158 new NiceMock<device::MockBluetoothDiscoverySession>()); | |
159 device::MockBluetoothDiscoverySession* discovery_session_alias = | |
160 discovery_session.get(); | |
161 | |
162 EXPECT_CALL(*adapter_, StartDiscoverySession(_, _)) | |
163 .WillOnce(SaveArg<0>(&discovery_callback)); | |
164 ON_CALL(*discovery_session_alias, IsActive()).WillByDefault(Return(true)); | |
165 EXPECT_CALL(*adapter_, AddObserver(_)); | |
166 connection_finder.Find(connection_callback_); | |
167 | |
168 EXPECT_CALL(*discovery_session_alias, Stop(_, _)); | |
169 ASSERT_FALSE(discovery_callback.is_null()); | |
170 discovery_callback.Run(discovery_session.Pass()); | |
171 | |
172 EXPECT_CALL(*adapter_, RemoveObserver(_)); | |
173 } | |
174 | |
175 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
176 Find_CreatesGattConnectionWhenRightDeviceIsAdded) { | |
177 BluetoothLowEnergyConnectionFinder connection_finder( | |
178 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
179 | |
180 std::vector<device::BluetoothUUID> uuids; | |
181 uuids.push_back(device::BluetoothUUID(kServiceUUID)); | |
182 | |
183 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
184 EXPECT_CALL(*device_, CreateGattConnection(_, _)); | |
185 connection_finder.DeviceAdded(adapter_.get(), device_.get()); | |
186 } | |
187 | |
188 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
189 Find_DoesntCreateGattConnectionWhenWrongDeviceIsAdded) { | |
190 BluetoothLowEnergyConnectionFinder connection_finder( | |
191 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
192 | |
193 std::vector<device::BluetoothUUID> uuids; | |
194 uuids.push_back(device::BluetoothUUID(kOtherUUID)); | |
195 | |
196 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
197 EXPECT_CALL(*device_, CreateGattConnection(_, _)).Times(0); | |
198 connection_finder.DeviceAdded(adapter_.get(), device_.get()); | |
199 } | |
200 | |
201 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
202 Find_CreatesGattConnectionWhenRightDeviceIsChanged) { | |
203 BluetoothLowEnergyConnectionFinder connection_finder( | |
204 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
205 | |
206 std::vector<device::BluetoothUUID> uuids; | |
207 uuids.push_back(device::BluetoothUUID(kServiceUUID)); | |
208 | |
209 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
210 EXPECT_CALL(*device_, CreateGattConnection(_, _)); | |
211 connection_finder.DeviceChanged(adapter_.get(), device_.get()); | |
212 } | |
213 | |
214 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
215 Find_DoesntCreateGattConnectionWhenWrongDeviceIsChanged) { | |
216 BluetoothLowEnergyConnectionFinder connection_finder( | |
217 kServiceUUID, kToPeripheralCharUUID, kFromPeripheralCharUUID); | |
218 | |
219 std::vector<device::BluetoothUUID> uuids; | |
220 uuids.push_back(device::BluetoothUUID(kOtherUUID)); | |
221 | |
222 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
223 EXPECT_CALL(*device_, CreateGattConnection(_, _)).Times(0); | |
224 connection_finder.DeviceChanged(adapter_.get(), device_.get()); | |
225 } | |
226 | |
227 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
228 Find_CreatesTwoGattConnections) { | |
229 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder; | |
230 connection_finder.ExpectCreateConnection(); | |
231 connection_finder.Find(connection_callback_); | |
232 | |
233 std::vector<device::BluetoothUUID> uuids; | |
234 uuids.push_back(device::BluetoothUUID(kServiceUUID)); | |
235 NiceMock<device::MockBluetoothDevice> other_device( | |
236 adapter_.get(), 0, kDeviceName, kOtherBluetoothAddress, false, false); | |
237 | |
238 ON_CALL(other_device, GetUUIDs()).WillByDefault((Return(uuids))); | |
239 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
240 | |
241 device::BluetoothDevice::GattConnectionCallback gatt_connection_callback, | |
242 other_gatt_connection_callback; | |
243 EXPECT_CALL(*device_, CreateGattConnection(_, _)) | |
244 .WillOnce(SaveArg<0>(&gatt_connection_callback)); | |
245 EXPECT_CALL(other_device, CreateGattConnection(_, _)) | |
246 .WillOnce(SaveArg<0>(&other_gatt_connection_callback)); | |
247 | |
248 connection_finder.DeviceAdded(adapter_.get(), device_.get()); | |
249 connection_finder.DeviceAdded(adapter_.get(), &other_device); | |
250 | |
251 ASSERT_FALSE(gatt_connection_callback.is_null()); | |
252 ASSERT_FALSE(other_gatt_connection_callback.is_null()); | |
253 | |
254 gatt_connection_callback.Run(make_scoped_ptr( | |
255 new NiceMock<device::MockBluetoothGattConnection>(kBluetoothAddress))); | |
256 | |
257 // The second device should be forget | |
258 EXPECT_CALL(*adapter_, GetDevice(std::string(kOtherBluetoothAddress))) | |
259 .WillOnce(Return(&other_device)); | |
260 EXPECT_CALL(other_device, Forget(_)); | |
261 other_gatt_connection_callback.Run( | |
262 make_scoped_ptr(new NiceMock<device::MockBluetoothGattConnection>( | |
263 kOtherBluetoothAddress))); | |
264 } | |
265 | |
266 TEST_F(ProximityAuthBluetoothLowEnergyConnectionFinderTest, | |
267 Find_ConnectionSucceeds) { | |
268 StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder; | |
269 | |
270 device::BluetoothAdapter::DiscoverySessionCallback discovery_callback; | |
271 scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session( | |
272 new NiceMock<device::MockBluetoothDiscoverySession>()); | |
273 device::MockBluetoothDiscoverySession* discovery_session_alias = | |
274 discovery_session.get(); | |
275 | |
276 // Starting a discovery session | |
277 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.
| |
278 .WillOnce(SaveArg<0>(&discovery_callback)); | |
279 EXPECT_CALL(*adapter_, AddObserver(_)); | |
280 ON_CALL(*discovery_session_alias, IsActive()).WillByDefault(Return(true)); | |
281 connection_finder.Find(connection_callback_); | |
282 ASSERT_FALSE(discovery_callback.is_null()); | |
283 discovery_callback.Run(discovery_session.Pass()); | |
284 | |
285 // Finding and creating a GATT connection to the right device | |
286 std::vector<device::BluetoothUUID> uuids; | |
287 uuids.push_back(device::BluetoothUUID(kServiceUUID)); | |
288 device::BluetoothDevice::GattConnectionCallback gatt_connection_callback; | |
289 | |
290 ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids)); | |
291 EXPECT_CALL(*device_, CreateGattConnection(_, _)) | |
292 .WillOnce(SaveArg<0>(&gatt_connection_callback)); | |
293 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.
| |
294 | |
295 // Creating a connection | |
296 MockConnection* connection = connection_finder.ExpectCreateConnection(); | |
297 ASSERT_FALSE(gatt_connection_callback.is_null()); | |
298 gatt_connection_callback.Run(make_scoped_ptr( | |
299 new NiceMock<device::MockBluetoothGattConnection>(kBluetoothAddress))); | |
300 connection->SetStatus(Connection::IN_PROGRESS); | |
301 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
| |
302 connection->SetStatus(Connection::CONNECTED); | |
303 | |
304 // Cleaning up | |
305 EXPECT_CALL(*discovery_session_alias, Stop(_, _)); | |
306 EXPECT_CALL(*adapter_, RemoveObserver(_)); | |
307 } | |
308 | |
309 } // namespace proximity_auth | |
OLD | NEW |