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.
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 "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
16 #include "device/bluetooth/bluetooth_adapter.h"
17 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
18 #include "device/bluetooth/bluetooth_adapter_factory.h"
19 #include "device/bluetooth/bluetooth_device.h"
20 #include "device/bluetooth/bluetooth_device_chromeos.h"
21 #include "device/bluetooth/bluetooth_socket.h"
22 #include "device/bluetooth/bluetooth_socket_chromeos.h"
23 #include "device/bluetooth/bluetooth_socket_thread.h"
24 #include "device/bluetooth/bluetooth_uuid.h"
25 #include "net/base/io_buffer.h"
26 #include "net/base/net_errors.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using device::BluetoothAdapter
;
30 using device::BluetoothDevice
;
31 using device::BluetoothSocket
;
32 using device::BluetoothSocketThread
;
33 using device::BluetoothUUID
;
37 void DoNothingDBusErrorCallback(const std::string
& error_name
,
38 const std::string
& error_message
) {}
44 class BluetoothSocketChromeOSTest
: public testing::Test
{
46 BluetoothSocketChromeOSTest()
47 : success_callback_count_(0),
48 error_callback_count_(0),
50 last_bytes_received_(0),
51 last_reason_(BluetoothSocket::kSystemError
) {}
53 void SetUp() override
{
54 scoped_ptr
<DBusThreadManagerSetter
> dbus_setter
=
55 DBusThreadManager::GetSetterForTesting();
57 dbus_setter
->SetBluetoothAdapterClient(
58 scoped_ptr
<BluetoothAdapterClient
>(new FakeBluetoothAdapterClient
));
59 dbus_setter
->SetBluetoothAgentManagerClient(
60 scoped_ptr
<BluetoothAgentManagerClient
>(
61 new FakeBluetoothAgentManagerClient
));
62 dbus_setter
->SetBluetoothDeviceClient(
63 scoped_ptr
<BluetoothDeviceClient
>(new FakeBluetoothDeviceClient
));
64 dbus_setter
->SetBluetoothGattServiceClient(
65 scoped_ptr
<BluetoothGattServiceClient
>(
66 new FakeBluetoothGattServiceClient
));
67 dbus_setter
->SetBluetoothInputClient(
68 scoped_ptr
<BluetoothInputClient
>(new FakeBluetoothInputClient
));
69 dbus_setter
->SetBluetoothProfileManagerClient(
70 scoped_ptr
<BluetoothProfileManagerClient
>(
71 new FakeBluetoothProfileManagerClient
));
73 BluetoothSocketThread::Get();
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());
83 // Turn on the adapter.
86 base::Bind(&base::DoNothing
),
87 base::Bind(&base::DoNothing
));
88 ASSERT_TRUE(adapter_
->IsPowered());
91 void TearDown() override
{
93 BluetoothSocketThread::CleanupForTesting();
94 DBusThreadManager::Shutdown();
97 void AdapterCallback(scoped_refptr
<BluetoothAdapter
> adapter
) {
101 void SuccessCallback() {
102 ++success_callback_count_
;
103 message_loop_
.Quit();
106 void ErrorCallback(const std::string
& message
) {
107 ++error_callback_count_
;
108 last_message_
= message
;
110 message_loop_
.Quit();
113 void ConnectToServiceSuccessCallback(scoped_refptr
<BluetoothSocket
> socket
) {
114 ++success_callback_count_
;
115 last_socket_
= socket
;
117 message_loop_
.Quit();
120 void SendSuccessCallback(int bytes_sent
) {
121 ++success_callback_count_
;
122 last_bytes_sent_
= bytes_sent
;
124 message_loop_
.Quit();
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
;
133 message_loop_
.Quit();
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
;
142 message_loop_
.Quit();
145 void CreateServiceSuccessCallback(scoped_refptr
<BluetoothSocket
> socket
) {
146 ++success_callback_count_
;
147 last_socket_
= socket
;
149 if (message_loop_
.is_running())
150 message_loop_
.Quit();
153 void AcceptSuccessCallback(const BluetoothDevice
* device
,
154 scoped_refptr
<BluetoothSocket
> socket
) {
155 ++success_callback_count_
;
156 last_device_
= device
;
157 last_socket_
= socket
;
159 message_loop_
.Quit();
162 void ImmediateSuccessCallback() {
163 ++success_callback_count_
;
167 base::MessageLoop message_loop_
;
169 scoped_refptr
<BluetoothAdapter
> adapter_
;
171 unsigned int success_callback_count_
;
172 unsigned int error_callback_count_
;
174 std::string last_message_
;
175 scoped_refptr
<BluetoothSocket
> last_socket_
;
176 int last_bytes_sent_
;
177 int last_bytes_received_
;
178 scoped_refptr
<net::IOBuffer
> last_io_buffer_
;
179 BluetoothSocket::ErrorReason last_reason_
;
180 const BluetoothDevice
* last_device_
;
183 TEST_F(BluetoothSocketChromeOSTest
, Connect
) {
184 BluetoothDevice
* device
= adapter_
->GetDevice(
185 FakeBluetoothDeviceClient::kPairedDeviceAddress
);
186 ASSERT_TRUE(device
!= NULL
);
188 device
->ConnectToService(
189 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
190 base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback
,
191 base::Unretained(this)),
192 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
193 base::Unretained(this)));
196 EXPECT_EQ(1U, success_callback_count_
);
197 EXPECT_EQ(0U, error_callback_count_
);
198 EXPECT_TRUE(last_socket_
.get() != NULL
);
200 // Take ownership of the socket for the remainder of the test.
201 scoped_refptr
<BluetoothSocket
> socket
= last_socket_
;
203 success_callback_count_
= 0;
204 error_callback_count_
= 0;
206 // Send data to the socket, expect all of the data to be sent.
207 scoped_refptr
<net::StringIOBuffer
> write_buffer(
208 new net::StringIOBuffer("test"));
210 socket
->Send(write_buffer
.get(), write_buffer
->size(),
211 base::Bind(&BluetoothSocketChromeOSTest::SendSuccessCallback
,
212 base::Unretained(this)),
213 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
214 base::Unretained(this)));
217 EXPECT_EQ(1U, success_callback_count_
);
218 EXPECT_EQ(0U, error_callback_count_
);
219 EXPECT_EQ(last_bytes_sent_
, write_buffer
->size());
221 success_callback_count_
= 0;
222 error_callback_count_
= 0;
224 // Receive data from the socket, and fetch the buffer from the callback; since
225 // the fake is an echo server, we expect to receive what we wrote.
228 base::Bind(&BluetoothSocketChromeOSTest::ReceiveSuccessCallback
,
229 base::Unretained(this)),
230 base::Bind(&BluetoothSocketChromeOSTest::ReceiveErrorCallback
,
231 base::Unretained(this)));
234 EXPECT_EQ(1U, success_callback_count_
);
235 EXPECT_EQ(0U, error_callback_count_
);
236 EXPECT_EQ(4, last_bytes_received_
);
237 EXPECT_TRUE(last_io_buffer_
.get() != NULL
);
239 // Take ownership of the received buffer.
240 scoped_refptr
<net::IOBuffer
> read_buffer
= last_io_buffer_
;
241 last_io_buffer_
= NULL
;
242 success_callback_count_
= 0;
243 error_callback_count_
= 0;
245 std::string data
= std::string(read_buffer
->data(), last_bytes_received_
);
246 EXPECT_EQ("test", data
);
250 // Receive data again; the socket will have been closed, this should cause a
251 // disconnected error to be returned via the error callback.
254 base::Bind(&BluetoothSocketChromeOSTest::ReceiveSuccessCallback
,
255 base::Unretained(this)),
256 base::Bind(&BluetoothSocketChromeOSTest::ReceiveErrorCallback
,
257 base::Unretained(this)));
260 EXPECT_EQ(0U, success_callback_count_
);
261 EXPECT_EQ(1U, error_callback_count_
);
262 EXPECT_EQ(BluetoothSocket::kDisconnected
, last_reason_
);
263 EXPECT_EQ(net::ErrorToString(net::OK
), last_message_
);
265 success_callback_count_
= 0;
266 error_callback_count_
= 0;
268 // Send data again; since the socket is closed we should get a system error
269 // equivalent to the connection reset error.
270 write_buffer
= new net::StringIOBuffer("second test");
272 socket
->Send(write_buffer
.get(), write_buffer
->size(),
273 base::Bind(&BluetoothSocketChromeOSTest::SendSuccessCallback
,
274 base::Unretained(this)),
275 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
276 base::Unretained(this)));
279 EXPECT_EQ(0U, success_callback_count_
);
280 EXPECT_EQ(1U, error_callback_count_
);
281 EXPECT_EQ(net::ErrorToString(net::ERR_CONNECTION_RESET
), last_message_
);
283 success_callback_count_
= 0;
284 error_callback_count_
= 0;
286 // Close our end of the socket.
287 socket
->Disconnect(base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback
,
288 base::Unretained(this)));
291 EXPECT_EQ(1U, success_callback_count_
);
294 TEST_F(BluetoothSocketChromeOSTest
, Listen
) {
295 adapter_
->CreateRfcommService(
296 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
297 BluetoothAdapter::ServiceOptions(),
298 base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback
,
299 base::Unretained(this)),
300 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
301 base::Unretained(this)));
305 EXPECT_EQ(1U, success_callback_count_
);
306 EXPECT_EQ(0U, error_callback_count_
);
307 EXPECT_TRUE(last_socket_
.get() != NULL
);
309 // Take ownership of the socket for the remainder of the test.
310 scoped_refptr
<BluetoothSocket
> server_socket
= last_socket_
;
312 success_callback_count_
= 0;
313 error_callback_count_
= 0;
315 // Simulate an incoming connection by just calling the ConnectProfile method
316 // of the underlying fake device client (from the BlueZ point of view,
317 // outgoing and incoming look the same).
319 // This is done before the Accept() call to simulate a pending call at the
320 // point that Accept() is called.
321 FakeBluetoothDeviceClient
* fake_bluetooth_device_client
=
322 static_cast<FakeBluetoothDeviceClient
*>(
323 DBusThreadManager::Get()->GetBluetoothDeviceClient());
324 BluetoothDevice
* device
= adapter_
->GetDevice(
325 FakeBluetoothDeviceClient::kPairedDeviceAddress
);
326 ASSERT_TRUE(device
!= NULL
);
327 fake_bluetooth_device_client
->ConnectProfile(
328 static_cast<BluetoothDeviceChromeOS
*>(device
)->object_path(),
329 FakeBluetoothProfileManagerClient::kRfcommUuid
,
330 base::Bind(&base::DoNothing
),
331 base::Bind(&DoNothingDBusErrorCallback
));
333 message_loop_
.RunUntilIdle();
335 server_socket
->Accept(
336 base::Bind(&BluetoothSocketChromeOSTest::AcceptSuccessCallback
,
337 base::Unretained(this)),
338 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
339 base::Unretained(this)));
343 EXPECT_EQ(1U, success_callback_count_
);
344 EXPECT_EQ(0U, error_callback_count_
);
345 EXPECT_TRUE(last_socket_
.get() != NULL
);
347 // Take ownership of the client socket for the remainder of the test.
348 scoped_refptr
<BluetoothSocket
> client_socket
= last_socket_
;
350 success_callback_count_
= 0;
351 error_callback_count_
= 0;
353 // Close our end of the client socket.
354 client_socket
->Disconnect(
355 base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback
,
356 base::Unretained(this)));
360 EXPECT_EQ(1U, success_callback_count_
);
361 client_socket
= NULL
;
362 success_callback_count_
= 0;
363 error_callback_count_
= 0;
365 // Run a second connection test, this time calling Accept() before the
366 // incoming connection comes in.
367 server_socket
->Accept(
368 base::Bind(&BluetoothSocketChromeOSTest::AcceptSuccessCallback
,
369 base::Unretained(this)),
370 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
371 base::Unretained(this)));
373 message_loop_
.RunUntilIdle();
375 fake_bluetooth_device_client
->ConnectProfile(
376 static_cast<BluetoothDeviceChromeOS
*>(device
)->object_path(),
377 FakeBluetoothProfileManagerClient::kRfcommUuid
,
378 base::Bind(&base::DoNothing
),
379 base::Bind(&DoNothingDBusErrorCallback
));
383 EXPECT_EQ(1U, success_callback_count_
);
384 EXPECT_EQ(0U, error_callback_count_
);
385 EXPECT_TRUE(last_socket_
.get() != NULL
);
387 // Take ownership of the client socket for the remainder of the test.
388 client_socket
= last_socket_
;
390 success_callback_count_
= 0;
391 error_callback_count_
= 0;
393 // Close our end of the client socket.
394 client_socket
->Disconnect(
395 base::Bind(&BluetoothSocketChromeOSTest::SuccessCallback
,
396 base::Unretained(this)));
400 EXPECT_EQ(1U, success_callback_count_
);
401 client_socket
= NULL
;
402 success_callback_count_
= 0;
403 error_callback_count_
= 0;
405 // Now close the server socket.
406 server_socket
->Disconnect(
407 base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback
,
408 base::Unretained(this)));
410 message_loop_
.RunUntilIdle();
412 EXPECT_EQ(1U, success_callback_count_
);
415 TEST_F(BluetoothSocketChromeOSTest
, ListenBeforeAdapterStart
) {
416 // Start off with an invisible adapter, register the profile, then make
417 // the adapter visible.
418 FakeBluetoothAdapterClient
* fake_bluetooth_adapter_client
=
419 static_cast<FakeBluetoothAdapterClient
*>(
420 DBusThreadManager::Get()->GetBluetoothAdapterClient());
421 fake_bluetooth_adapter_client
->SetVisible(false);
423 adapter_
->CreateRfcommService(
424 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
425 BluetoothAdapter::ServiceOptions(),
426 base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback
,
427 base::Unretained(this)),
428 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
429 base::Unretained(this)));
432 EXPECT_EQ(1U, success_callback_count_
);
433 EXPECT_EQ(0U, error_callback_count_
);
434 EXPECT_TRUE(last_socket_
.get() != NULL
);
436 // Take ownership of the socket for the remainder of the test.
437 scoped_refptr
<BluetoothSocket
> socket
= last_socket_
;
439 success_callback_count_
= 0;
440 error_callback_count_
= 0;
442 // But there shouldn't be a profile registered yet.
443 FakeBluetoothProfileManagerClient
* fake_bluetooth_profile_manager_client
=
444 static_cast<FakeBluetoothProfileManagerClient
*>(
445 DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
446 FakeBluetoothProfileServiceProvider
* profile_service_provider
=
447 fake_bluetooth_profile_manager_client
->GetProfileServiceProvider(
448 FakeBluetoothProfileManagerClient::kRfcommUuid
);
449 EXPECT_TRUE(profile_service_provider
== NULL
);
451 // Make the adapter visible. This should register a profile.
452 fake_bluetooth_adapter_client
->SetVisible(true);
454 message_loop_
.RunUntilIdle();
456 profile_service_provider
=
457 fake_bluetooth_profile_manager_client
->GetProfileServiceProvider(
458 FakeBluetoothProfileManagerClient::kRfcommUuid
);
459 EXPECT_TRUE(profile_service_provider
!= NULL
);
461 // Cleanup the socket.
463 base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback
,
464 base::Unretained(this)));
466 message_loop_
.RunUntilIdle();
468 EXPECT_EQ(1U, success_callback_count_
);
471 TEST_F(BluetoothSocketChromeOSTest
, ListenAcrossAdapterRestart
) {
472 // The fake adapter starts off visible by default.
473 FakeBluetoothAdapterClient
* fake_bluetooth_adapter_client
=
474 static_cast<FakeBluetoothAdapterClient
*>(
475 DBusThreadManager::Get()->GetBluetoothAdapterClient());
477 adapter_
->CreateRfcommService(
478 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
479 BluetoothAdapter::ServiceOptions(),
480 base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback
,
481 base::Unretained(this)),
482 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
483 base::Unretained(this)));
486 EXPECT_EQ(1U, success_callback_count_
);
487 EXPECT_EQ(0U, error_callback_count_
);
488 EXPECT_TRUE(last_socket_
.get() != NULL
);
490 // Take ownership of the socket for the remainder of the test.
491 scoped_refptr
<BluetoothSocket
> socket
= last_socket_
;
493 success_callback_count_
= 0;
494 error_callback_count_
= 0;
496 // Make sure the profile was registered with the daemon.
497 FakeBluetoothProfileManagerClient
* fake_bluetooth_profile_manager_client
=
498 static_cast<FakeBluetoothProfileManagerClient
*>(
499 DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
500 FakeBluetoothProfileServiceProvider
* profile_service_provider
=
501 fake_bluetooth_profile_manager_client
->GetProfileServiceProvider(
502 FakeBluetoothProfileManagerClient::kRfcommUuid
);
503 EXPECT_TRUE(profile_service_provider
!= NULL
);
505 // Make the adapter invisible, and fiddle with the profile fake to unregister
506 // the profile since this doesn't happen automatically.
507 fake_bluetooth_adapter_client
->SetVisible(false);
509 message_loop_
.RunUntilIdle();
511 // Then make the adapter visible again. This should re-register the profile.
512 fake_bluetooth_adapter_client
->SetVisible(true);
514 message_loop_
.RunUntilIdle();
516 profile_service_provider
=
517 fake_bluetooth_profile_manager_client
->GetProfileServiceProvider(
518 FakeBluetoothProfileManagerClient::kRfcommUuid
);
519 EXPECT_TRUE(profile_service_provider
!= NULL
);
521 // Cleanup the socket.
523 base::Bind(&BluetoothSocketChromeOSTest::ImmediateSuccessCallback
,
524 base::Unretained(this)));
526 message_loop_
.RunUntilIdle();
528 EXPECT_EQ(1U, success_callback_count_
);
531 TEST_F(BluetoothSocketChromeOSTest
, PairedConnectFails
) {
532 BluetoothDevice
* device
= adapter_
->GetDevice(
533 FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress
);
534 ASSERT_TRUE(device
!= NULL
);
536 device
->ConnectToService(
537 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
538 base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback
,
539 base::Unretained(this)),
540 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
541 base::Unretained(this)));
544 EXPECT_EQ(0U, success_callback_count_
);
545 EXPECT_EQ(1U, error_callback_count_
);
546 EXPECT_TRUE(last_socket_
.get() == NULL
);
548 device
->ConnectToService(
549 BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid
),
550 base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback
,
551 base::Unretained(this)),
552 base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback
,
553 base::Unretained(this)));
556 EXPECT_EQ(0U, success_callback_count_
);
557 EXPECT_EQ(2U, error_callback_count_
);
558 EXPECT_TRUE(last_socket_
.get() == NULL
);
561 } // namespace chromeos