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