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 "base/bind.h"
6#include "base/memory/ref_counted.h"
7#include "base/message_loop/message_loop.h"
8#include "chromeos/dbus/dbus_thread_manager.h"
9#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
10#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
11#include "chromeos/dbus/fake_bluetooth_device_client.h"
12#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
13#include "chromeos/dbus/fake_bluetooth_input_client.h"
14#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
15#include "device/bluetooth/bluetooth_adapter.h"
16#include "device/bluetooth/bluetooth_adapter_chromeos.h"
17#include "device/bluetooth/bluetooth_adapter_factory.h"
18#include "device/bluetooth/bluetooth_device.h"
19#include "device/bluetooth/bluetooth_device_chromeos.h"
20#include "device/bluetooth/bluetooth_socket.h"
21#include "device/bluetooth/bluetooth_socket_chromeos.h"
22#include "device/bluetooth/bluetooth_socket_thread.h"
23#include "device/bluetooth/bluetooth_uuid.h"
24#include "net/base/io_buffer.h"
25#include "net/base/net_errors.h"
26#include "testing/gtest/include/gtest/gtest.h"
27
28using device::BluetoothAdapter;
29using device::BluetoothDevice;
30using device::BluetoothSocket;
31using device::BluetoothSocketThread;
32using device::BluetoothUUID;
33
34namespace {
35
36void DoNothingDBusErrorCallback(const std::string& error_name,
37                                const std::string& error_message) {}
38
39}  // namespace
40
41namespace chromeos {
42
43class BluetoothSocketChromeOSTest : public testing::Test {
44 public:
45  BluetoothSocketChromeOSTest()
46      : success_callback_count_(0),
47        error_callback_count_(0),
48        last_bytes_sent_(0),
49        last_bytes_received_(0),
50        last_reason_(BluetoothSocket::kSystemError) {}
51
52  virtual void SetUp() OVERRIDE {
53    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
54        DBusThreadManager::GetSetterForTesting();
55
56    dbus_setter->SetBluetoothAdapterClient(
57        scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
58    dbus_setter->SetBluetoothAgentManagerClient(
59        scoped_ptr<BluetoothAgentManagerClient>(
60            new FakeBluetoothAgentManagerClient));
61    dbus_setter->SetBluetoothDeviceClient(
62        scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
63    dbus_setter->SetBluetoothGattServiceClient(
64        scoped_ptr<BluetoothGattServiceClient>(
65            new FakeBluetoothGattServiceClient));
66    dbus_setter->SetBluetoothInputClient(
67        scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
68    dbus_setter->SetBluetoothProfileManagerClient(
69        scoped_ptr<BluetoothProfileManagerClient>(
70            new FakeBluetoothProfileManagerClient));
71
72    BluetoothSocketThread::Get();
73
74    // Grab a pointer to the adapter.
75    device::BluetoothAdapterFactory::GetAdapter(
76        base::Bind(&BluetoothSocketChromeOSTest::AdapterCallback,
77                   base::Unretained(this)));
78    ASSERT_TRUE(adapter_.get() != NULL);
79    ASSERT_TRUE(adapter_->IsInitialized());
80    ASSERT_TRUE(adapter_->IsPresent());
81
82    // Turn on the adapter.
83    adapter_->SetPowered(
84        true,
85        base::Bind(&base::DoNothing),
86        base::Bind(&base::DoNothing));
87    ASSERT_TRUE(adapter_->IsPowered());
88  }
89
90  virtual void TearDown() OVERRIDE {
91    adapter_ = NULL;
92    BluetoothSocketThread::CleanupForTesting();
93    DBusThreadManager::Shutdown();
94  }
95
96  void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
97    adapter_ = adapter;
98  }
99
100  void SuccessCallback() {
101    ++success_callback_count_;
102    message_loop_.Quit();
103  }
104
105  void ErrorCallback(const std::string& message) {
106    ++error_callback_count_;
107    last_message_ = message;
108
109    message_loop_.Quit();
110  }
111
112  void ConnectToServiceSuccessCallback(scoped_refptr<BluetoothSocket> socket) {
113    ++success_callback_count_;
114    last_socket_ = socket;
115
116    message_loop_.Quit();
117  }
118
119  void SendSuccessCallback(int bytes_sent) {
120    ++success_callback_count_;
121    last_bytes_sent_ = bytes_sent;
122
123    message_loop_.Quit();
124  }
125
126  void ReceiveSuccessCallback(int bytes_received,
127                              scoped_refptr<net::IOBuffer> io_buffer) {
128    ++success_callback_count_;
129    last_bytes_received_ = bytes_received;
130    last_io_buffer_ = io_buffer;
131
132    message_loop_.Quit();
133  }
134
135  void ReceiveErrorCallback(BluetoothSocket::ErrorReason reason,
136                            const std::string& error_message) {
137    ++error_callback_count_;
138    last_reason_ = reason;
139    last_message_ = error_message;
140
141    message_loop_.Quit();
142  }
143
144  void CreateServiceSuccessCallback(scoped_refptr<BluetoothSocket> socket) {
145    ++success_callback_count_;
146    last_socket_ = socket;
147  }
148
149  void AcceptSuccessCallback(const BluetoothDevice* device,
150                             scoped_refptr<BluetoothSocket> socket) {
151    ++success_callback_count_;
152    last_device_ = device;
153    last_socket_ = socket;
154
155    message_loop_.Quit();
156  }
157
158  void ImmediateSuccessCallback() {
159    ++success_callback_count_;
160  }
161
162 protected:
163  base::MessageLoop message_loop_;
164
165  scoped_refptr<BluetoothAdapter> adapter_;
166
167  unsigned int success_callback_count_;
168  unsigned int error_callback_count_;
169
170  std::string last_message_;
171  scoped_refptr<BluetoothSocket> last_socket_;
172  int last_bytes_sent_;
173  int last_bytes_received_;
174  scoped_refptr<net::IOBuffer> last_io_buffer_;
175  BluetoothSocket::ErrorReason last_reason_;
176  const BluetoothDevice* last_device_;
177};
178
179TEST_F(BluetoothSocketChromeOSTest, Connect) {
180  BluetoothDevice* device = adapter_->GetDevice(
181      FakeBluetoothDeviceClient::kPairedDeviceAddress);
182  ASSERT_TRUE(device != NULL);
183
184  device->ConnectToService(
185      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
186      base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback,
187                 base::Unretained(this)),
188      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
189                 base::Unretained(this)));
190
191  message_loop_.Run();
192
193  EXPECT_EQ(1U, success_callback_count_);
194  EXPECT_EQ(0U, error_callback_count_);
195  EXPECT_TRUE(last_socket_.get() != NULL);
196
197  // Take ownership of the socket for the remainder of the test.
198  scoped_refptr<BluetoothSocket> socket = last_socket_;
199  last_socket_ = NULL;
200  success_callback_count_ = 0;
201  error_callback_count_ = 0;
202
203  // Send data to the socket, expect all of the data to be sent.
204  scoped_refptr<net::StringIOBuffer> write_buffer(
205      new net::StringIOBuffer("test"));
206
207  socket->Send(write_buffer.get(), write_buffer->size(),
208               base::Bind(&BluetoothSocketChromeOSTest::SendSuccessCallback,
209                          base::Unretained(this)),
210               base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
211                          base::Unretained(this)));
212  message_loop_.Run();
213
214  EXPECT_EQ(1U, success_callback_count_);
215  EXPECT_EQ(0U, error_callback_count_);
216  EXPECT_EQ(last_bytes_sent_, write_buffer->size());
217
218  success_callback_count_ = 0;
219  error_callback_count_ = 0;
220
221  // Receive data from the socket, and fetch the buffer from the callback; since
222  // the fake is an echo server, we expect to receive what we wrote.
223  socket->Receive(
224      4096,
225      base::Bind(&BluetoothSocketChromeOSTest::ReceiveSuccessCallback,
226                 base::Unretained(this)),
227      base::Bind(&BluetoothSocketChromeOSTest::ReceiveErrorCallback,
228                 base::Unretained(this)));
229  message_loop_.Run();
230
231  EXPECT_EQ(1U, success_callback_count_);
232  EXPECT_EQ(0U, error_callback_count_);
233  EXPECT_EQ(4, last_bytes_received_);
234  EXPECT_TRUE(last_io_buffer_.get() != NULL);
235
236  // Take ownership of the received buffer.
237  scoped_refptr<net::IOBuffer> read_buffer = last_io_buffer_;
238  last_io_buffer_ = NULL;
239  success_callback_count_ = 0;
240  error_callback_count_ = 0;
241
242  std::string data = std::string(read_buffer->data(), last_bytes_received_);
243  EXPECT_EQ("test", data);
244
245  read_buffer = NULL;
246
247  // Receive data again; the socket will have been closed, this should cause a
248  // disconnected error to be returned via the error callback.
249  socket->Receive(
250      4096,
251      base::Bind(&BluetoothSocketChromeOSTest::ReceiveSuccessCallback,
252                 base::Unretained(this)),
253      base::Bind(&BluetoothSocketChromeOSTest::ReceiveErrorCallback,
254                 base::Unretained(this)));
255  message_loop_.Run();
256
257  EXPECT_EQ(0U, success_callback_count_);
258  EXPECT_EQ(1U, error_callback_count_);
259  EXPECT_EQ(BluetoothSocket::kDisconnected, last_reason_);
260  EXPECT_EQ(net::ErrorToString(net::OK), last_message_);
261
262  success_callback_count_ = 0;
263  error_callback_count_ = 0;
264
265  // Send data again; since the socket is closed we should get a system error
266  // equivalent to the connection reset error.
267  write_buffer = new net::StringIOBuffer("second test");
268
269  socket->Send(write_buffer.get(), write_buffer->size(),
270               base::Bind(&BluetoothSocketChromeOSTest::SendSuccessCallback,
271                          base::Unretained(this)),
272               base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
273                          base::Unretained(this)));
274  message_loop_.Run();
275
276  EXPECT_EQ(0U, success_callback_count_);
277  EXPECT_EQ(1U, error_callback_count_);
278  EXPECT_EQ(net::ErrorToString(net::ERR_CONNECTION_RESET), last_message_);
279
280  success_callback_count_ = 0;
281  error_callback_count_ = 0;
282
283  // Close our end of the socket.
284  socket->Disconnect(base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback,
285                                base::Unretained(this)));
286
287  message_loop_.Run();
288  EXPECT_EQ(1U, success_callback_count_);
289}
290
291TEST_F(BluetoothSocketChromeOSTest, Listen) {
292  adapter_->CreateRfcommService(
293      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
294      BluetoothAdapter::ServiceOptions(),
295      base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
296                 base::Unretained(this)),
297      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
298                 base::Unretained(this)));
299
300  EXPECT_EQ(1U, success_callback_count_);
301  EXPECT_EQ(0U, error_callback_count_);
302  EXPECT_TRUE(last_socket_.get() != NULL);
303
304  // Take ownership of the socket for the remainder of the test.
305  scoped_refptr<BluetoothSocket> server_socket = last_socket_;
306  last_socket_ = NULL;
307  success_callback_count_ = 0;
308  error_callback_count_ = 0;
309
310  // Simulate an incoming connection by just calling the ConnectProfile method
311  // of the underlying fake device client (from the BlueZ point of view,
312  // outgoing and incoming look the same).
313  //
314  // This is done before the Accept() call to simulate a pending call at the
315  // point that Accept() is called.
316  FakeBluetoothDeviceClient* fake_bluetooth_device_client =
317      static_cast<FakeBluetoothDeviceClient*>(
318          DBusThreadManager::Get()->GetBluetoothDeviceClient());
319  BluetoothDevice* device = adapter_->GetDevice(
320      FakeBluetoothDeviceClient::kPairedDeviceAddress);
321  ASSERT_TRUE(device != NULL);
322  fake_bluetooth_device_client->ConnectProfile(
323      static_cast<BluetoothDeviceChromeOS*>(device)->object_path(),
324      FakeBluetoothProfileManagerClient::kRfcommUuid,
325      base::Bind(&base::DoNothing),
326      base::Bind(&DoNothingDBusErrorCallback));
327
328  server_socket->Accept(
329      base::Bind(&BluetoothSocketChromeOSTest::AcceptSuccessCallback,
330                 base::Unretained(this)),
331      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
332                 base::Unretained(this)));
333
334  message_loop_.Run();
335
336  EXPECT_EQ(1U, success_callback_count_);
337  EXPECT_EQ(0U, error_callback_count_);
338  EXPECT_TRUE(last_socket_.get() != NULL);
339
340  // Take ownership of the client socket for the remainder of the test.
341  scoped_refptr<BluetoothSocket> client_socket = last_socket_;
342  last_socket_ = NULL;
343  success_callback_count_ = 0;
344  error_callback_count_ = 0;
345
346  // Close our end of the client socket.
347  client_socket->Disconnect(
348      base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback,
349                 base::Unretained(this)));
350
351  message_loop_.Run();
352
353  EXPECT_EQ(1U, success_callback_count_);
354  client_socket = NULL;
355  success_callback_count_ = 0;
356  error_callback_count_ = 0;
357
358  // Run a second connection test, this time calling Accept() before the
359  // incoming connection comes in.
360  server_socket->Accept(
361      base::Bind(&BluetoothSocketChromeOSTest::AcceptSuccessCallback,
362                 base::Unretained(this)),
363      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
364                 base::Unretained(this)));
365
366  fake_bluetooth_device_client->ConnectProfile(
367      static_cast<BluetoothDeviceChromeOS*>(device)->object_path(),
368      FakeBluetoothProfileManagerClient::kRfcommUuid,
369      base::Bind(&base::DoNothing),
370      base::Bind(&DoNothingDBusErrorCallback));
371
372  message_loop_.Run();
373
374  EXPECT_EQ(1U, success_callback_count_);
375  EXPECT_EQ(0U, error_callback_count_);
376  EXPECT_TRUE(last_socket_.get() != NULL);
377
378  // Take ownership of the client socket for the remainder of the test.
379  client_socket = last_socket_;
380  last_socket_ = NULL;
381  success_callback_count_ = 0;
382  error_callback_count_ = 0;
383
384  // Close our end of the client socket.
385  client_socket->Disconnect(
386      base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback,
387                 base::Unretained(this)));
388
389  message_loop_.Run();
390
391  EXPECT_EQ(1U, success_callback_count_);
392  client_socket = NULL;
393  success_callback_count_ = 0;
394  error_callback_count_ = 0;
395
396  // Now close the server socket.
397  server_socket->Disconnect(
398      base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback,
399                 base::Unretained(this)));
400
401  EXPECT_EQ(1U, success_callback_count_);
402}
403
404TEST_F(BluetoothSocketChromeOSTest, ListenBeforeAdapterStart) {
405  // Start off with an invisible adapter, register the profile, then make
406  // the adapter visible.
407  FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
408      static_cast<FakeBluetoothAdapterClient*>(
409          DBusThreadManager::Get()->GetBluetoothAdapterClient());
410  fake_bluetooth_adapter_client->SetVisible(false);
411
412  adapter_->CreateRfcommService(
413      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
414      BluetoothAdapter::ServiceOptions(),
415      base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
416                 base::Unretained(this)),
417      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
418                 base::Unretained(this)));
419
420  EXPECT_EQ(1U, success_callback_count_);
421  EXPECT_EQ(0U, error_callback_count_);
422  EXPECT_TRUE(last_socket_.get() != NULL);
423
424  // Take ownership of the socket for the remainder of the test.
425  scoped_refptr<BluetoothSocket> socket = last_socket_;
426  last_socket_ = NULL;
427  success_callback_count_ = 0;
428  error_callback_count_ = 0;
429
430  // But there shouldn't be a profile registered yet.
431  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
432      static_cast<FakeBluetoothProfileManagerClient*>(
433          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
434  FakeBluetoothProfileServiceProvider* profile_service_provider =
435      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
436          FakeBluetoothProfileManagerClient::kRfcommUuid);
437  EXPECT_TRUE(profile_service_provider == NULL);
438
439  // Make the adapter visible. This should register a profile.
440  fake_bluetooth_adapter_client->SetVisible(true);
441
442  profile_service_provider =
443      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
444          FakeBluetoothProfileManagerClient::kRfcommUuid);
445  EXPECT_TRUE(profile_service_provider != NULL);
446
447  // Cleanup the socket.
448  socket->Disconnect(
449      base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback,
450                 base::Unretained(this)));
451
452  EXPECT_EQ(1U, success_callback_count_);
453}
454
455TEST_F(BluetoothSocketChromeOSTest, ListenAcrossAdapterRestart) {
456  // The fake adapter starts off visible by default.
457  FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
458      static_cast<FakeBluetoothAdapterClient*>(
459          DBusThreadManager::Get()->GetBluetoothAdapterClient());
460
461  adapter_->CreateRfcommService(
462      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
463      BluetoothAdapter::ServiceOptions(),
464      base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
465                 base::Unretained(this)),
466      base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
467                 base::Unretained(this)));
468
469  EXPECT_EQ(1U, success_callback_count_);
470  EXPECT_EQ(0U, error_callback_count_);
471  EXPECT_TRUE(last_socket_.get() != NULL);
472
473  // Take ownership of the socket for the remainder of the test.
474  scoped_refptr<BluetoothSocket> socket = last_socket_;
475  last_socket_ = NULL;
476  success_callback_count_ = 0;
477  error_callback_count_ = 0;
478
479  // Make sure the profile was registered with the daemon.
480  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
481      static_cast<FakeBluetoothProfileManagerClient*>(
482          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
483  FakeBluetoothProfileServiceProvider* profile_service_provider =
484      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
485          FakeBluetoothProfileManagerClient::kRfcommUuid);
486  EXPECT_TRUE(profile_service_provider != NULL);
487
488  // Make the adapter invisible, and fiddle with the profile fake to unregister
489  // the profile since this doesn't happen automatically.
490  fake_bluetooth_adapter_client->SetVisible(false);
491  fake_bluetooth_profile_manager_client->UnregisterProfile(
492      static_cast<BluetoothSocketChromeOS*>(socket.get())->object_path(),
493      base::Bind(&base::DoNothing),
494      base::Bind(&DoNothingDBusErrorCallback));
495
496  // Then make the adapter visible again. This should re-register the profile.
497  fake_bluetooth_adapter_client->SetVisible(true);
498
499  profile_service_provider =
500      fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
501          FakeBluetoothProfileManagerClient::kRfcommUuid);
502  EXPECT_TRUE(profile_service_provider != NULL);
503
504  // Cleanup the socket.
505  socket->Disconnect(
506      base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback,
507                 base::Unretained(this)));
508
509  EXPECT_EQ(1U, success_callback_count_);
510}
511
512}  // namespace chromeos
513