Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/bluetooth_gatt_characteristic.h" | 5 #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 #include "device/bluetooth/bluetooth_gatt_service.h" | 12 #include "device/bluetooth/bluetooth_gatt_service.h" |
| 13 #include "device/bluetooth/test/test_bluetooth_adapter_observer.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 15 |
| 15 #if defined(OS_ANDROID) | 16 #if defined(OS_ANDROID) |
| 16 #include "device/bluetooth/test/bluetooth_test_android.h" | 17 #include "device/bluetooth/test/bluetooth_test_android.h" |
| 17 #elif defined(OS_MACOSX) | 18 #elif defined(OS_MACOSX) |
| 18 #include "device/bluetooth/test/bluetooth_test_mac.h" | 19 #include "device/bluetooth/test/bluetooth_test_mac.h" |
| 19 #endif | 20 #endif |
| 20 | 21 |
| 21 namespace device { | 22 namespace device { |
| 22 | 23 |
| 23 #if defined(OS_ANDROID) || defined(OS_MACOSX) | 24 #if defined(OS_ANDROID) || defined(OS_MACOSX) |
| 24 class BluetoothGattCharacteristicTest : public BluetoothTest { | 25 class BluetoothGattCharacteristicTest : public BluetoothTest { |
| 25 public: | 26 public: |
| 26 // Creates adapter_, device_, service_, characteristic1_, & characteristic2_. | 27 // Creates adapter_, device_, service_, characteristic1_, & characteristic2_. |
| 27 void FakeCharacteristicBoilerplate() { | 28 // |properties| will be used for each characteristic. |
| 29 void FakeCharacteristicBoilerplate(int properties = 0) { | |
| 28 InitWithFakeAdapter(); | 30 InitWithFakeAdapter(); |
| 29 StartLowEnergyDiscoverySession(); | 31 StartLowEnergyDiscoverySession(); |
| 30 device_ = DiscoverLowEnergyDevice(3); | 32 device_ = DiscoverLowEnergyDevice(3); |
| 31 device_->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), | 33 device_->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), |
| 32 GetConnectErrorCallback(Call::NOT_EXPECTED)); | 34 GetConnectErrorCallback(Call::NOT_EXPECTED)); |
| 33 SimulateGattConnection(device_); | 35 SimulateGattConnection(device_); |
| 34 std::vector<std::string> services; | 36 std::vector<std::string> services; |
| 35 std::string uuid("00000000-0000-1000-8000-00805f9b34fb"); | 37 std::string uuid("00000000-0000-1000-8000-00805f9b34fb"); |
| 36 services.push_back(uuid); | 38 services.push_back(uuid); |
| 37 SimulateGattServicesDiscovered(device_, services); | 39 SimulateGattServicesDiscovered(device_, services); |
| 38 ASSERT_EQ(1u, device_->GetGattServices().size()); | 40 ASSERT_EQ(1u, device_->GetGattServices().size()); |
| 39 service_ = device_->GetGattServices()[0]; | 41 service_ = device_->GetGattServices()[0]; |
| 40 SimulateGattCharacteristic(service_, uuid, /* properties */ 0); | 42 SimulateGattCharacteristic(service_, uuid, properties); |
| 41 SimulateGattCharacteristic(service_, uuid, /* properties */ 0); | 43 SimulateGattCharacteristic(service_, uuid, properties); |
| 42 ASSERT_EQ(2u, service_->GetCharacteristics().size()); | 44 ASSERT_EQ(2u, service_->GetCharacteristics().size()); |
| 43 characteristic1_ = service_->GetCharacteristics()[0]; | 45 characteristic1_ = service_->GetCharacteristics()[0]; |
| 44 characteristic2_ = service_->GetCharacteristics()[1]; | 46 characteristic2_ = service_->GetCharacteristics()[1]; |
| 45 ResetEventCounts(); | 47 ResetEventCounts(); |
| 46 } | 48 } |
| 47 | 49 |
| 50 // Constructs characteristics with |properties|, calls StartNotifySession, | |
| 51 // and verifies the appropriate |expected_config_descriptor_value| is written. | |
| 52 void StartNotifyBoilerplate(int properties, | |
| 53 uint16_t expected_config_descriptor_value) { | |
| 54 ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(properties)); | |
| 55 SimulateGattDescriptor( | |
| 56 characteristic1_, | |
| 57 /* Client Characteristic Configuration descriptor's standard UUID: */ | |
| 58 "00002902-0000-1000-8000-00805F9B34FB"); | |
| 59 ASSERT_EQ(1u, characteristic1_->GetDescriptors().size()); | |
| 60 | |
| 61 characteristic1_->StartNotifySession( | |
| 62 GetNotifyCallback(Call::EXPECTED), | |
| 63 GetGattErrorCallback(Call::NOT_EXPECTED)); | |
| 64 EXPECT_EQ(1, gatt_notify_characteristic_attempts_); | |
| 65 EXPECT_EQ(0, callback_count_); | |
| 66 SimulateGattNotifySessionStarted(characteristic1_); | |
| 67 EXPECT_EQ(1, callback_count_); | |
| 68 EXPECT_EQ(0, error_callback_count_); | |
| 69 ASSERT_EQ(1u, notify_sessions_.size()); | |
| 70 ASSERT_TRUE(notify_sessions_[0]); | |
| 71 EXPECT_EQ(characteristic1_->GetIdentifier(), | |
| 72 notify_sessions_[0]->GetCharacteristicIdentifier()); | |
| 73 EXPECT_TRUE(notify_sessions_[0]->IsActive()); | |
| 74 | |
| 75 // Verify the Client Characteristic Configuration descriptor was written to. | |
| 76 EXPECT_EQ(1, gatt_write_descriptor_attempts_); | |
| 77 std::vector<uint8_t> written_vector( | |
| 78 &expected_config_descriptor_value, | |
|
Jeffrey Yasskin
2016/01/14 00:13:42
You mean to pull the bytes out of here, right? Ins
scheib
2016/01/14 01:12:26
Thanks - double check this version.
| |
| 79 &expected_config_descriptor_value + | |
| 80 sizeof(expected_config_descriptor_value)); | |
| 81 EXPECT_EQ(written_vector, last_write_value_); | |
| 82 } | |
| 83 | |
| 48 BluetoothDevice* device_ = nullptr; | 84 BluetoothDevice* device_ = nullptr; |
| 49 BluetoothGattService* service_ = nullptr; | 85 BluetoothGattService* service_ = nullptr; |
| 50 BluetoothGattCharacteristic* characteristic1_ = nullptr; | 86 BluetoothGattCharacteristic* characteristic1_ = nullptr; |
| 51 BluetoothGattCharacteristic* characteristic2_ = nullptr; | 87 BluetoothGattCharacteristic* characteristic2_ = nullptr; |
| 52 }; | 88 }; |
| 53 #endif | 89 #endif |
| 54 | 90 |
| 55 #if defined(OS_ANDROID) | 91 #if defined(OS_ANDROID) |
| 56 TEST_F(BluetoothGattCharacteristicTest, GetIdentifier) { | 92 TEST_F(BluetoothGattCharacteristicTest, GetIdentifier) { |
| 57 InitWithFakeAdapter(); | 93 InitWithFakeAdapter(); |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 | 667 |
| 632 // Initial read should still succeed: | 668 // Initial read should still succeed: |
| 633 ResetEventCounts(); | 669 ResetEventCounts(); |
| 634 SimulateGattCharacteristicRead(characteristic1_, empty_vector); | 670 SimulateGattCharacteristicRead(characteristic1_, empty_vector); |
| 635 EXPECT_EQ(1, callback_count_); | 671 EXPECT_EQ(1, callback_count_); |
| 636 EXPECT_EQ(0, error_callback_count_); | 672 EXPECT_EQ(0, error_callback_count_); |
| 637 } | 673 } |
| 638 #endif // defined(OS_ANDROID) | 674 #endif // defined(OS_ANDROID) |
| 639 | 675 |
| 640 #if defined(OS_ANDROID) | 676 #if defined(OS_ANDROID) |
| 641 // Tests StartNotifySession success. | 677 // StartNotifySession fails if characteristic doesn't have Notify or Indicate |
| 642 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession) { | 678 // property. |
| 679 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_NoNotifyOrIndicate) { | |
| 643 ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); | 680 ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); |
| 644 | 681 |
| 645 characteristic1_->StartNotifySession( | 682 characteristic1_->StartNotifySession(GetNotifyCallback(Call::NOT_EXPECTED), |
| 646 GetNotifyCallback(Call::EXPECTED), | 683 GetGattErrorCallback(Call::EXPECTED)); |
| 647 GetGattErrorCallback(Call::NOT_EXPECTED)); | 684 EXPECT_EQ(0, gatt_notify_characteristic_attempts_); |
| 648 EXPECT_EQ(1, gatt_notify_characteristic_attempts_); | 685 |
| 649 EXPECT_EQ(0, callback_count_); | 686 // The expected error callback is asynchronous: |
| 650 SimulateGattNotifySessionStarted(characteristic1_); | |
| 651 EXPECT_EQ(1, callback_count_); | |
| 652 EXPECT_EQ(0, error_callback_count_); | 687 EXPECT_EQ(0, error_callback_count_); |
| 653 ASSERT_EQ(1u, notify_sessions_.size()); | 688 base::RunLoop().RunUntilIdle(); |
| 654 ASSERT_TRUE(notify_sessions_[0]); | 689 EXPECT_EQ(1, error_callback_count_); |
| 655 EXPECT_EQ(characteristic1_->GetIdentifier(), | 690 } |
| 656 notify_sessions_[0]->GetCharacteristicIdentifier()); | 691 #endif // defined(OS_ANDROID) |
| 657 EXPECT_TRUE(notify_sessions_[0]->IsActive()); | 692 |
| 693 #if defined(OS_ANDROID) | |
| 694 // StartNotifySession fails if the characteristic is missing the Client | |
| 695 // Characteristic Configuration descriptor. | |
| 696 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_NoConfigDescriptor) { | |
| 697 ASSERT_NO_FATAL_FAILURE( | |
| 698 FakeCharacteristicBoilerplate(/* properties: NOTIFY */ 0x10)); | |
| 699 | |
| 700 characteristic1_->StartNotifySession(GetNotifyCallback(Call::NOT_EXPECTED), | |
| 701 GetGattErrorCallback(Call::EXPECTED)); | |
| 702 EXPECT_EQ(0, gatt_notify_characteristic_attempts_); | |
| 703 | |
| 704 // The expected error callback is asynchronous: | |
| 705 EXPECT_EQ(0, error_callback_count_); | |
| 706 base::RunLoop().RunUntilIdle(); | |
| 707 EXPECT_EQ(1, error_callback_count_); | |
| 658 } | 708 } |
| 659 #endif // defined(OS_ANDROID) | 709 #endif // defined(OS_ANDROID) |
| 660 | 710 |
| 661 #if defined(OS_ANDROID) | 711 #if defined(OS_ANDROID) |
| 662 // Tests StartNotifySession synchronous failure. | 712 // Tests StartNotifySession synchronous failure. |
| 663 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_SynchronousError) { | 713 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_SynchronousError) { |
|
Jeffrey Yasskin
2016/01/14 00:13:43
Is "SynchronousError" the most descriptive name fo
scheib
2016/01/14 01:12:26
Done. Naming was intentionally abstracting platfor
| |
| 664 ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); | 714 ASSERT_NO_FATAL_FAILURE( |
| 715 FakeCharacteristicBoilerplate(/* properties: NOTIFY */ 0x10)); | |
| 665 | 716 |
| 666 SimulateGattCharacteristicSetNotifyWillFailSynchronouslyOnce( | 717 SimulateGattCharacteristicSetNotifyWillFailSynchronouslyOnce( |
|
Jeffrey Yasskin
2016/01/14 00:13:42
If you remove this line, does the test fail? I sus
scheib
2016/01/14 01:12:26
It needed the descriptor. Code coverage here is br
Jeffrey Yasskin
2016/01/14 18:43:31
One way to do it would be to have StartNotifyBoile
scheib
2016/01/14 21:02:14
Nice idea - I'll refactor to use it in a follow up
| |
| 667 characteristic1_); | 718 characteristic1_); |
| 668 characteristic1_->StartNotifySession(GetNotifyCallback(Call::NOT_EXPECTED), | 719 characteristic1_->StartNotifySession(GetNotifyCallback(Call::NOT_EXPECTED), |
| 669 GetGattErrorCallback(Call::EXPECTED)); | 720 GetGattErrorCallback(Call::EXPECTED)); |
| 670 EXPECT_EQ(0, error_callback_count_); | 721 EXPECT_EQ(0, error_callback_count_); |
| 671 base::RunLoop().RunUntilIdle(); | 722 base::RunLoop().RunUntilIdle(); |
| 723 EXPECT_EQ(1, error_callback_count_); | |
| 672 EXPECT_EQ(0, gatt_notify_characteristic_attempts_); | 724 EXPECT_EQ(0, gatt_notify_characteristic_attempts_); |
| 673 EXPECT_EQ(0, callback_count_); | 725 ASSERT_EQ(0u, notify_sessions_.size()); |
| 726 } | |
| 727 #endif // defined(OS_ANDROID) | |
| 728 | |
| 729 #if defined(OS_ANDROID) | |
| 730 // Tests StartNotifySession descriptor write synchronous failure. | |
| 731 TEST_F(BluetoothGattCharacteristicTest, | |
| 732 StartNotifySession_WriteDescriptorSynchronousError) { | |
| 733 ASSERT_NO_FATAL_FAILURE( | |
| 734 FakeCharacteristicBoilerplate(/* properties: NOTIFY */ 0x10)); | |
| 735 SimulateGattDescriptor( | |
| 736 characteristic1_, | |
| 737 /* Client Characteristic Configuration descriptor's standard UUID: */ | |
| 738 "00002902-0000-1000-8000-00805F9B34FB"); | |
| 739 ASSERT_EQ(1u, characteristic1_->GetDescriptors().size()); | |
| 740 | |
| 741 // Fail to write to config descriptor synchronously. | |
| 742 SimulateGattDescriptorWriteWillFailSynchronouslyOnce( | |
| 743 characteristic1_->GetDescriptors()[0]); | |
| 744 | |
| 745 characteristic1_->StartNotifySession(GetNotifyCallback(Call::NOT_EXPECTED), | |
| 746 GetGattErrorCallback(Call::EXPECTED)); | |
| 747 EXPECT_EQ(0, error_callback_count_); | |
| 748 base::RunLoop().RunUntilIdle(); | |
| 674 EXPECT_EQ(1, error_callback_count_); | 749 EXPECT_EQ(1, error_callback_count_); |
| 750 EXPECT_EQ(1, gatt_notify_characteristic_attempts_); | |
| 675 ASSERT_EQ(0u, notify_sessions_.size()); | 751 ASSERT_EQ(0u, notify_sessions_.size()); |
| 676 } | 752 } |
| 677 #endif // defined(OS_ANDROID) | 753 #endif // defined(OS_ANDROID) |
| 678 | 754 |
| 679 #if defined(OS_ANDROID) | 755 #if defined(OS_ANDROID) |
| 756 // Tests StartNotifySession success. | |
| 757 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession) { | |
| 758 ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( | |
| 759 /* properties: NOTIFY */ 0x10, | |
| 760 /* expected_config_descriptor_value: NOTIFY */ 1)); | |
| 761 } | |
| 762 #endif // defined(OS_ANDROID) | |
| 763 | |
| 764 #if defined(OS_ANDROID) | |
| 765 // Tests StartNotifySession success. | |
| 766 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_OnIndicate) { | |
| 767 ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( | |
| 768 /* properties: INDICATE */ 0x20, | |
|
Jeffrey Yasskin
2016/01/14 00:13:42
Please also check when both NOTIFY and INDICATE pr
scheib
2016/01/14 01:12:26
Done.
| |
| 769 /* expected_config_descriptor_value: INDICATE */ 2)); | |
| 770 } | |
| 771 #endif // defined(OS_ANDROID) | |
| 772 | |
| 773 #if defined(OS_ANDROID) | |
| 774 // Tests Characteristic Value changes during a Notify Session. | |
| 775 TEST_F(BluetoothGattCharacteristicTest, GattCharacteristicValueChanged) { | |
| 776 ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( | |
| 777 /* properties: NOTIFY */ 0x10, | |
| 778 /* expected_config_descriptor_value: NOTIFY */ 1)); | |
| 779 | |
| 780 TestBluetoothAdapterObserver observer(adapter_); | |
| 781 | |
| 782 std::vector<uint8_t> test_vector1; | |
| 783 test_vector1.push_back(111); | |
| 784 std::vector<uint8_t> test_vector2; | |
| 785 test_vector2.push_back(222); | |
| 786 | |
| 787 SimulateGattCharacteristicChanged(characteristic1_, test_vector1); | |
| 788 EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count()); | |
| 789 EXPECT_EQ(test_vector1, characteristic1_->GetValue()); | |
| 790 | |
| 791 SimulateGattCharacteristicChanged(characteristic1_, test_vector2); | |
| 792 EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count()); | |
| 793 EXPECT_EQ(test_vector2, characteristic1_->GetValue()); | |
| 794 } | |
| 795 #endif // defined(OS_ANDROID) | |
| 796 | |
| 797 #if defined(OS_ANDROID) | |
| 798 // Tests Characteristic Value changing after a Notify Session and objects being | |
| 799 // destroyed. | |
| 800 TEST_F(BluetoothGattCharacteristicTest, | |
| 801 GattCharacteristicValueChanged_AfterDeleted) { | |
| 802 ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate( | |
| 803 /* properties: NOTIFY */ 0x10, | |
| 804 /* expected_config_descriptor_value: NOTIFY */ 1)); | |
| 805 | |
| 806 RememberCharacteristicForSubsequentAction(characteristic1_); | |
| 807 DeleteDevice(device_); | |
| 808 | |
| 809 std::vector<uint8_t> empty_vector; | |
| 810 SimulateGattCharacteristicChanged(/* use remembered characteristic */ nullptr, | |
|
Jeffrey Yasskin
2016/01/14 00:13:42
Please comment that the test here is that nothing
scheib
2016/01/14 01:12:26
Done.
| |
| 811 empty_vector); | |
| 812 } | |
| 813 #endif // defined(OS_ANDROID) | |
| 814 | |
| 815 #if defined(OS_ANDROID) | |
| 680 // Tests multiple StartNotifySession success. | 816 // Tests multiple StartNotifySession success. |
| 681 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_Multiple) { | 817 TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_Multiple) { |
| 682 ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); | 818 ASSERT_NO_FATAL_FAILURE( |
| 819 FakeCharacteristicBoilerplate(/* properties: NOTIFY */ 0x10)); | |
| 820 SimulateGattDescriptor( | |
| 821 characteristic1_, | |
| 822 /* Client Characteristic Configuration descriptor's standard UUID: */ | |
| 823 "00002902-0000-1000-8000-00805F9B34FB"); | |
| 824 ASSERT_EQ(1u, characteristic1_->GetDescriptors().size()); | |
| 683 | 825 |
| 684 characteristic1_->StartNotifySession( | 826 characteristic1_->StartNotifySession( |
| 685 GetNotifyCallback(Call::EXPECTED), | 827 GetNotifyCallback(Call::EXPECTED), |
| 686 GetGattErrorCallback(Call::NOT_EXPECTED)); | 828 GetGattErrorCallback(Call::NOT_EXPECTED)); |
| 687 characteristic1_->StartNotifySession( | 829 characteristic1_->StartNotifySession( |
| 688 GetNotifyCallback(Call::EXPECTED), | 830 GetNotifyCallback(Call::EXPECTED), |
| 689 GetGattErrorCallback(Call::NOT_EXPECTED)); | 831 GetGattErrorCallback(Call::NOT_EXPECTED)); |
| 690 #if defined(OS_ANDROID) | 832 #if defined(OS_ANDROID) |
| 691 // TODO(crbug.com/551634): Decide when implementing IsNotifying if Android | 833 // TODO(crbug.com/551634): Decide when implementing IsNotifying if Android |
| 692 // should trust the notification request always worked, or if we should always | 834 // should trust the notification request always worked, or if we should always |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 | 900 |
| 759 // Characteristic 1 has descriptor uuids 1 and 2 (we don't know the order). | 901 // Characteristic 1 has descriptor uuids 1 and 2 (we don't know the order). |
| 760 EXPECT_TRUE(c1_uuid1 == uuid1 || c1_uuid2 == uuid1); | 902 EXPECT_TRUE(c1_uuid1 == uuid1 || c1_uuid2 == uuid1); |
| 761 EXPECT_TRUE(c1_uuid1 == uuid2 || c1_uuid2 == uuid2); | 903 EXPECT_TRUE(c1_uuid1 == uuid2 || c1_uuid2 == uuid2); |
| 762 // ... but not uuid 3 | 904 // ... but not uuid 3 |
| 763 EXPECT_FALSE(c1_uuid1 == uuid3 || c1_uuid2 == uuid3); | 905 EXPECT_FALSE(c1_uuid1 == uuid3 || c1_uuid2 == uuid3); |
| 764 } | 906 } |
| 765 #endif // defined(OS_ANDROID) | 907 #endif // defined(OS_ANDROID) |
| 766 | 908 |
| 767 } // namespace device | 909 } // namespace device |
| OLD | NEW |