Rename GetIconID to GetIconId
[chromium-blink-merge.git] / components / proximity_auth / bluetooth_connection_unittest.cc
blobfb007bab26131ff091b8597c252211ada18dfb0a
1 // Copyright 2014 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/bluetooth_connection.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/run_loop.h"
10 #include "components/proximity_auth/remote_device.h"
11 #include "components/proximity_auth/wire_message.h"
12 #include "device/bluetooth/bluetooth_adapter_factory.h"
13 #include "device/bluetooth/bluetooth_uuid.h"
14 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
15 #include "device/bluetooth/test/mock_bluetooth_device.h"
16 #include "device/bluetooth/test/mock_bluetooth_socket.h"
17 #include "net/base/io_buffer.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using testing::_;
22 using testing::AnyNumber;
23 using testing::NiceMock;
24 using testing::Ref;
25 using testing::Return;
26 using testing::SaveArg;
27 using testing::StrictMock;
29 namespace proximity_auth {
30 namespace {
32 const char kDeviceName[] = "Device name";
33 const char kOtherDeviceName[] = "Other device name";
35 const char kBluetoothAddress[] = "11:22:33:44:55:66";
36 const char kOtherBluetoothAddress[] = "AA:BB:CC:DD:EE:FF";
38 const char kPublicKey[] = "Public key";
39 const char kPersistentSymmetricKey[] = "PSK";
41 const char kSerializedMessage[] = "Yarrr, this be a serialized message. Yarr!";
42 const int kSerializedMessageLength = strlen(kSerializedMessage);
44 const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF";
46 const int kReceiveBufferSize = 6;
47 const char kReceiveBufferContents[] = "bytes";
49 // Create a buffer for testing received data.
50 scoped_refptr<net::IOBuffer> CreateReceiveBuffer() {
51 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kReceiveBufferSize);
52 memcpy(buffer->data(), kReceiveBufferContents, kReceiveBufferSize);
53 return buffer;
56 class MockBluetoothConnection : public BluetoothConnection {
57 public:
58 MockBluetoothConnection()
59 : BluetoothConnection(CreateRemoteDevice(),
60 device::BluetoothUUID(kUuid)) {}
62 // Calls back into the parent Connection class.
63 MOCK_METHOD1(SetStatusProxy, void(Status status));
64 MOCK_METHOD1(OnBytesReceived, void(const std::string& bytes));
65 MOCK_METHOD2(OnDidSendMessage,
66 void(const WireMessage& message, bool success));
68 void SetStatus(Status status) override {
69 SetStatusProxy(status);
70 BluetoothConnection::SetStatus(status);
73 using BluetoothConnection::status;
74 using BluetoothConnection::Connect;
75 using BluetoothConnection::DeviceRemoved;
76 using BluetoothConnection::Disconnect;
78 private:
79 RemoteDevice CreateRemoteDevice() {
80 return RemoteDevice(kDeviceName, kPublicKey, kBluetoothAddress,
81 kPersistentSymmetricKey);
84 DISALLOW_COPY_AND_ASSIGN(MockBluetoothConnection);
87 class TestWireMessage : public WireMessage {
88 public:
89 TestWireMessage() : WireMessage("permit id", "payload") {}
90 ~TestWireMessage() override {}
92 std::string Serialize() const override { return kSerializedMessage; }
94 private:
95 DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
98 } // namespace
100 class ProximityAuthBluetoothConnectionTest : public testing::Test {
101 public:
102 ProximityAuthBluetoothConnectionTest()
103 : adapter_(new device::MockBluetoothAdapter),
104 device_(adapter_.get(), 0, kDeviceName, kBluetoothAddress, true, true),
105 socket_(new StrictMock<device::MockBluetoothSocket>),
106 uuid_(kUuid) {
107 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
109 // Suppress uninteresting Gmock call warnings.
110 EXPECT_CALL(*adapter_, GetDevice(_)).Times(AnyNumber());
113 // Transition the connection into an in-progress state.
114 void BeginConnecting(MockBluetoothConnection* connection) {
115 EXPECT_EQ(Connection::DISCONNECTED, connection->status());
117 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
118 EXPECT_CALL(*connection, SetStatusProxy(Connection::IN_PROGRESS));
119 EXPECT_CALL(*adapter_, AddObserver(connection));
120 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _));
121 connection->Connect();
123 EXPECT_EQ(Connection::IN_PROGRESS, connection->status());
126 // Transition the connection into a connected state.
127 // Saves the success and error callbacks passed into OnReceive(), which can be
128 // accessed via receive_callback() and receive_success_callback().
129 void Connect(MockBluetoothConnection* connection) {
130 EXPECT_EQ(Connection::DISCONNECTED, connection->status());
132 device::BluetoothDevice::ConnectToServiceCallback callback;
133 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
134 EXPECT_CALL(*connection, SetStatusProxy(Connection::IN_PROGRESS));
135 EXPECT_CALL(*adapter_, AddObserver(connection));
136 EXPECT_CALL(device_, ConnectToServiceInsecurely(_, _, _))
137 .WillOnce(SaveArg<1>(&callback));
138 connection->Connect();
139 ASSERT_FALSE(callback.is_null());
141 EXPECT_CALL(*connection, SetStatusProxy(Connection::CONNECTED));
142 EXPECT_CALL(*socket_, Receive(_, _, _))
143 .WillOnce(DoAll(SaveArg<1>(&receive_callback_),
144 SaveArg<2>(&receive_error_callback_)));
145 callback.Run(socket_);
147 EXPECT_EQ(Connection::CONNECTED, connection->status());
150 device::BluetoothSocket::ReceiveCompletionCallback* receive_callback() {
151 return &receive_callback_;
153 device::BluetoothSocket::ReceiveErrorCompletionCallback*
154 receive_error_callback() {
155 return &receive_error_callback_;
158 protected:
159 // Mocks used for verifying interactions with the Bluetooth subsystem.
160 scoped_refptr<device::MockBluetoothAdapter> adapter_;
161 NiceMock<device::MockBluetoothDevice> device_;
162 scoped_refptr<StrictMock<device::MockBluetoothSocket>> socket_;
164 device::BluetoothUUID uuid_;
166 private:
167 base::MessageLoop message_loop_;
169 device::BluetoothSocket::ReceiveCompletionCallback receive_callback_;
170 device::BluetoothSocket::ReceiveErrorCompletionCallback
171 receive_error_callback_;
174 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasInProgress) {
175 // Create an in-progress connection.
176 StrictMock<MockBluetoothConnection> connection;
177 BeginConnecting(&connection);
179 // A second call to Connect() should be ignored.
180 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
181 connection.Connect();
183 // The connection cleans up after itself upon destruction.
184 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
187 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasConnected) {
188 // Create a connected connection.
189 StrictMock<MockBluetoothConnection> connection;
190 Connect(&connection);
192 // A second call to Connect() should be ignored.
193 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
194 connection.Connect();
196 // The connection disconnects and unregisters as an observer upon destruction.
197 EXPECT_CALL(*socket_, Disconnect(_));
198 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
201 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_NoBluetoothAdapter) {
202 // Some platforms do not support Bluetooth. This test is only meaningful on
203 // those platforms.
204 adapter_ = NULL;
205 if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
206 return;
208 StrictMock<MockBluetoothConnection> connection;
209 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
210 connection.Connect();
213 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_DeviceMissing) {
214 StrictMock<MockBluetoothConnection> connection;
216 ON_CALL(*adapter_, GetDevice(_))
217 .WillByDefault(Return(static_cast<device::BluetoothDevice*>(NULL)));
218 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
219 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
220 connection.Connect();
223 TEST_F(ProximityAuthBluetoothConnectionTest,
224 Connect_DeviceRemovedWhileConnecting) {
225 // Create an in-progress connection.
226 StrictMock<MockBluetoothConnection> connection;
227 BeginConnecting(&connection);
229 // Remove the device while the connection is in-progress. This should cause
230 // the connection to disconnect.
231 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
232 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
233 connection.DeviceRemoved(adapter_.get(), &device_);
236 TEST_F(ProximityAuthBluetoothConnectionTest,
237 Connect_OtherDeviceRemovedWhileConnecting) {
238 // Create an in-progress connection.
239 StrictMock<MockBluetoothConnection> connection;
240 BeginConnecting(&connection);
242 // Remove a device other than the one that is being connected to. This should
243 // not have any effect on the connection.
244 NiceMock<device::MockBluetoothDevice> other_device(
245 adapter_.get(), 0, kOtherDeviceName, kOtherBluetoothAddress, true, true);
246 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
247 connection.DeviceRemoved(adapter_.get(), &other_device);
249 // The connection removes itself as an observer when it is destroyed.
250 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
253 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionFails) {
254 StrictMock<MockBluetoothConnection> connection;
256 device::BluetoothDevice::ConnectToServiceErrorCallback error_callback;
257 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
258 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
259 EXPECT_CALL(*adapter_, AddObserver(&connection));
260 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
261 .WillOnce(SaveArg<2>(&error_callback));
262 connection.Connect();
263 ASSERT_FALSE(error_callback.is_null());
265 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
266 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
267 error_callback.Run("super descriptive error message");
270 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionSucceeds) {
271 StrictMock<MockBluetoothConnection> connection;
272 Connect(&connection);
274 // The connection disconnects and unregisters as an observer upon destruction.
275 EXPECT_CALL(*socket_, Disconnect(_));
276 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
279 TEST_F(ProximityAuthBluetoothConnectionTest,
280 Connect_ConnectionSucceeds_ThenDeviceRemoved) {
281 StrictMock<MockBluetoothConnection> connection;
282 Connect(&connection);
284 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
285 EXPECT_CALL(*socket_, Disconnect(_));
286 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
287 connection.DeviceRemoved(adapter_.get(), &device_);
290 TEST_F(ProximityAuthBluetoothConnectionTest,
291 Connect_ConnectionSucceeds_ReceiveData) {
292 StrictMock<MockBluetoothConnection> connection;
293 Connect(&connection);
294 ASSERT_TRUE(receive_callback() && !receive_callback()->is_null());
296 // Receive some data. Once complete, the connection should re-register to be
297 // ready receive more data.
298 scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
299 EXPECT_CALL(
300 connection,
301 OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
302 EXPECT_CALL(*socket_, Receive(_, _, _));
303 receive_callback()->Run(kReceiveBufferSize, buffer);
304 base::RunLoop run_loop;
305 run_loop.RunUntilIdle();
307 // The connection disconnects and unregisters as an observer upon destruction.
308 EXPECT_CALL(*socket_, Disconnect(_));
309 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
312 TEST_F(ProximityAuthBluetoothConnectionTest,
313 Connect_ConnectionSucceeds_ReceiveDataAfterReceiveError) {
314 StrictMock<MockBluetoothConnection> connection;
315 Connect(&connection);
316 ASSERT_TRUE(receive_error_callback() && !receive_error_callback()->is_null());
318 // Simulate an error while receiving data. The connection should re-register
319 // to be ready receive more data despite the error.
320 device::BluetoothSocket::ReceiveCompletionCallback receive_callback;
321 EXPECT_CALL(*socket_, Receive(_, _, _))
322 .WillOnce(SaveArg<1>(&receive_callback));
323 receive_error_callback()->Run(device::BluetoothSocket::kSystemError,
324 "The system is down. They're taking over!");
325 base::RunLoop run_loop;
326 run_loop.RunUntilIdle();
327 ASSERT_FALSE(receive_callback.is_null());
329 // Receive some data.
330 scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
331 EXPECT_CALL(
332 connection,
333 OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
334 EXPECT_CALL(*socket_, Receive(_, _, _));
335 receive_callback.Run(kReceiveBufferSize, buffer);
336 base::RunLoop run_loop2;
337 run_loop2.RunUntilIdle();
339 // The connection disconnects and unregisters as an observer upon destruction.
340 EXPECT_CALL(*socket_, Disconnect(_));
341 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
344 TEST_F(ProximityAuthBluetoothConnectionTest,
345 Disconnect_ConnectionWasAlreadyDisconnected) {
346 StrictMock<MockBluetoothConnection> connection;
347 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
348 connection.Disconnect();
351 TEST_F(ProximityAuthBluetoothConnectionTest,
352 Disconnect_ConnectionWasInProgress) {
353 // Create an in-progress connection.
354 StrictMock<MockBluetoothConnection> connection;
355 BeginConnecting(&connection);
357 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
358 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
359 connection.Disconnect();
362 TEST_F(ProximityAuthBluetoothConnectionTest,
363 Disconnect_ConnectionWasConnected) {
364 // Create a connected connection.
365 StrictMock<MockBluetoothConnection> connection;
366 Connect(&connection);
368 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
369 EXPECT_CALL(*socket_, Disconnect(_));
370 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
371 connection.Disconnect();
374 TEST_F(ProximityAuthBluetoothConnectionTest,
375 Connect_ThenDisconnectWhileInProgress_ThenBackingConnectionSucceeds) {
376 StrictMock<MockBluetoothConnection> connection;
377 device::BluetoothDevice::ConnectToServiceCallback callback;
378 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
379 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
380 EXPECT_CALL(*adapter_, AddObserver(&connection));
381 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
382 .WillOnce(SaveArg<1>(&callback));
383 connection.Connect();
384 ASSERT_FALSE(callback.is_null());
386 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
387 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
388 connection.Disconnect();
390 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
391 EXPECT_CALL(*socket_, Receive(_, _, _)).Times(0);
392 callback.Run(socket_);
395 TEST_F(ProximityAuthBluetoothConnectionTest,
396 SendMessage_SendsExpectedDataOverTheWire) {
397 // Create a connected connection.
398 StrictMock<MockBluetoothConnection> connection;
399 Connect(&connection);
401 scoped_refptr<net::IOBuffer> buffer;
402 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
403 EXPECT_CALL(*socket_, Send(_, kSerializedMessageLength, _, _))
404 .WillOnce(SaveArg<0>(&buffer));
405 connection.SendMessage(wire_message.Pass());
406 ASSERT_TRUE(buffer.get());
407 EXPECT_EQ(kSerializedMessage,
408 std::string(buffer->data(), kSerializedMessageLength));
410 // The connection disconnects and unregisters as an observer upon destruction.
411 EXPECT_CALL(*socket_, Disconnect(_));
412 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
415 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Success) {
416 // Create a connected connection.
417 StrictMock<MockBluetoothConnection> connection;
418 Connect(&connection);
420 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
421 // Ownership will be transfered below, so grab a reference here.
422 TestWireMessage* expected_wire_message = wire_message.get();
424 device::BluetoothSocket::SendCompletionCallback callback;
425 EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<2>(&callback));
426 connection.SendMessage(wire_message.Pass());
427 ASSERT_FALSE(callback.is_null());
429 EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), true));
430 callback.Run(kSerializedMessageLength);
432 // The connection disconnects and unregisters as an observer upon destruction.
433 EXPECT_CALL(*socket_, Disconnect(_));
434 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
437 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Failure) {
438 // Create a connected connection.
439 StrictMock<MockBluetoothConnection> connection;
440 Connect(&connection);
442 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
443 // Ownership will be transfered below, so grab a reference here.
444 TestWireMessage* expected_wire_message = wire_message.get();
446 device::BluetoothSocket::ErrorCompletionCallback error_callback;
447 EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<3>(&error_callback));
448 connection.SendMessage(wire_message.Pass());
450 ASSERT_FALSE(error_callback.is_null());
451 EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), false));
452 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
453 EXPECT_CALL(*socket_, Disconnect(_));
454 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
455 error_callback.Run("The most helpful of error messages");
458 } // namespace proximity_auth