Home | History | Annotate | Download | only in test
      1 //
      2 //  Copyright (C) 2015 Google, Inc.
      3 //
      4 //  Licensed under the Apache License, Version 2.0 (the "License");
      5 //  you may not use this file except in compliance with the License.
      6 //  You may obtain a copy of the License at:
      7 //
      8 //  http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 //  Unless required by applicable law or agreed to in writing, software
     11 //  distributed under the License is distributed on an "AS IS" BASIS,
     12 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 //  See the License for the specific language governing permissions and
     14 //  limitations under the License.
     15 //
     16 
     17 #include <base/macros.h>
     18 #include <gmock/gmock.h>
     19 #include <gtest/gtest.h>
     20 
     21 #include "service/adapter.h"
     22 #include "service/hal/fake_bluetooth_gatt_interface.h"
     23 #include "service/low_energy_client.h"
     24 #include "stack/include/bt_types.h"
     25 #include "stack/include/hcidefs.h"
     26 #include "test/mock_adapter.h"
     27 
     28 using ::testing::_;
     29 using ::testing::Return;
     30 using ::testing::Pointee;
     31 using ::testing::DoAll;
     32 using ::testing::Invoke;
     33 
     34 namespace bluetooth {
     35 namespace {
     36 
     37 class MockGattHandler
     38     : public hal::FakeBluetoothGattInterface::TestClientHandler {
     39  public:
     40   MockGattHandler(){};
     41   ~MockGattHandler() override = default;
     42 
     43   MOCK_METHOD1(RegisterClient, bt_status_t(bt_uuid_t*));
     44   MOCK_METHOD1(UnregisterClient, bt_status_t(int));
     45   MOCK_METHOD4(Connect, bt_status_t(int, const bt_bdaddr_t*, bool, int));
     46   MOCK_METHOD3(Disconnect, bt_status_t(int, const bt_bdaddr_t*, int));
     47 
     48  private:
     49   DISALLOW_COPY_AND_ASSIGN(MockGattHandler);
     50 };
     51 
     52 class TestDelegate : public LowEnergyClient::Delegate {
     53  public:
     54   TestDelegate() : connection_state_count_(0), last_mtu_(0) {}
     55 
     56   ~TestDelegate() override = default;
     57 
     58   int connection_state_count() const { return connection_state_count_; }
     59 
     60   void OnConnectionState(LowEnergyClient* client, int status,
     61                          const char* address, bool connected) {
     62     ASSERT_TRUE(client);
     63     connection_state_count_++;
     64   }
     65 
     66   void OnMtuChanged(LowEnergyClient* client, int status, const char* address,
     67                     int mtu) {
     68     ASSERT_TRUE(client);
     69     last_mtu_ = mtu;
     70   }
     71 
     72  private:
     73   int connection_state_count_;
     74 
     75   int last_mtu_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
     78 };
     79 
     80 class LowEnergyClientTest : public ::testing::Test {
     81  public:
     82   LowEnergyClientTest() = default;
     83   ~LowEnergyClientTest() override = default;
     84 
     85   void SetUp() override {
     86     // Only set |mock_handler_| if a test hasn't set it.
     87     if (!mock_handler_) mock_handler_.reset(new MockGattHandler());
     88     fake_hal_gatt_iface_ = new hal::FakeBluetoothGattInterface(
     89         nullptr, nullptr,
     90         std::static_pointer_cast<
     91             hal::FakeBluetoothGattInterface::TestClientHandler>(mock_handler_),
     92         nullptr);
     93     hal::BluetoothGattInterface::InitializeForTesting(fake_hal_gatt_iface_);
     94     ble_factory_.reset(new LowEnergyClientFactory(mock_adapter_));
     95   }
     96 
     97   void TearDown() override {
     98     ble_factory_.reset();
     99     hal::BluetoothGattInterface::CleanUp();
    100   }
    101 
    102  protected:
    103   hal::FakeBluetoothGattInterface* fake_hal_gatt_iface_;
    104   testing::MockAdapter mock_adapter_;
    105   std::shared_ptr<MockGattHandler> mock_handler_;
    106   std::unique_ptr<LowEnergyClientFactory> ble_factory_;
    107 
    108  private:
    109   DISALLOW_COPY_AND_ASSIGN(LowEnergyClientTest);
    110 };
    111 
    112 // Used for tests that operate on a pre-registered client.
    113 class LowEnergyClientPostRegisterTest : public LowEnergyClientTest {
    114  public:
    115   LowEnergyClientPostRegisterTest() : next_client_id_(0) {}
    116   ~LowEnergyClientPostRegisterTest() override = default;
    117 
    118   void SetUp() override {
    119     LowEnergyClientTest::SetUp();
    120     auto callback = [&](std::unique_ptr<LowEnergyClient> client) {
    121       le_client_ = std::move(client);
    122     };
    123     RegisterTestClient(callback);
    124   }
    125 
    126   void TearDown() override {
    127     EXPECT_CALL(*mock_handler_, UnregisterClient(_))
    128         .Times(1)
    129         .WillOnce(Return(BT_STATUS_SUCCESS));
    130     le_client_.reset();
    131     LowEnergyClientTest::TearDown();
    132   }
    133 
    134   void RegisterTestClient(
    135       const std::function<void(std::unique_ptr<LowEnergyClient> client)>
    136           callback) {
    137     UUID uuid = UUID::GetRandom();
    138     auto api_callback = [&](BLEStatus status, const UUID& in_uuid,
    139                             std::unique_ptr<BluetoothInstance> in_client) {
    140       CHECK(in_uuid == uuid);
    141       CHECK(in_client.get());
    142       CHECK(status == BLE_STATUS_SUCCESS);
    143 
    144       callback(std::unique_ptr<LowEnergyClient>(
    145           static_cast<LowEnergyClient*>(in_client.release())));
    146     };
    147 
    148     EXPECT_CALL(*mock_handler_, RegisterClient(_))
    149         .Times(1)
    150         .WillOnce(Return(BT_STATUS_SUCCESS));
    151 
    152     ble_factory_->RegisterInstance(uuid, api_callback);
    153 
    154     bt_uuid_t hal_uuid = uuid.GetBlueDroid();
    155     fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, next_client_id_++,
    156                                                        hal_uuid);
    157     ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    158   }
    159 
    160  protected:
    161   std::unique_ptr<LowEnergyClient> le_client_;
    162 
    163  private:
    164   int next_client_id_;
    165 
    166   DISALLOW_COPY_AND_ASSIGN(LowEnergyClientPostRegisterTest);
    167 };
    168 
    169 TEST_F(LowEnergyClientTest, RegisterInstance) {
    170   EXPECT_CALL(*mock_handler_, RegisterClient(_))
    171       .Times(2)
    172       .WillOnce(Return(BT_STATUS_FAIL))
    173       .WillOnce(Return(BT_STATUS_SUCCESS));
    174 
    175   // These will be asynchronously populated with a result when the callback
    176   // executes.
    177   BLEStatus status = BLE_STATUS_SUCCESS;
    178   UUID cb_uuid;
    179   std::unique_ptr<LowEnergyClient> client;
    180   int callback_count = 0;
    181 
    182   auto callback = [&](BLEStatus in_status, const UUID& uuid,
    183                       std::unique_ptr<BluetoothInstance> in_client) {
    184     status = in_status;
    185     cb_uuid = uuid;
    186     client = std::unique_ptr<LowEnergyClient>(
    187         static_cast<LowEnergyClient*>(in_client.release()));
    188     callback_count++;
    189   };
    190 
    191   UUID uuid0 = UUID::GetRandom();
    192 
    193   // HAL returns failure.
    194   EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
    195   EXPECT_EQ(0, callback_count);
    196 
    197   // HAL returns success.
    198   EXPECT_TRUE(ble_factory_->RegisterInstance(uuid0, callback));
    199   EXPECT_EQ(0, callback_count);
    200 
    201   // Calling twice with the same UUID should fail with no additional call into
    202   // the stack.
    203   EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
    204 
    205   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    206 
    207   // Call with a different UUID while one is pending.
    208   UUID uuid1 = UUID::GetRandom();
    209   EXPECT_CALL(*mock_handler_, RegisterClient(_))
    210       .Times(1)
    211       .WillOnce(Return(BT_STATUS_SUCCESS));
    212   EXPECT_TRUE(ble_factory_->RegisterInstance(uuid1, callback));
    213 
    214   // Trigger callback with an unknown UUID. This should get ignored.
    215   UUID uuid2 = UUID::GetRandom();
    216   bt_uuid_t hal_uuid = uuid2.GetBlueDroid();
    217   fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, hal_uuid);
    218   EXPECT_EQ(0, callback_count);
    219 
    220   // |uuid0| succeeds.
    221   int client_if0 = 2;  // Pick something that's not 0.
    222   hal_uuid = uuid0.GetBlueDroid();
    223   fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_SUCCESS,
    224                                                      client_if0, hal_uuid);
    225 
    226   EXPECT_EQ(1, callback_count);
    227   ASSERT_TRUE(client.get() != nullptr);  // Assert to terminate in case of error
    228   EXPECT_EQ(BLE_STATUS_SUCCESS, status);
    229   EXPECT_EQ(client_if0, client->GetInstanceId());
    230   EXPECT_EQ(uuid0, client->GetAppIdentifier());
    231   EXPECT_EQ(uuid0, cb_uuid);
    232 
    233   // The client should unregister itself when deleted.
    234   EXPECT_CALL(*mock_handler_, UnregisterClient(client_if0))
    235       .Times(1)
    236       .WillOnce(Return(BT_STATUS_SUCCESS));
    237   client.reset();
    238   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    239 
    240   // |uuid1| fails.
    241   int client_if1 = 3;
    242   hal_uuid = uuid1.GetBlueDroid();
    243   fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_FAIL, client_if1,
    244                                                      hal_uuid);
    245 
    246   EXPECT_EQ(2, callback_count);
    247   ASSERT_TRUE(client.get() == nullptr);  // Assert to terminate in case of error
    248   EXPECT_EQ(BLE_STATUS_FAILURE, status);
    249   EXPECT_EQ(uuid1, cb_uuid);
    250 }
    251 
    252 MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") +
    253                         " bitwise equal to " + ::testing::PrintToString(x)) {
    254   static_assert(sizeof(x) == sizeof(arg), "Size mismatch");
    255   return std::memcmp(&arg, &x, sizeof(x)) == 0;
    256 }
    257 
    258 TEST_F(LowEnergyClientPostRegisterTest, Connect) {
    259   const bt_bdaddr_t kTestAddress = {{0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C}};
    260   const char kTestAddressStr[] = "01:02:03:0A:0B:0C";
    261   const bool kTestDirect = false;
    262   const int connId = 12;
    263 
    264   TestDelegate delegate;
    265   le_client_->SetDelegate(&delegate);
    266 
    267   // TODO(jpawlowski): NotifyConnectCallback should be called after returning
    268   // success, fix it when it becomes important.
    269   // These should succeed and result in a HAL call
    270   EXPECT_CALL(*mock_handler_,
    271               Connect(le_client_->GetInstanceId(), Pointee(BitEq(kTestAddress)),
    272                       kTestDirect, BT_TRANSPORT_LE))
    273       .Times(1)
    274       .WillOnce(DoAll(Invoke([&](int client_id, const bt_bdaddr_t* bd_addr,
    275                                  bool is_direct, int transport) {
    276                         fake_hal_gatt_iface_->NotifyConnectCallback(
    277                             connId, BT_STATUS_SUCCESS, client_id, *bd_addr);
    278                       }),
    279                       Return(BT_STATUS_SUCCESS)));
    280 
    281   EXPECT_TRUE(le_client_->Connect(kTestAddressStr, kTestDirect));
    282   EXPECT_EQ(1, delegate.connection_state_count());
    283 
    284   // TODO(jpawlowski): same as above
    285   // These should succeed and result in a HAL call
    286   EXPECT_CALL(*mock_handler_, Disconnect(le_client_->GetInstanceId(),
    287                                          Pointee(BitEq(kTestAddress)), connId))
    288       .Times(1)
    289       .WillOnce(DoAll(
    290           Invoke([&](int client_id, const bt_bdaddr_t* bd_addr, int connId) {
    291             fake_hal_gatt_iface_->NotifyDisconnectCallback(
    292                 connId, BT_STATUS_SUCCESS, client_id, *bd_addr);
    293           }),
    294           Return(BT_STATUS_SUCCESS)));
    295 
    296   EXPECT_TRUE(le_client_->Disconnect(kTestAddressStr));
    297   EXPECT_EQ(2, delegate.connection_state_count());
    298 
    299   le_client_->SetDelegate(nullptr);
    300   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    301 }
    302 
    303 }  // namespace
    304 }  // namespace bluetooth
    305