Home | History | Annotate | Download | only in bluetooth
      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 
     28 using device::BluetoothAdapter;
     29 using device::BluetoothDevice;
     30 using device::BluetoothSocket;
     31 using device::BluetoothSocketThread;
     32 using device::BluetoothUUID;
     33 
     34 namespace {
     35 
     36 void DoNothingDBusErrorCallback(const std::string& error_name,
     37                                 const std::string& error_message) {}
     38 
     39 }  // namespace
     40 
     41 namespace chromeos {
     42 
     43 class 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 
    180 TEST_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 
    292 TEST_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 
    405 TEST_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 
    456 TEST_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