Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / components / proximity_auth / bluetooth_connection_unittest.cc
bloba30d08c5e800573de5e1f1d51c0315282d3ab559
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 kSerializedMessage[] = "Yarrr, this be a serialized message. Yarr!";
39 const int kSerializedMessageLength = strlen(kSerializedMessage);
41 const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF";
43 const RemoteDevice kRemoteDevice = {kDeviceName, kBluetoothAddress};
45 const int kReceiveBufferSize = 6;
46 const char kReceiveBufferContents[] = "bytes";
48 // Create a buffer for testing received data.
49 scoped_refptr<net::IOBuffer> CreateReceiveBuffer() {
50 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kReceiveBufferSize);
51 memcpy(buffer->data(), kReceiveBufferContents, kReceiveBufferSize);
52 return buffer;
55 class MockBluetoothConnection : public BluetoothConnection {
56 public:
57 MockBluetoothConnection()
58 : BluetoothConnection(kRemoteDevice, device::BluetoothUUID(kUuid)) {}
60 // Calls back into the parent Connection class.
61 MOCK_METHOD1(SetStatusProxy, void(Status status));
62 MOCK_METHOD1(OnBytesReceived, void(const std::string& bytes));
63 MOCK_METHOD2(OnDidSendMessage,
64 void(const WireMessage& message, bool success));
66 virtual void SetStatus(Status status) override {
67 SetStatusProxy(status);
68 BluetoothConnection::SetStatus(status);
71 using BluetoothConnection::status;
72 using BluetoothConnection::Connect;
73 using BluetoothConnection::DeviceRemoved;
74 using BluetoothConnection::Disconnect;
76 private:
77 DISALLOW_COPY_AND_ASSIGN(MockBluetoothConnection);
80 class TestWireMessage : public WireMessage {
81 public:
82 TestWireMessage() : WireMessage("permit id", "payload") {}
83 ~TestWireMessage() override {}
85 std::string Serialize() const override { return kSerializedMessage; }
87 private:
88 DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
91 } // namespace
93 class ProximityAuthBluetoothConnectionTest : public testing::Test {
94 public:
95 ProximityAuthBluetoothConnectionTest()
96 : adapter_(new device::MockBluetoothAdapter),
97 device_(adapter_.get(), 0, kDeviceName, kBluetoothAddress, true, true),
98 socket_(new StrictMock<device::MockBluetoothSocket>),
99 uuid_(kUuid) {
100 device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
102 // Suppress uninteresting Gmock call warnings.
103 EXPECT_CALL(*adapter_, GetDevice(_)).Times(AnyNumber());
106 // Transition the connection into an in-progress state.
107 void BeginConnecting(MockBluetoothConnection* connection) {
108 EXPECT_EQ(Connection::DISCONNECTED, connection->status());
110 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
111 EXPECT_CALL(*connection, SetStatusProxy(Connection::IN_PROGRESS));
112 EXPECT_CALL(*adapter_, AddObserver(connection));
113 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _));
114 connection->Connect();
116 EXPECT_EQ(Connection::IN_PROGRESS, connection->status());
119 // Transition the connection into a connected state.
120 // Saves the success and error callbacks passed into OnReceive(), which can be
121 // accessed via receive_callback() and receive_success_callback().
122 void Connect(MockBluetoothConnection* connection) {
123 EXPECT_EQ(Connection::DISCONNECTED, connection->status());
125 device::BluetoothDevice::ConnectToServiceCallback callback;
126 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
127 EXPECT_CALL(*connection, SetStatusProxy(Connection::IN_PROGRESS));
128 EXPECT_CALL(*adapter_, AddObserver(connection));
129 EXPECT_CALL(device_, ConnectToServiceInsecurely(_, _, _))
130 .WillOnce(SaveArg<1>(&callback));
131 connection->Connect();
132 ASSERT_FALSE(callback.is_null());
134 EXPECT_CALL(*connection, SetStatusProxy(Connection::CONNECTED));
135 EXPECT_CALL(*socket_, Receive(_, _, _))
136 .WillOnce(DoAll(SaveArg<1>(&receive_callback_),
137 SaveArg<2>(&receive_error_callback_)));
138 callback.Run(socket_);
140 EXPECT_EQ(Connection::CONNECTED, connection->status());
143 device::BluetoothSocket::ReceiveCompletionCallback* receive_callback() {
144 return &receive_callback_;
146 device::BluetoothSocket::ReceiveErrorCompletionCallback*
147 receive_error_callback() {
148 return &receive_error_callback_;
151 protected:
152 // Mocks used for verifying interactions with the Bluetooth subsystem.
153 scoped_refptr<device::MockBluetoothAdapter> adapter_;
154 NiceMock<device::MockBluetoothDevice> device_;
155 scoped_refptr<StrictMock<device::MockBluetoothSocket>> socket_;
157 device::BluetoothUUID uuid_;
159 private:
160 base::MessageLoop message_loop_;
162 device::BluetoothSocket::ReceiveCompletionCallback receive_callback_;
163 device::BluetoothSocket::ReceiveErrorCompletionCallback
164 receive_error_callback_;
167 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasInProgress) {
168 // Create an in-progress connection.
169 StrictMock<MockBluetoothConnection> connection;
170 BeginConnecting(&connection);
172 // A second call to Connect() should be ignored.
173 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
174 connection.Connect();
176 // The connection cleans up after itself upon destruction.
177 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
180 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasConnected) {
181 // Create a connected connection.
182 StrictMock<MockBluetoothConnection> connection;
183 Connect(&connection);
185 // A second call to Connect() should be ignored.
186 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
187 connection.Connect();
189 // The connection disconnects and unregisters as an observer upon destruction.
190 EXPECT_CALL(*socket_, Disconnect(_));
191 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
194 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_NoBluetoothAdapter) {
195 // Some platforms do not support Bluetooth. This test is only meaningful on
196 // those platforms.
197 adapter_ = NULL;
198 if (device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
199 return;
201 StrictMock<MockBluetoothConnection> connection;
202 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
203 connection.Connect();
206 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_DeviceMissing) {
207 StrictMock<MockBluetoothConnection> connection;
209 ON_CALL(*adapter_, GetDevice(_))
210 .WillByDefault(Return(static_cast<device::BluetoothDevice*>(NULL)));
211 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
212 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
213 connection.Connect();
216 TEST_F(ProximityAuthBluetoothConnectionTest,
217 Connect_DeviceRemovedWhileConnecting) {
218 // Create an in-progress connection.
219 StrictMock<MockBluetoothConnection> connection;
220 BeginConnecting(&connection);
222 // Remove the device while the connection is in-progress. This should cause
223 // the connection to disconnect.
224 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
225 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
226 connection.DeviceRemoved(adapter_.get(), &device_);
229 TEST_F(ProximityAuthBluetoothConnectionTest,
230 Connect_OtherDeviceRemovedWhileConnecting) {
231 // Create an in-progress connection.
232 StrictMock<MockBluetoothConnection> connection;
233 BeginConnecting(&connection);
235 // Remove a device other than the one that is being connected to. This should
236 // not have any effect on the connection.
237 NiceMock<device::MockBluetoothDevice> other_device(
238 adapter_.get(), 0, kOtherDeviceName, kOtherBluetoothAddress, true, true);
239 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
240 connection.DeviceRemoved(adapter_.get(), &other_device);
242 // The connection removes itself as an observer when it is destroyed.
243 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
246 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionFails) {
247 StrictMock<MockBluetoothConnection> connection;
249 device::BluetoothDevice::ConnectToServiceErrorCallback error_callback;
250 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
251 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
252 EXPECT_CALL(*adapter_, AddObserver(&connection));
253 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
254 .WillOnce(SaveArg<2>(&error_callback));
255 connection.Connect();
256 ASSERT_FALSE(error_callback.is_null());
258 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
259 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
260 error_callback.Run("super descriptive error message");
263 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionSucceeds) {
264 StrictMock<MockBluetoothConnection> connection;
265 Connect(&connection);
267 // The connection disconnects and unregisters as an observer upon destruction.
268 EXPECT_CALL(*socket_, Disconnect(_));
269 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
272 TEST_F(ProximityAuthBluetoothConnectionTest,
273 Connect_ConnectionSucceeds_ThenDeviceRemoved) {
274 StrictMock<MockBluetoothConnection> connection;
275 Connect(&connection);
277 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
278 EXPECT_CALL(*socket_, Disconnect(_));
279 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
280 connection.DeviceRemoved(adapter_.get(), &device_);
283 TEST_F(ProximityAuthBluetoothConnectionTest,
284 Connect_ConnectionSucceeds_ReceiveData) {
285 StrictMock<MockBluetoothConnection> connection;
286 Connect(&connection);
287 ASSERT_TRUE(receive_callback() && !receive_callback()->is_null());
289 // Receive some data. Once complete, the connection should re-register to be
290 // ready receive more data.
291 scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
292 EXPECT_CALL(
293 connection,
294 OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
295 EXPECT_CALL(*socket_, Receive(_, _, _));
296 receive_callback()->Run(kReceiveBufferSize, buffer);
297 base::RunLoop run_loop;
298 run_loop.RunUntilIdle();
300 // The connection disconnects and unregisters as an observer upon destruction.
301 EXPECT_CALL(*socket_, Disconnect(_));
302 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
305 TEST_F(ProximityAuthBluetoothConnectionTest,
306 Connect_ConnectionSucceeds_ReceiveDataAfterReceiveError) {
307 StrictMock<MockBluetoothConnection> connection;
308 Connect(&connection);
309 ASSERT_TRUE(receive_error_callback() && !receive_error_callback()->is_null());
311 // Simulate an error while receiving data. The connection should re-register
312 // to be ready receive more data despite the error.
313 device::BluetoothSocket::ReceiveCompletionCallback receive_callback;
314 EXPECT_CALL(*socket_, Receive(_, _, _))
315 .WillOnce(SaveArg<1>(&receive_callback));
316 receive_error_callback()->Run(device::BluetoothSocket::kSystemError,
317 "The system is down. They're taking over!");
318 base::RunLoop run_loop;
319 run_loop.RunUntilIdle();
320 ASSERT_FALSE(receive_callback.is_null());
322 // Receive some data.
323 scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
324 EXPECT_CALL(
325 connection,
326 OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
327 EXPECT_CALL(*socket_, Receive(_, _, _));
328 receive_callback.Run(kReceiveBufferSize, buffer);
329 base::RunLoop run_loop2;
330 run_loop2.RunUntilIdle();
332 // The connection disconnects and unregisters as an observer upon destruction.
333 EXPECT_CALL(*socket_, Disconnect(_));
334 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
337 TEST_F(ProximityAuthBluetoothConnectionTest,
338 Disconnect_ConnectionWasAlreadyDisconnected) {
339 StrictMock<MockBluetoothConnection> connection;
340 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
341 connection.Disconnect();
344 TEST_F(ProximityAuthBluetoothConnectionTest,
345 Disconnect_ConnectionWasInProgress) {
346 // Create an in-progress connection.
347 StrictMock<MockBluetoothConnection> connection;
348 BeginConnecting(&connection);
350 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
351 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
352 connection.Disconnect();
355 TEST_F(ProximityAuthBluetoothConnectionTest,
356 Disconnect_ConnectionWasConnected) {
357 // Create a connected connection.
358 StrictMock<MockBluetoothConnection> connection;
359 Connect(&connection);
361 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
362 EXPECT_CALL(*socket_, Disconnect(_));
363 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
364 connection.Disconnect();
367 TEST_F(ProximityAuthBluetoothConnectionTest,
368 Connect_ThenDisconnectWhileInProgress_ThenBackingConnectionSucceeds) {
369 StrictMock<MockBluetoothConnection> connection;
370 device::BluetoothDevice::ConnectToServiceCallback callback;
371 ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
372 EXPECT_CALL(connection, SetStatusProxy(Connection::IN_PROGRESS));
373 EXPECT_CALL(*adapter_, AddObserver(&connection));
374 EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
375 .WillOnce(SaveArg<1>(&callback));
376 connection.Connect();
377 ASSERT_FALSE(callback.is_null());
379 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
380 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
381 connection.Disconnect();
383 EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
384 EXPECT_CALL(*socket_, Receive(_, _, _)).Times(0);
385 callback.Run(socket_);
388 TEST_F(ProximityAuthBluetoothConnectionTest,
389 SendMessage_SendsExpectedDataOverTheWire) {
390 // Create a connected connection.
391 StrictMock<MockBluetoothConnection> connection;
392 Connect(&connection);
394 scoped_refptr<net::IOBuffer> buffer;
395 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
396 EXPECT_CALL(*socket_, Send(_, kSerializedMessageLength, _, _))
397 .WillOnce(SaveArg<0>(&buffer));
398 connection.SendMessage(wire_message.Pass());
399 ASSERT_TRUE(buffer.get());
400 EXPECT_EQ(kSerializedMessage,
401 std::string(buffer->data(), kSerializedMessageLength));
403 // The connection disconnects and unregisters as an observer upon destruction.
404 EXPECT_CALL(*socket_, Disconnect(_));
405 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
408 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Success) {
409 // Create a connected connection.
410 StrictMock<MockBluetoothConnection> connection;
411 Connect(&connection);
413 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
414 // Ownership will be transfered below, so grab a reference here.
415 TestWireMessage* expected_wire_message = wire_message.get();
417 device::BluetoothSocket::SendCompletionCallback callback;
418 EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<2>(&callback));
419 connection.SendMessage(wire_message.Pass());
420 ASSERT_FALSE(callback.is_null());
422 EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), true));
423 callback.Run(kSerializedMessageLength);
425 // The connection disconnects and unregisters as an observer upon destruction.
426 EXPECT_CALL(*socket_, Disconnect(_));
427 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
430 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Failure) {
431 // Create a connected connection.
432 StrictMock<MockBluetoothConnection> connection;
433 Connect(&connection);
435 scoped_ptr<TestWireMessage> wire_message(new TestWireMessage);
436 // Ownership will be transfered below, so grab a reference here.
437 TestWireMessage* expected_wire_message = wire_message.get();
439 device::BluetoothSocket::ErrorCompletionCallback error_callback;
440 EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<3>(&error_callback));
441 connection.SendMessage(wire_message.Pass());
443 ASSERT_FALSE(error_callback.is_null());
444 EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), false));
445 EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
446 EXPECT_CALL(*socket_, Disconnect(_));
447 EXPECT_CALL(*adapter_, RemoveObserver(&connection));
448 error_callback.Run("The most helpful of error messages");
451 } // namespace proximity_auth