Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / proximity_auth / bluetooth_connection_unittest.cc
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.
4
5 #include "components/proximity_auth/bluetooth_connection.h"
6
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"
20
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;
28
29 namespace proximity_auth {
30 namespace {
31
32 const char kDeviceName[] = "Device name";
33 const char kOtherDeviceName[] = "Other device name";
34
35 const char kBluetoothAddress[] = "11:22:33:44:55:66";
36 const char kOtherBluetoothAddress[] = "AA:BB:CC:DD:EE:FF";
37
38 const char kSerializedMessage[] = "Yarrr, this be a serialized message. Yarr!";
39 const int kSerializedMessageLength = strlen(kSerializedMessage);
40
41 const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF";
42
43 const RemoteDevice kRemoteDevice = {kDeviceName, kBluetoothAddress};
44
45 const int kReceiveBufferSize = 6;
46 const char kReceiveBufferContents[] = "bytes";
47
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;
53 }
54
55 class MockBluetoothConnection : public BluetoothConnection {
56  public:
57   MockBluetoothConnection()
58       : BluetoothConnection(kRemoteDevice, device::BluetoothUUID(kUuid)) {}
59
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));
65
66   virtual void SetStatus(Status status) override {
67     SetStatusProxy(status);
68     BluetoothConnection::SetStatus(status);
69   }
70
71   using BluetoothConnection::status;
72   using BluetoothConnection::Connect;
73   using BluetoothConnection::DeviceRemoved;
74   using BluetoothConnection::Disconnect;
75
76  private:
77   DISALLOW_COPY_AND_ASSIGN(MockBluetoothConnection);
78 };
79
80 class TestWireMessage : public WireMessage {
81  public:
82   TestWireMessage() : WireMessage("permit id", "payload") {}
83   ~TestWireMessage() override {}
84
85   std::string Serialize() const override { return kSerializedMessage; }
86
87  private:
88   DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
89 };
90
91 }  // namespace
92
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_);
101
102     // Suppress uninteresting Gmock call warnings.
103     EXPECT_CALL(*adapter_, GetDevice(_)).Times(AnyNumber());
104   }
105
106   // Transition the connection into an in-progress state.
107   void BeginConnecting(MockBluetoothConnection* connection) {
108     EXPECT_EQ(Connection::DISCONNECTED, connection->status());
109
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();
115
116     EXPECT_EQ(Connection::IN_PROGRESS, connection->status());
117   }
118
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());
124
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());
133
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_);
139
140     EXPECT_EQ(Connection::CONNECTED, connection->status());
141   }
142
143   device::BluetoothSocket::ReceiveCompletionCallback* receive_callback() {
144     return &receive_callback_;
145   }
146   device::BluetoothSocket::ReceiveErrorCompletionCallback*
147   receive_error_callback() {
148     return &receive_error_callback_;
149   }
150
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_;
156
157   device::BluetoothUUID uuid_;
158
159  private:
160   base::MessageLoop message_loop_;
161
162   device::BluetoothSocket::ReceiveCompletionCallback receive_callback_;
163   device::BluetoothSocket::ReceiveErrorCompletionCallback
164       receive_error_callback_;
165 };
166
167 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasInProgress) {
168   // Create an in-progress connection.
169   StrictMock<MockBluetoothConnection> connection;
170   BeginConnecting(&connection);
171
172   // A second call to Connect() should be ignored.
173   EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
174   connection.Connect();
175
176   // The connection cleans up after itself upon destruction.
177   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
178 }
179
180 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasConnected) {
181   // Create a connected connection.
182   StrictMock<MockBluetoothConnection> connection;
183   Connect(&connection);
184
185   // A second call to Connect() should be ignored.
186   EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
187   connection.Connect();
188
189   // The connection disconnects and unregisters as an observer upon destruction.
190   EXPECT_CALL(*socket_, Disconnect(_));
191   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
192 }
193
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;
200
201   StrictMock<MockBluetoothConnection> connection;
202   EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
203   connection.Connect();
204 }
205
206 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_DeviceMissing) {
207   StrictMock<MockBluetoothConnection> connection;
208
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();
214 }
215
216 TEST_F(ProximityAuthBluetoothConnectionTest,
217        Connect_DeviceRemovedWhileConnecting) {
218   // Create an in-progress connection.
219   StrictMock<MockBluetoothConnection> connection;
220   BeginConnecting(&connection);
221
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_);
227 }
228
229 TEST_F(ProximityAuthBluetoothConnectionTest,
230        Connect_OtherDeviceRemovedWhileConnecting) {
231   // Create an in-progress connection.
232   StrictMock<MockBluetoothConnection> connection;
233   BeginConnecting(&connection);
234
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);
241
242   // The connection removes itself as an observer when it is destroyed.
243   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
244 }
245
246 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionFails) {
247   StrictMock<MockBluetoothConnection> connection;
248
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());
257
258   EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
259   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
260   error_callback.Run("super descriptive error message");
261 }
262
263 TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionSucceeds) {
264   StrictMock<MockBluetoothConnection> connection;
265   Connect(&connection);
266
267   // The connection disconnects and unregisters as an observer upon destruction.
268   EXPECT_CALL(*socket_, Disconnect(_));
269   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
270 }
271
272 TEST_F(ProximityAuthBluetoothConnectionTest,
273        Connect_ConnectionSucceeds_ThenDeviceRemoved) {
274   StrictMock<MockBluetoothConnection> connection;
275   Connect(&connection);
276
277   EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
278   EXPECT_CALL(*socket_, Disconnect(_));
279   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
280   connection.DeviceRemoved(adapter_.get(), &device_);
281 }
282
283 TEST_F(ProximityAuthBluetoothConnectionTest,
284        Connect_ConnectionSucceeds_ReceiveData) {
285   StrictMock<MockBluetoothConnection> connection;
286   Connect(&connection);
287   ASSERT_TRUE(receive_callback() && !receive_callback()->is_null());
288
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();
299
300   // The connection disconnects and unregisters as an observer upon destruction.
301   EXPECT_CALL(*socket_, Disconnect(_));
302   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
303 }
304
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());
310
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());
321
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();
331
332   // The connection disconnects and unregisters as an observer upon destruction.
333   EXPECT_CALL(*socket_, Disconnect(_));
334   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
335 }
336
337 TEST_F(ProximityAuthBluetoothConnectionTest,
338        Disconnect_ConnectionWasAlreadyDisconnected) {
339   StrictMock<MockBluetoothConnection> connection;
340   EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
341   connection.Disconnect();
342 }
343
344 TEST_F(ProximityAuthBluetoothConnectionTest,
345        Disconnect_ConnectionWasInProgress) {
346   // Create an in-progress connection.
347   StrictMock<MockBluetoothConnection> connection;
348   BeginConnecting(&connection);
349
350   EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
351   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
352   connection.Disconnect();
353 }
354
355 TEST_F(ProximityAuthBluetoothConnectionTest,
356        Disconnect_ConnectionWasConnected) {
357   // Create a connected connection.
358   StrictMock<MockBluetoothConnection> connection;
359   Connect(&connection);
360
361   EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
362   EXPECT_CALL(*socket_, Disconnect(_));
363   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
364   connection.Disconnect();
365 }
366
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());
378
379   EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
380   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
381   connection.Disconnect();
382
383   EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
384   EXPECT_CALL(*socket_, Receive(_, _, _)).Times(0);
385   callback.Run(socket_);
386 }
387
388 TEST_F(ProximityAuthBluetoothConnectionTest,
389        SendMessage_SendsExpectedDataOverTheWire) {
390   // Create a connected connection.
391   StrictMock<MockBluetoothConnection> connection;
392   Connect(&connection);
393
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));
402
403   // The connection disconnects and unregisters as an observer upon destruction.
404   EXPECT_CALL(*socket_, Disconnect(_));
405   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
406 }
407
408 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Success) {
409   // Create a connected connection.
410   StrictMock<MockBluetoothConnection> connection;
411   Connect(&connection);
412
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();
416
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());
421
422   EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), true));
423   callback.Run(kSerializedMessageLength);
424
425   // The connection disconnects and unregisters as an observer upon destruction.
426   EXPECT_CALL(*socket_, Disconnect(_));
427   EXPECT_CALL(*adapter_, RemoveObserver(&connection));
428 }
429
430 TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Failure) {
431   // Create a connected connection.
432   StrictMock<MockBluetoothConnection> connection;
433   Connect(&connection);
434
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();
438
439   device::BluetoothSocket::ErrorCompletionCallback error_callback;
440   EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<3>(&error_callback));
441   connection.SendMessage(wire_message.Pass());
442
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");
449 }
450
451 }  // namespace proximity_auth