blob: e9ee1dfa9db1e99a9aa518da3b202da6758882e4 [file] [log] [blame]
Torne (Richard Coles)cedac222014-06-03 10:58:34 +01001// 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"
Primiano Tucci1320f922014-09-30 14:45:55 +01008#include "chromeos/dbus/dbus_thread_manager.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +01009#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"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010015#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 {
Primiano Tucci1320f922014-09-30 14:45:55 +010053 scoped_ptr<DBusThreadManagerSetter> dbus_setter =
54 DBusThreadManager::GetSetterForTesting();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010055
Primiano Tucci1320f922014-09-30 14:45:55 +010056 dbus_setter->SetBluetoothAdapterClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010057 scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
Primiano Tucci1320f922014-09-30 14:45:55 +010058 dbus_setter->SetBluetoothAgentManagerClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010059 scoped_ptr<BluetoothAgentManagerClient>(
60 new FakeBluetoothAgentManagerClient));
Primiano Tucci1320f922014-09-30 14:45:55 +010061 dbus_setter->SetBluetoothDeviceClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010062 scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
Primiano Tucci1320f922014-09-30 14:45:55 +010063 dbus_setter->SetBluetoothGattServiceClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010064 scoped_ptr<BluetoothGattServiceClient>(
65 new FakeBluetoothGattServiceClient));
Primiano Tucci1320f922014-09-30 14:45:55 +010066 dbus_setter->SetBluetoothInputClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010067 scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
Primiano Tucci1320f922014-09-30 14:45:55 +010068 dbus_setter->SetBluetoothProfileManagerClient(
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010069 scoped_ptr<BluetoothProfileManagerClient>(
70 new FakeBluetoothProfileManagerClient));
71
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010072 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_);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100260 EXPECT_EQ(net::ErrorToString(net::OK), last_message_);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100261
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),
Ben Murdoch116680a2014-07-20 18:25:52 -0700294 BluetoothAdapter::ServiceOptions(),
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100295 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),
Ben Murdoch116680a2014-07-20 18:25:52 -0700414 BluetoothAdapter::ServiceOptions(),
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100415 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),
Ben Murdoch116680a2014-07-20 18:25:52 -0700463 BluetoothAdapter::ServiceOptions(),
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100464 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