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