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