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