Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/bluetooth/device.h" | 5 #include "device/bluetooth/device.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
| 14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
| 15 #include "device/bluetooth/test/mock_bluetooth_adapter.h" | 15 #include "device/bluetooth/test/mock_bluetooth_adapter.h" |
| 16 #include "device/bluetooth/test/mock_bluetooth_device.h" | 16 #include "device/bluetooth/test/mock_bluetooth_device.h" |
| 17 #include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h" | |
| 17 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" | 18 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h" |
| 19 #include "device/bluetooth/test/mock_bluetooth_gatt_service.h" | |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 21 |
| 20 using ::testing::Return; | 22 using ::testing::Return; |
| 21 | 23 |
| 22 namespace bluetooth { | 24 namespace bluetooth { |
| 23 | 25 |
| 24 using NiceMockBluetoothAdapter = | 26 using NiceMockBluetoothAdapter = |
| 25 testing::NiceMock<device::MockBluetoothAdapter>; | 27 testing::NiceMock<device::MockBluetoothAdapter>; |
| 26 using NiceMockBluetoothDevice = testing::NiceMock<device::MockBluetoothDevice>; | 28 using NiceMockBluetoothDevice = testing::NiceMock<device::MockBluetoothDevice>; |
| 27 using NiceMockBluetoothGattService = | 29 using NiceMockBluetoothGattService = |
| 28 testing::NiceMock<device::MockBluetoothGattService>; | 30 testing::NiceMock<device::MockBluetoothGattService>; |
| 31 using NiceMockBluetoothGattCharacteristic = | |
| 32 testing::NiceMock<device::MockBluetoothGattCharacteristic>; | |
| 29 using NiceMockBluetoothGattConnection = | 33 using NiceMockBluetoothGattConnection = |
| 30 testing::NiceMock<device::MockBluetoothGattConnection>; | 34 testing::NiceMock<device::MockBluetoothGattConnection>; |
| 31 | 35 |
| 36 using Properties = device::BluetoothGattCharacteristic::Properties; | |
| 37 using Property = device::BluetoothGattCharacteristic::Property; | |
| 38 | |
| 32 namespace { | 39 namespace { |
| 33 const char kTestLeDeviceAddress0[] = "11:22:33:44:55:66"; | 40 const char kTestLeDeviceAddress0[] = "11:22:33:44:55:66"; |
| 34 const char kTestLeDeviceName0[] = "Test LE Device 0"; | 41 const char kTestLeDeviceName0[] = "Test LE Device 0"; |
| 35 | 42 |
| 36 const char kTestServiceId0[] = "service_id0"; | 43 const char kTestServiceId0[] = "service_id0"; |
| 37 const char kTestServiceUuid0[] = "1234"; | 44 const char kTestServiceUuid0[] = "1234"; |
| 38 | 45 |
| 39 const char kTestServiceId1[] = "service_id1"; | 46 const char kTestServiceId1[] = "service_id1"; |
| 40 const char kTestServiceUuid1[] = "5678"; | 47 const char kTestServiceUuid1[] = "5678"; |
| 41 | 48 |
| 49 const char kTestCharacteristicId0[] = "characteristic_id0"; | |
| 50 const char kTestCharacteristicUuid0[] = "1234"; | |
| 51 | |
| 52 const char kTestCharacteristicId1[] = "characteristic_id1"; | |
| 53 const char kTestCharacteristicUuid1[] = "5678"; | |
| 54 | |
| 55 const char kTestCharacteristicId2[] = "characteristic_id2"; | |
| 56 const char kTestCharacteristicUuid2[] = "9012"; | |
| 57 | |
| 58 const Properties kReadWriteProperties = | |
| 59 Property::PROPERTY_READ | Property::PROPERTY_WRITE; | |
| 60 const Properties kAllProperties = Property::NUM_PROPERTY - 1; | |
| 61 | |
| 42 class BluetoothInterfaceDeviceTest : public testing::Test { | 62 class BluetoothInterfaceDeviceTest : public testing::Test { |
| 43 public: | 63 public: |
| 44 enum class Call { EXPECTED, NOT_EXPECTED }; | 64 enum class Call { EXPECTED, NOT_EXPECTED }; |
| 45 | 65 |
| 46 BluetoothInterfaceDeviceTest() | 66 BluetoothInterfaceDeviceTest() |
| 47 : adapter_(new NiceMockBluetoothAdapter), | 67 : adapter_(new NiceMockBluetoothAdapter), |
| 48 device_(adapter_.get(), | 68 device_(adapter_.get(), |
| 49 0, | 69 0, |
| 50 kTestLeDeviceName0, | 70 kTestLeDeviceName0, |
| 51 kTestLeDeviceAddress0, | 71 kTestLeDeviceAddress0, |
| 52 false, | 72 false, |
| 53 true), | 73 true), |
| 54 weak_factory_(this) { | 74 weak_factory_(this) { |
| 55 ON_CALL(*adapter_, GetDevice(kTestLeDeviceAddress0)) | 75 ON_CALL(*adapter_, GetDevice(kTestLeDeviceAddress0)) |
| 56 .WillByDefault(Return(&device_)); | 76 .WillByDefault(Return(&device_)); |
| 57 | 77 |
| 58 auto service1 = base::MakeUnique<NiceMockBluetoothGattService>( | 78 auto service1 = base::MakeUnique<NiceMockBluetoothGattService>( |
| 59 &device_, kTestServiceId0, device::BluetoothUUID(kTestServiceUuid0), | 79 &device_, kTestServiceId0, device::BluetoothUUID(kTestServiceUuid0), |
| 60 true /* is_primary */, false /* is_local */); | 80 true /* is_primary */, false /* is_local */); |
| 81 | |
| 82 auto characteristic1 = | |
| 83 base::MakeUnique<NiceMockBluetoothGattCharacteristic>( | |
| 84 service1.get(), kTestCharacteristicId0, | |
| 85 device::BluetoothUUID(kTestCharacteristicUuid0), | |
| 86 false /* is_local */, kReadWriteProperties, 0 /* permissions */); | |
| 87 | |
| 88 auto characteristic2 = | |
| 89 base::MakeUnique<NiceMockBluetoothGattCharacteristic>( | |
| 90 service1.get(), kTestCharacteristicId1, | |
| 91 device::BluetoothUUID(kTestCharacteristicUuid1), | |
| 92 false /* is_local */, kReadWriteProperties, 0 /* permissions */); | |
| 93 | |
| 94 service1->AddMockCharacteristic(std::move(characteristic1)); | |
| 95 service1->AddMockCharacteristic(std::move(characteristic2)); | |
| 96 | |
| 61 auto service2 = base::MakeUnique<NiceMockBluetoothGattService>( | 97 auto service2 = base::MakeUnique<NiceMockBluetoothGattService>( |
| 62 &device_, kTestServiceId1, device::BluetoothUUID(kTestServiceUuid1), | 98 &device_, kTestServiceId1, device::BluetoothUUID(kTestServiceUuid1), |
| 63 true /* is_primary */, false /* is_local */); | 99 true /* is_primary */, false /* is_local */); |
| 64 | 100 |
| 101 auto characteristic3 = | |
| 102 base::MakeUnique<NiceMockBluetoothGattCharacteristic>( | |
| 103 service2.get(), kTestCharacteristicId2, | |
| 104 device::BluetoothUUID(kTestCharacteristicUuid2), | |
| 105 false /* is_local */, kAllProperties, 0 /* permissions */); | |
| 106 | |
| 107 service2->AddMockCharacteristic(std::move(characteristic3)); | |
| 108 | |
| 109 EXPECT_CALL(*service1, GetCharacteristics()) | |
| 110 .WillRepeatedly( | |
| 111 Invoke(service1.get(), | |
| 112 &device::MockBluetoothGattService::GetMockCharacteristics)); | |
| 113 | |
| 114 EXPECT_CALL(*service2, GetCharacteristics()) | |
| 115 .WillRepeatedly( | |
| 116 Invoke(service2.get(), | |
| 117 &device::MockBluetoothGattService::GetMockCharacteristics)); | |
| 118 | |
| 65 device_.AddMockService(std::move(service1)); | 119 device_.AddMockService(std::move(service1)); |
| 66 device_.AddMockService(std::move(service2)); | 120 device_.AddMockService(std::move(service2)); |
| 67 | 121 |
| 68 EXPECT_CALL(device_, GetGattServices()) | 122 EXPECT_CALL(device_, GetGattServices()) |
| 69 .WillRepeatedly( | 123 .WillRepeatedly( |
| 70 Invoke(&device_, &device::MockBluetoothDevice::GetMockServices)); | 124 Invoke(&device_, &device::MockBluetoothDevice::GetMockServices)); |
| 71 | 125 |
| 126 EXPECT_CALL(device_, GetGattService(testing::_)) | |
| 127 .WillRepeatedly( | |
| 128 Invoke(&device_, &device::MockBluetoothDevice::GetMockService)); | |
| 129 | |
| 72 auto connection = base::MakeUnique<NiceMockBluetoothGattConnection>( | 130 auto connection = base::MakeUnique<NiceMockBluetoothGattConnection>( |
| 73 adapter_, device_.GetAddress()); | 131 adapter_, device_.GetAddress()); |
| 74 | 132 |
| 75 Device::Create(adapter_, std::move(connection), mojo::MakeRequest(&proxy_)); | 133 Device::Create(adapter_, std::move(connection), mojo::MakeRequest(&proxy_)); |
| 76 | 134 |
| 77 proxy_.set_connection_error_handler( | 135 proxy_.set_connection_error_handler( |
| 78 base::Bind(&BluetoothInterfaceDeviceTest::OnConnectionError, | 136 base::Bind(&BluetoothInterfaceDeviceTest::OnConnectionError, |
| 79 weak_factory_.GetWeakPtr())); | 137 weak_factory_.GetWeakPtr())); |
| 80 } | 138 } |
| 81 | 139 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 int num_of_preceding_calls) { | 175 int num_of_preceding_calls) { |
| 118 if (expected == Call::EXPECTED) | 176 if (expected == Call::EXPECTED) |
| 119 ++expected_success_callback_calls_; | 177 ++expected_success_callback_calls_; |
| 120 | 178 |
| 121 return base::Bind( | 179 return base::Bind( |
| 122 &BluetoothInterfaceDeviceTest::GetServicesCheckForPrecedingCalls, | 180 &BluetoothInterfaceDeviceTest::GetServicesCheckForPrecedingCalls, |
| 123 weak_factory_.GetWeakPtr(), expected, 2 /* expected_service_count */, | 181 weak_factory_.GetWeakPtr(), expected, 2 /* expected_service_count */, |
| 124 num_of_preceding_calls); | 182 num_of_preceding_calls); |
| 125 } | 183 } |
| 126 | 184 |
| 185 void GetCharacteristicsCheckForPrecedingCalls( | |
|
scheib
2017/01/13 05:24:40
Maybe names such as:
CheckGetCharacteristicsCount
mbrunson
2017/01/13 21:21:13
Done.
| |
| 186 Call expected, | |
| 187 size_t expected_count, | |
| 188 int num_of_preceding_calls, | |
| 189 std::vector<mojom::CharacteristicInfoPtr> characteristics) { | |
| 190 EXPECT_EQ(num_of_preceding_calls, callback_count_); | |
| 191 ++callback_count_; | |
| 192 | |
| 193 if (expected == Call::EXPECTED) | |
| 194 ++actual_success_callback_calls_; | |
| 195 | |
| 196 EXPECT_EQ(expected_count, characteristics.size()); | |
| 197 } | |
| 198 | |
| 199 Device::GetCharacteristicsCallback | |
| 200 GetGetCharacteristicsCheckForPrecedingCalls(Call expected, | |
| 201 int num_of_preceding_calls, | |
|
scheib
2017/01/13 05:24:40
Can't num_of_preceding be incremented as a test fi
mbrunson
2017/01/13 21:21:13
Done.
| |
| 202 int expected_count) { | |
| 203 if (expected == Call::EXPECTED) | |
| 204 ++expected_success_callback_calls_; | |
| 205 | |
| 206 return base::Bind( | |
| 207 &BluetoothInterfaceDeviceTest::GetCharacteristicsCheckForPrecedingCalls, | |
| 208 weak_factory_.GetWeakPtr(), expected, expected_count, | |
| 209 num_of_preceding_calls); | |
| 210 } | |
| 211 | |
| 212 void GetCharacteristicsCheckProperties( | |
| 213 Call expected, | |
| 214 std::vector<Properties> expected_properties, | |
| 215 std::vector<mojom::CharacteristicInfoPtr> characteristics) { | |
| 216 if (expected == Call::EXPECTED) | |
| 217 ++actual_success_callback_calls_; | |
| 218 | |
| 219 ASSERT_EQ(expected_properties.size(), characteristics.size()); | |
| 220 | |
| 221 for (size_t i = 0; i < characteristics.size(); i++) { | |
| 222 EXPECT_EQ(expected_properties[i], characteristics[i]->properties); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 Device::GetCharacteristicsCallback GetGetCharacteristicsCheckProperties( | |
| 227 Call expected, | |
| 228 std::vector<Properties> expected_properties) { | |
| 229 if (expected == Call::EXPECTED) | |
| 230 ++expected_success_callback_calls_; | |
| 231 | |
| 232 return base::Bind( | |
| 233 &BluetoothInterfaceDeviceTest::GetCharacteristicsCheckProperties, | |
| 234 weak_factory_.GetWeakPtr(), expected, std::move(expected_properties)); | |
| 235 } | |
| 236 | |
| 127 scoped_refptr<NiceMockBluetoothAdapter> adapter_; | 237 scoped_refptr<NiceMockBluetoothAdapter> adapter_; |
| 128 NiceMockBluetoothDevice device_; | 238 NiceMockBluetoothDevice device_; |
| 129 base::MessageLoop message_loop_; | 239 base::MessageLoop message_loop_; |
| 130 mojom::DevicePtr proxy_; | 240 mojom::DevicePtr proxy_; |
| 131 mojo::StrongBindingPtr<mojom::Device> binding_ptr_; | 241 mojo::StrongBindingPtr<mojom::Device> binding_ptr_; |
| 132 | 242 |
| 133 bool message_pipe_closed_ = false; | 243 bool message_pipe_closed_ = false; |
| 134 bool expect_device_service_deleted_ = false; | 244 bool expect_device_service_deleted_ = false; |
| 135 int expected_success_callback_calls_ = 0; | 245 int expected_success_callback_calls_ = 0; |
| 136 int actual_success_callback_calls_ = 0; | 246 int actual_success_callback_calls_ = 0; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 EXPECT_EQ(0, callback_count_); | 329 EXPECT_EQ(0, callback_count_); |
| 220 | 330 |
| 221 // Simulate connection loss. | 331 // Simulate connection loss. |
| 222 proxy_->Disconnect(); | 332 proxy_->Disconnect(); |
| 223 expect_device_service_deleted_ = true; | 333 expect_device_service_deleted_ = true; |
| 224 | 334 |
| 225 // Wait for message pipe to process error. | 335 // Wait for message pipe to process error. |
| 226 base::RunLoop().RunUntilIdle(); | 336 base::RunLoop().RunUntilIdle(); |
| 227 } | 337 } |
| 228 | 338 |
| 339 TEST_F(BluetoothInterfaceDeviceTest, GetCharacteristics) { | |
| 340 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 341 .WillRepeatedly(Return(true)); | |
| 342 | |
| 343 proxy_->GetCharacteristics(kTestServiceId0, | |
| 344 GetGetCharacteristicsCheckForPrecedingCalls( | |
| 345 Call::EXPECTED, 0 /* num_of_preceding_calls | |
|
scheib
2017/01/13 05:24:40
Use "//" comment style to force auto-wrapping to n
mbrunson
2017/01/13 21:21:13
I've removed these comments. Done.
| |
| 346 */, | |
| 347 2 /* expected_count */)); | |
| 348 | |
| 349 base::RunLoop().RunUntilIdle(); | |
| 350 } | |
| 351 | |
| 352 TEST_F(BluetoothInterfaceDeviceTest, | |
| 353 GetCharacteristicsCheckPropertiesService0) { | |
| 354 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 355 .WillRepeatedly(Return(true)); | |
| 356 | |
| 357 std::vector<Properties> properties; | |
| 358 properties.push_back(kReadWriteProperties); | |
| 359 properties.push_back(kReadWriteProperties); | |
| 360 | |
| 361 proxy_->GetCharacteristics(kTestServiceId0, | |
| 362 GetGetCharacteristicsCheckProperties( | |
| 363 Call::EXPECTED, std::move(properties))); | |
| 364 | |
| 365 base::RunLoop().RunUntilIdle(); | |
| 366 } | |
| 367 | |
| 368 TEST_F(BluetoothInterfaceDeviceTest, | |
| 369 GetCharacteristicsCheckPropertiesService1) { | |
| 370 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 371 .WillRepeatedly(Return(true)); | |
| 372 | |
| 373 std::vector<Properties> properties; | |
| 374 properties.push_back(kAllProperties); | |
| 375 | |
| 376 proxy_->GetCharacteristics(kTestServiceId1, | |
| 377 GetGetCharacteristicsCheckProperties( | |
| 378 Call::EXPECTED, std::move(properties))); | |
| 379 | |
| 380 base::RunLoop().RunUntilIdle(); | |
| 381 } | |
| 382 | |
| 383 TEST_F(BluetoothInterfaceDeviceTest, GetCharacteristicsNotDiscovered) { | |
| 384 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 385 .WillOnce(Return(false)) | |
| 386 .WillOnce(Return(false)) | |
| 387 .WillRepeatedly(Return(true)); | |
| 388 | |
| 389 // Client: Sends multiple requests for services. | |
| 390 proxy_->GetCharacteristics(kTestServiceId0, | |
| 391 GetGetCharacteristicsCheckForPrecedingCalls( | |
| 392 Call::EXPECTED, 0 /* num_of_preceding_calls | |
| 393 */, | |
| 394 2 /* expected_count */)); | |
| 395 proxy_->GetCharacteristics(kTestServiceId1, | |
| 396 GetGetCharacteristicsCheckForPrecedingCalls( | |
| 397 Call::EXPECTED, 1 /* num_of_preceding_calls | |
| 398 */, | |
| 399 1 /* expected_count */)); | |
| 400 | |
| 401 base::RunLoop().RunUntilIdle(); | |
| 402 | |
| 403 SimulateGattServicesDiscovered(); | |
| 404 | |
| 405 // No more GetServices calls will complete. | |
| 406 SimulateGattServicesDiscovered(); | |
| 407 | |
| 408 base::RunLoop().RunUntilIdle(); | |
| 409 | |
| 410 // Client: Sends more requests which run immediately. | |
| 411 proxy_->GetCharacteristics(kTestServiceId0, | |
| 412 GetGetCharacteristicsCheckForPrecedingCalls( | |
| 413 Call::EXPECTED, 2 /* num_of_preceding_calls | |
| 414 */, | |
| 415 2 /* expected_count */)); | |
| 416 proxy_->GetCharacteristics(kTestServiceId1, | |
| 417 GetGetCharacteristicsCheckForPrecedingCalls( | |
| 418 Call::EXPECTED, 3 /* num_of_preceding_calls | |
| 419 */, | |
| 420 1 /* expected_count */)); | |
| 421 | |
| 422 base::RunLoop().RunUntilIdle(); | |
| 423 | |
| 424 // No more GetCharacteristics calls will complete. | |
| 425 SimulateGattServicesDiscovered(); | |
| 426 | |
| 427 // Wait for message pipe to process error. | |
| 428 base::RunLoop().RunUntilIdle(); | |
| 429 } | |
| 430 | |
| 431 TEST_F(BluetoothInterfaceDeviceTest, | |
| 432 GetCharacteristicsLostConnectionWithPendingRequests) { | |
| 433 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 434 .WillRepeatedly(Return(false)); | |
| 435 // Client: Sends multiple requests for characteristics. | |
| 436 proxy_->GetCharacteristics( | |
| 437 kTestServiceId0, | |
| 438 GetGetCharacteristicsCheckForPrecedingCalls(Call::NOT_EXPECTED, 0 /* | |
| 439 num_of_preceding_calls | |
| 440 */, | |
| 441 2 /* expected_count */)); | |
| 442 proxy_->GetCharacteristics( | |
| 443 kTestServiceId1, | |
| 444 GetGetCharacteristicsCheckForPrecedingCalls(Call::NOT_EXPECTED, 1 /* | |
| 445 num_of_preceding_calls | |
| 446 */, | |
| 447 1 /* expected_count */)); | |
| 448 EXPECT_EQ(0, callback_count_); | |
| 449 | |
| 450 // Simulate connection loss. | |
| 451 device_.SetConnected(false); | |
| 452 SimulateDeviceChanged(); | |
| 453 expect_device_service_deleted_ = true; | |
| 454 | |
| 455 // Wait for message pipe to process error. | |
| 456 base::RunLoop().RunUntilIdle(); | |
| 457 } | |
| 458 | |
| 459 TEST_F(BluetoothInterfaceDeviceTest, | |
| 460 GetCharacteristicsForcedDisconnectionWithPendingRequests) { | |
| 461 EXPECT_CALL(device_, IsGattServicesDiscoveryComplete()) | |
| 462 .WillRepeatedly(Return(false)); | |
| 463 | |
| 464 // Client: Sends multiple requests for services. | |
| 465 proxy_->GetCharacteristics( | |
| 466 kTestServiceId0, | |
| 467 GetGetCharacteristicsCheckForPrecedingCalls(Call::NOT_EXPECTED, 0 /* | |
| 468 num_of_preceding_calls | |
| 469 */, | |
| 470 2 /* expected_count */)); | |
| 471 proxy_->GetCharacteristics( | |
| 472 kTestServiceId1, | |
| 473 GetGetCharacteristicsCheckForPrecedingCalls(Call::NOT_EXPECTED, 1 /* | |
| 474 num_of_preceding_calls | |
| 475 */, | |
| 476 1 /* expected_count */)); | |
| 477 EXPECT_EQ(0, callback_count_); | |
| 478 | |
| 479 // Simulate connection loss. | |
| 480 proxy_->Disconnect(); | |
| 481 expect_device_service_deleted_ = true; | |
| 482 | |
| 483 // Wait for message pipe to process error. | |
| 484 base::RunLoop().RunUntilIdle(); | |
| 485 } | |
| 486 | |
| 229 } // namespace bluetooth | 487 } // namespace bluetooth |
| OLD | NEW |