Home | History | Annotate | Download | only in test
      1 //
      2 //  Copyright 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(const bluetooth::Uuid&));
     44   MOCK_METHOD1(UnregisterClient, bt_status_t(int));
     45   MOCK_METHOD4(Connect, bt_status_t(int, const RawAddress&, bool, int));
     46   MOCK_METHOD3(Disconnect, bt_status_t(int, const RawAddress&, 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     fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, next_client_id_++,
    155                                                        uuid);
    156     ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    157   }
    158 
    159  protected:
    160   std::unique_ptr<LowEnergyClient> le_client_;
    161 
    162  private:
    163   int next_client_id_;
    164 
    165   DISALLOW_COPY_AND_ASSIGN(LowEnergyClientPostRegisterTest);
    166 };
    167 
    168 TEST_F(LowEnergyClientTest, RegisterInstance) {
    169   EXPECT_CALL(*mock_handler_, RegisterClient(_))
    170       .Times(2)
    171       .WillOnce(Return(BT_STATUS_FAIL))
    172       .WillOnce(Return(BT_STATUS_SUCCESS));
    173 
    174   // These will be asynchronously populated with a result when the callback
    175   // executes.
    176   BLEStatus status = BLE_STATUS_SUCCESS;
    177   Uuid cb_uuid;
    178   std::unique_ptr<LowEnergyClient> client;
    179   int callback_count = 0;
    180 
    181   auto callback = [&](BLEStatus in_status, const Uuid& uuid,
    182                       std::unique_ptr<BluetoothInstance> in_client) {
    183     status = in_status;
    184     cb_uuid = uuid;
    185     client = std::unique_ptr<LowEnergyClient>(
    186         static_cast<LowEnergyClient*>(in_client.release()));
    187     callback_count++;
    188   };
    189 
    190   Uuid uuid0 = Uuid::GetRandom();
    191 
    192   // HAL returns failure.
    193   EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
    194   EXPECT_EQ(0, callback_count);
    195 
    196   // HAL returns success.
    197   EXPECT_TRUE(ble_factory_->RegisterInstance(uuid0, callback));
    198   EXPECT_EQ(0, callback_count);
    199 
    200   // Calling twice with the same Uuid should fail with no additional call into
    201   // the stack.
    202   EXPECT_FALSE(ble_factory_->RegisterInstance(uuid0, callback));
    203 
    204   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    205 
    206   // Call with a different Uuid while one is pending.
    207   Uuid uuid1 = Uuid::GetRandom();
    208   EXPECT_CALL(*mock_handler_, RegisterClient(_))
    209       .Times(1)
    210       .WillOnce(Return(BT_STATUS_SUCCESS));
    211   EXPECT_TRUE(ble_factory_->RegisterInstance(uuid1, callback));
    212 
    213   // Trigger callback with an unknown Uuid. This should get ignored.
    214   Uuid uuid2 = Uuid::GetRandom();
    215   fake_hal_gatt_iface_->NotifyRegisterClientCallback(0, 0, uuid2);
    216   EXPECT_EQ(0, callback_count);
    217 
    218   // |uuid0| succeeds.
    219   int client_if0 = 2;  // Pick something that's not 0.
    220   fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_SUCCESS,
    221                                                      client_if0, uuid0);
    222 
    223   EXPECT_EQ(1, callback_count);
    224   ASSERT_TRUE(client.get() != nullptr);  // Assert to terminate in case of error
    225   EXPECT_EQ(BLE_STATUS_SUCCESS, status);
    226   EXPECT_EQ(client_if0, client->GetInstanceId());
    227   EXPECT_EQ(uuid0, client->GetAppIdentifier());
    228   EXPECT_EQ(uuid0, cb_uuid);
    229 
    230   // The client should unregister itself when deleted.
    231   EXPECT_CALL(*mock_handler_, UnregisterClient(client_if0))
    232       .Times(1)
    233       .WillOnce(Return(BT_STATUS_SUCCESS));
    234   client.reset();
    235   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    236 
    237   // |uuid1| fails.
    238   int client_if1 = 3;
    239   fake_hal_gatt_iface_->NotifyRegisterClientCallback(BT_STATUS_FAIL, client_if1,
    240                                                      uuid1);
    241 
    242   EXPECT_EQ(2, callback_count);
    243   ASSERT_TRUE(client.get() == nullptr);  // Assert to terminate in case of error
    244   EXPECT_EQ(BLE_STATUS_FAILURE, status);
    245   EXPECT_EQ(uuid1, cb_uuid);
    246 }
    247 
    248 MATCHER_P(BitEq, x, std::string(negation ? "isn't" : "is") +
    249                         " bitwise equal to " + ::testing::PrintToString(x)) {
    250   static_assert(sizeof(x) == sizeof(arg), "Size mismatch");
    251   return std::memcmp(&arg, &x, sizeof(x)) == 0;
    252 }
    253 
    254 TEST_F(LowEnergyClientPostRegisterTest, Connect) {
    255   const RawAddress kTestAddress = {{0x01, 0x02, 0x03, 0x0A, 0x0B, 0x0C}};
    256   const char kTestAddressStr[] = "01:02:03:0A:0B:0C";
    257   const bool kTestDirect = false;
    258   const int connId = 12;
    259 
    260   TestDelegate delegate;
    261   le_client_->SetDelegate(&delegate);
    262 
    263   // TODO(jpawlowski): NotifyConnectCallback should be called after returning
    264   // success, fix it when it becomes important.
    265   // These should succeed and result in a HAL call
    266   EXPECT_CALL(*mock_handler_,
    267               Connect(le_client_->GetInstanceId(), BitEq(kTestAddress),
    268                       kTestDirect, BT_TRANSPORT_LE))
    269       .Times(1)
    270       .WillOnce(DoAll(Invoke([&](int client_id, const RawAddress& bd_addr,
    271                                  bool is_direct, int transport) {
    272                         fake_hal_gatt_iface_->NotifyConnectCallback(
    273                             connId, BT_STATUS_SUCCESS, client_id, bd_addr);
    274                       }),
    275                       Return(BT_STATUS_SUCCESS)));
    276 
    277   EXPECT_TRUE(le_client_->Connect(kTestAddressStr, kTestDirect));
    278   EXPECT_EQ(1, delegate.connection_state_count());
    279 
    280   // TODO(jpawlowski): same as above
    281   // These should succeed and result in a HAL call
    282   EXPECT_CALL(*mock_handler_, Disconnect(le_client_->GetInstanceId(),
    283                                          BitEq(kTestAddress), connId))
    284       .Times(1)
    285       .WillOnce(DoAll(
    286           Invoke([&](int client_id, const RawAddress& bd_addr, int connId) {
    287             fake_hal_gatt_iface_->NotifyDisconnectCallback(
    288                 connId, BT_STATUS_SUCCESS, client_id, bd_addr);
    289           }),
    290           Return(BT_STATUS_SUCCESS)));
    291 
    292   EXPECT_TRUE(le_client_->Disconnect(kTestAddressStr));
    293   EXPECT_EQ(2, delegate.connection_state_count());
    294 
    295   le_client_->SetDelegate(nullptr);
    296   ::testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
    297 }
    298 
    299 }  // namespace
    300 }  // namespace bluetooth
    301