blob: b216b0e260c906d69fb86e2f2bb14ef1cc07acb0 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <memory>
#include <tuple>
#include <utility>
#include "base/test/gmock_move_support.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "content/public/test/browser_test.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_descriptor.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_notify_session.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
#include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h"
#include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h"
#include "extensions/common/extension_builder.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
#include "testing/gmock/include/gmock/gmock.h"
using device::BluetoothUUID;
using device::BluetoothAdapter;
using device::BluetoothDevice;
using device::BluetoothRemoteGattCharacteristic;
using device::BluetoothGattConnection;
using device::BluetoothRemoteGattDescriptor;
using device::BluetoothRemoteGattService;
using device::BluetoothGattNotifySession;
using device::MockBluetoothAdapter;
using device::MockBluetoothDevice;
using device::MockBluetoothGattCharacteristic;
using device::MockBluetoothGattConnection;
using device::MockBluetoothGattDescriptor;
using device::MockBluetoothGattService;
using device::MockBluetoothGattNotifySession;
using extensions::BluetoothLowEnergyEventRouter;
using extensions::ResultCatcher;
using testing::Invoke;
using testing::Return;
using testing::ReturnRef;
using testing::ReturnRefOfCopy;
using testing::SaveArg;
using testing::_;
namespace {
// Test service constants.
const char kTestLeDeviceAddress0[] = "11:22:33:44:55:66";
const char kTestLeDeviceName0[] = "Test LE Device 0";
const char kTestLeDeviceAddress1[] = "77:88:99:AA:BB:CC";
const char kTestLeDeviceName1[] = "Test LE Device 1";
const char kTestServiceId0[] = "service_id0";
const char kTestServiceUuid0[] = "1234";
const char kTestServiceId1[] = "service_id1";
const char kTestServiceUuid1[] = "5678";
// Test characteristic constants.
const char kTestCharacteristicId0[] = "char_id0";
const char kTestCharacteristicUuid0[] = "1211";
const BluetoothRemoteGattCharacteristic::Properties
kTestCharacteristicProperties0 =
BluetoothRemoteGattCharacteristic::PROPERTY_BROADCAST |
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE |
BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE;
const uint8_t kTestCharacteristicDefaultValue0[] = {0x01, 0x02, 0x03, 0x04,
0x05};
const char kTestCharacteristicId1[] = "char_id1";
const char kTestCharacteristicUuid1[] = "1212";
const BluetoothRemoteGattCharacteristic::Properties
kTestCharacteristicProperties1 =
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE |
BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY;
const uint8_t kTestCharacteristicDefaultValue1[] = {0x06, 0x07, 0x08};
const char kTestCharacteristicId2[] = "char_id2";
const char kTestCharacteristicUuid2[] = "1213";
const BluetoothRemoteGattCharacteristic::Properties
kTestCharacteristicProperties2 =
BluetoothRemoteGattCharacteristic::PROPERTY_NONE;
// Test descriptor constants.
const char kTestDescriptorId0[] = "desc_id0";
const char kTestDescriptorUuid0[] = "1221";
const uint8_t kTestDescriptorDefaultValue0[] = {0x01, 0x02, 0x03};
const char kTestDescriptorId1[] = "desc_id1";
const char kTestDescriptorUuid1[] = "1222";
const uint8_t kTestDescriptorDefaultValue1[] = {0x04, 0x05};
class BluetoothLowEnergyApiTest : public extensions::ExtensionApiTest {
public:
BluetoothLowEnergyApiTest() {}
~BluetoothLowEnergyApiTest() override {}
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
empty_extension_ = extensions::ExtensionBuilder("Test").Build();
SetUpMocks();
}
void TearDownOnMainThread() override {
EXPECT_CALL(*mock_adapter_, RemoveObserver(_));
}
void SetUpMocks() {
mock_adapter_ = new testing::StrictMock<MockBluetoothAdapter>();
EXPECT_CALL(*mock_adapter_, GetDevices())
.WillOnce(Return(BluetoothAdapter::ConstDeviceList()));
event_router()->SetAdapterForTesting(mock_adapter_);
device0_ = std::make_unique<testing::NiceMock<MockBluetoothDevice>>(
mock_adapter_, 0, kTestLeDeviceName0, kTestLeDeviceAddress0,
/*paired=*/false, /*connected=*/true);
device1_ = std::make_unique<testing::NiceMock<MockBluetoothDevice>>(
mock_adapter_, 0, kTestLeDeviceName1, kTestLeDeviceAddress1,
/*paired=*/false, /*connected=*/true);
service0_ = std::make_unique<testing::NiceMock<MockBluetoothGattService>>(
device0_.get(), kTestServiceId0, BluetoothUUID(kTestServiceUuid0),
/*is_primary=*/true);
service1_ = std::make_unique<testing::NiceMock<MockBluetoothGattService>>(
device0_.get(), kTestServiceId1, BluetoothUUID(kTestServiceUuid1),
/*is_primary=*/false);
// Assign characteristics some random properties and permissions. They don't
// need to reflect what the characteristic is actually capable of, since
// the JS API just passes values through from
// device::BluetoothRemoteGattCharacteristic.
std::vector<uint8_t> default_value;
chrc0_ =
std::make_unique<testing::NiceMock<MockBluetoothGattCharacteristic>>(
service0_.get(), kTestCharacteristicId0,
BluetoothUUID(kTestCharacteristicUuid0),
kTestCharacteristicProperties0,
BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
default_value.assign(kTestCharacteristicDefaultValue0,
(kTestCharacteristicDefaultValue0 +
sizeof(kTestCharacteristicDefaultValue0)));
ON_CALL(*chrc0_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
chrc1_ =
std::make_unique<testing::NiceMock<MockBluetoothGattCharacteristic>>(
service0_.get(), kTestCharacteristicId1,
BluetoothUUID(kTestCharacteristicUuid1),
kTestCharacteristicProperties1,
BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
default_value.assign(kTestCharacteristicDefaultValue1,
(kTestCharacteristicDefaultValue1 +
sizeof(kTestCharacteristicDefaultValue1)));
ON_CALL(*chrc1_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
chrc2_ =
std::make_unique<testing::NiceMock<MockBluetoothGattCharacteristic>>(
service1_.get(), kTestCharacteristicId2,
BluetoothUUID(kTestCharacteristicUuid2),
kTestCharacteristicProperties2,
BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
desc0_ = std::make_unique<testing::NiceMock<MockBluetoothGattDescriptor>>(
chrc0_.get(), kTestDescriptorId0, BluetoothUUID(kTestDescriptorUuid0),
BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
default_value.assign(
kTestDescriptorDefaultValue0,
(kTestDescriptorDefaultValue0 + sizeof(kTestDescriptorDefaultValue0)));
ON_CALL(*desc0_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
desc1_ = std::make_unique<testing::NiceMock<MockBluetoothGattDescriptor>>(
chrc0_.get(), kTestDescriptorId1, BluetoothUUID(kTestDescriptorUuid1),
BluetoothRemoteGattCharacteristic::PERMISSION_NONE);
default_value.assign(
kTestDescriptorDefaultValue1,
(kTestDescriptorDefaultValue1 + sizeof(kTestDescriptorDefaultValue1)));
ON_CALL(*desc1_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
}
protected:
BluetoothLowEnergyEventRouter* event_router() {
return extensions::BluetoothLowEnergyAPI::Get(browser()->profile())
->event_router();
}
testing::StrictMock<MockBluetoothAdapter>* mock_adapter_;
std::unique_ptr<testing::NiceMock<MockBluetoothDevice>> device0_;
std::unique_ptr<testing::NiceMock<MockBluetoothDevice>> device1_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattService>> service0_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattService>> service1_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattCharacteristic>> chrc0_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattCharacteristic>> chrc1_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattCharacteristic>> chrc2_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattDescriptor>> desc0_;
std::unique_ptr<testing::NiceMock<MockBluetoothGattDescriptor>> desc1_;
private:
scoped_refptr<const extensions::Extension> empty_extension_;
};
ACTION_TEMPLATE(InvokeCallbackArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_0_VALUE_PARAMS()) {
std::move(std::get<k>(args)).Run();
}
ACTION_TEMPLATE(InvokeCallbackArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(p0)) {
std::move(std::get<k>(args)).Run(p0);
}
ACTION_TEMPLATE(InvokeCallbackWithScopedPtrArg,
HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
AND_1_VALUE_PARAMS(p0)) {
std::move(std::get<k>(args)).Run(std::unique_ptr<T>(p0));
}
BluetoothGattConnection* CreateGattConnection(
scoped_refptr<device::BluetoothAdapter> adapter,
const std::string& device_address,
bool expect_disconnect) {
testing::NiceMock<MockBluetoothGattConnection>* conn =
new testing::NiceMock<MockBluetoothGattConnection>(adapter,
device_address);
EXPECT_CALL(*conn, Disconnect()).Times(expect_disconnect ? 1 : 0);
return conn;
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetServices) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
std::vector<BluetoothRemoteGattService*> services;
services.push_back(service0_.get());
services.push_back(service1_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattServices())
.Times(2)
.WillOnce(Return(std::vector<BluetoothRemoteGattService*>()))
.WillOnce(Return(services));
// Load and wait for setup.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_services")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetService) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(2)
.WillOnce(Return(static_cast<BluetoothRemoteGattService*>(NULL)))
.WillOnce(Return(service0_.get()));
// Load and wait for setup.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_service")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ServiceEvents) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
// Load the extension and let it set up.
ExtensionTestMessageListener listener(true);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/service_events")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
// These will create the identifier mappings.
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service1_.get());
// These will send the onServiceAdded event to apps.
event_router()->GattDiscoveryCompleteForService(mock_adapter_,
service0_.get());
event_router()->GattDiscoveryCompleteForService(mock_adapter_,
service1_.get());
// This will send the onServiceChanged event to apps.
event_router()->GattServiceChanged(mock_adapter_, service1_.get());
// This will send the onServiceRemoved event to apps.
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
ASSERT_EQ("ready", listener.message()) << listener.message();
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service1_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedService) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
// Load the extension and let it set up.
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_removed_service")));
// 1. getService success.
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(1)
.WillOnce(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(1)
.WillOnce(Return(service0_.get()));
ExtensionTestMessageListener get_service_success_listener(false);
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattDiscoveryCompleteForService(mock_adapter_,
service0_.get());
EXPECT_TRUE(get_service_success_listener.WaitUntilSatisfied());
ASSERT_EQ("getServiceSuccess", get_service_success_listener.message())
<< get_service_success_listener.message();
testing::Mock::VerifyAndClearExpectations(mock_adapter_);
testing::Mock::VerifyAndClearExpectations(device0_.get());
// 2. getService fail.
EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0)).Times(0);
ExtensionTestMessageListener get_service_fail_listener(true);
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
EXPECT_TRUE(get_service_fail_listener.WaitUntilSatisfied());
ASSERT_EQ("getServiceFail", get_service_fail_listener.message())
<< get_service_fail_listener.message();
testing::Mock::VerifyAndClearExpectations(mock_adapter_);
testing::Mock::VerifyAndClearExpectations(device0_.get());
get_service_fail_listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetIncludedServices) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
// Wait for initial call to end with failure as there is no mapping.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/get_included_services")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
// Set up for the rest of the calls before replying. Included services can be
// returned even if there is no instance ID mapping for them yet, so no need
// to call GattServiceAdded for |service1_| here.
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
std::vector<BluetoothRemoteGattService*> includes;
includes.push_back(service1_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
.Times(2)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(2)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetIncludedServices())
.Times(2)
.WillOnce(Return(std::vector<BluetoothRemoteGattService*>()))
.WillOnce(Return(includes));
listener.Reply("go");
listener.Reset();
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristics) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
std::vector<BluetoothRemoteGattCharacteristic*> characteristics;
characteristics.push_back(chrc0_.get());
characteristics.push_back(chrc1_.get());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(3).WillRepeatedly(
Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(3)
.WillOnce(Return(static_cast<BluetoothRemoteGattService*>(NULL)))
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristics())
.Times(2)
.WillOnce(Return(std::vector<BluetoothRemoteGattCharacteristic*>()))
.WillOnce(Return(characteristics));
ExtensionTestMessageListener listener("ready", true);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristics")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristic) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(4)
.WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(3)
.WillOnce(Return(static_cast<BluetoothRemoteGattService*>(NULL)))
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(2)
.WillOnce(Return(static_cast<BluetoothRemoteGattCharacteristic*>(NULL)))
.WillOnce(Return(chrc0_.get()));
// Load the extension and wait for first test.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristic")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicProperties) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(12)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(12)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(12)
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetProperties())
.Times(12)
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_NONE))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_BROADCAST))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_READ))
.WillOnce(Return(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_WRITE))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE))
.WillOnce(Return(BluetoothRemoteGattCharacteristic::
PROPERTY_AUTHENTICATED_SIGNED_WRITES))
.WillOnce(Return(
BluetoothRemoteGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES))
.WillOnce(
Return(BluetoothRemoteGattCharacteristic::PROPERTY_RELIABLE_WRITE))
.WillOnce(Return(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITABLE_AUXILIARIES))
.WillOnce(Return(
BluetoothRemoteGattCharacteristic::PROPERTY_BROADCAST |
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE |
BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY |
BluetoothRemoteGattCharacteristic::PROPERTY_INDICATE |
BluetoothRemoteGattCharacteristic::
PROPERTY_AUTHENTICATED_SIGNED_WRITES |
BluetoothRemoteGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES |
BluetoothRemoteGattCharacteristic::PROPERTY_RELIABLE_WRITE |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITABLE_AUXILIARIES));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/characteristic_properties")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedCharacteristic) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(1)
.WillOnce(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(1)
.WillOnce(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(1)
.WillOnce(Return(chrc0_.get()));
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
ExtensionTestMessageListener listener(true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/get_removed_characteristic")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("ready", listener.message()) << listener.message();
testing::Mock::VerifyAndClearExpectations(mock_adapter_);
testing::Mock::VerifyAndClearExpectations(device0_.get());
testing::Mock::VerifyAndClearExpectations(service0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
listener.Reply("go");
listener.Reset();
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("ready", listener.message()) << listener.message();
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicValueChanged) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
// Cause events to be sent to the extension.
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service1_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc2_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(2)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(1)
.WillOnce(Return(service0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
.Times(1)
.WillOnce(Return(service1_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(1)
.WillOnce(Return(chrc0_.get()));
EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
.Times(1)
.WillOnce(Return(chrc2_.get()));
BluetoothGattNotifySession* session0 =
new testing::NiceMock<MockBluetoothGattNotifySession>(
chrc0_->GetWeakPtr());
BluetoothGattNotifySession* session1 =
new testing::NiceMock<MockBluetoothGattNotifySession>(
chrc2_->GetWeakPtr());
EXPECT_CALL(*chrc0_, StartNotifySession_(_, _))
.Times(1)
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
session0));
EXPECT_CALL(*chrc2_, StartNotifySession_(_, _))
.Times(1)
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
session1));
ExtensionTestMessageListener listener("ready", true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/characteristic_value_changed")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
std::vector<uint8_t> value;
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc0_.get(), value);
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc2_.get(), value);
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc2_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service1_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadCharacteristicValue) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(4)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(4)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(4)
.WillRepeatedly(Return(chrc0_.get()));
std::vector<uint8_t> value;
EXPECT_CALL(*chrc0_, ReadRemoteCharacteristic_(_, _))
.Times(2)
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
.WillOnce(InvokeCallbackArgument<0>(value));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/read_characteristic_value")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteCharacteristicValue) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(3)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(3)
.WillRepeatedly(Return(chrc0_.get()));
std::vector<uint8_t> write_value;
EXPECT_CALL(*chrc0_, DeprecatedWriteRemoteCharacteristic_(_, _, _))
.Times(2)
.WillOnce(InvokeCallbackArgument<2>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
.WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
EXPECT_CALL(*chrc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/write_characteristic_value")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptors) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
std::vector<BluetoothRemoteGattDescriptor*> descriptors;
descriptors.push_back(desc0_.get());
descriptors.push_back(desc1_.get());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(3)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(3)
.WillOnce(Return(static_cast<BluetoothRemoteGattCharacteristic*>(NULL)))
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptors())
.Times(2)
.WillOnce(Return(std::vector<BluetoothRemoteGattDescriptor*>()))
.WillOnce(Return(descriptors));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptors")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptor) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(5)
.WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(4)
.WillOnce(Return(static_cast<BluetoothRemoteGattService*>(NULL)))
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(3)
.WillOnce(Return(static_cast<BluetoothRemoteGattCharacteristic*>(NULL)))
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.Times(2)
.WillOnce(Return(static_cast<BluetoothRemoteGattDescriptor*>(NULL)))
.WillOnce(Return(desc0_.get()));
// Load the extension and wait for first test.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptor")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedDescriptor) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(1)
.WillOnce(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(1)
.WillOnce(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(1)
.WillOnce(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.Times(1)
.WillOnce(Return(desc0_.get()));
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
ExtensionTestMessageListener listener(true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/get_removed_descriptor")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("ready", listener.message()) << listener.message();
testing::Mock::VerifyAndClearExpectations(mock_adapter_);
testing::Mock::VerifyAndClearExpectations(device0_.get());
testing::Mock::VerifyAndClearExpectations(service0_.get());
testing::Mock::VerifyAndClearExpectations(chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
EXPECT_CALL(*chrc0_, GetDescriptor(_)).Times(0);
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
listener.Reply("go");
listener.Reset();
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("ready", listener.message()) << listener.message();
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, DescriptorValueChanged) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc1_.get());
// Load the extension and let it set up.
ExtensionTestMessageListener listener("ready", true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/descriptor_value_changed")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
// Cause events to be sent to the extension.
std::vector<uint8_t> value;
event_router()->GattDescriptorValueChanged(
mock_adapter_, desc0_.get(), value);
event_router()->GattDescriptorValueChanged(
mock_adapter_, desc1_.get(), value);
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc1_.get());
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadDescriptorValue) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(9)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(9)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(9)
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.Times(9)
.WillRepeatedly(Return(desc0_.get()));
std::vector<uint8_t> value;
EXPECT_CALL(*desc0_, ReadRemoteDescriptor_(_, _))
.Times(8)
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_NOT_AUTHORIZED))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_NOT_PAIRED))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED))
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS))
.WillOnce(InvokeCallbackArgument<0>(value));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/read_descriptor_value")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteDescriptorValue) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.Times(3)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(3)
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.Times(3)
.WillRepeatedly(Return(desc0_.get()));
std::vector<uint8_t> write_value;
EXPECT_CALL(*desc0_, WriteRemoteDescriptor_(_, _, _))
.Times(2)
.WillOnce(InvokeCallbackArgument<2>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
.WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
EXPECT_CALL(*desc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/write_descriptor_value")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, PermissionDenied) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/permission_denied")));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionMethods) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
std::vector<BluetoothRemoteGattService*> services;
services.push_back(service0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattServices()).WillOnce(Return(services));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.WillRepeatedly(Return(desc0_.get()));
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/uuid_permission_methods")));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionEvents) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
ExtensionTestMessageListener listener(true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/uuid_permission_events")));
// Cause events to be sent to the extension.
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
std::vector<uint8_t> value;
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc0_.get(), value);
event_router()->GattDescriptorValueChanged(
mock_adapter_, desc0_.get(), value);
event_router()->GattServiceChanged(mock_adapter_, service0_.get());
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
ASSERT_EQ("ready", listener.message()) << listener.message();
event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GattConnection) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.WillRepeatedly(Return(static_cast<BluetoothDevice*>(NULL)));
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress1))
.WillRepeatedly(Return(device1_.get()));
static_assert(
BluetoothDevice::NUM_CONNECT_ERROR_CODES == 8,
"Update required if the number of BluetoothDevice enums changes.");
EXPECT_CALL(*device0_, CreateGattConnection_(_, _))
.Times(9)
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_FAILED))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_INPROGRESS))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_FAILED))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_REJECTED))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_CANCELED))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_TIMEOUT))
.WillOnce(
InvokeCallbackArgument<1>(BluetoothDevice::ERROR_UNSUPPORTED_DEVICE))
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
CreateGattConnection(mock_adapter_, kTestLeDeviceAddress0,
true /* expect_disconnect */)))
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
CreateGattConnection(mock_adapter_, kTestLeDeviceAddress0,
false /* expect_disconnect */)));
EXPECT_CALL(*device1_, CreateGattConnection_(_, _))
.Times(1)
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
CreateGattConnection(mock_adapter_, kTestLeDeviceAddress1,
true /* expect_disconnect */)));
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/gatt_connection")));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReconnectAfterDisconnected) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
.WillRepeatedly(Return(device0_.get()));
MockBluetoothGattConnection* first_conn =
static_cast<MockBluetoothGattConnection*>(CreateGattConnection(
mock_adapter_, kTestLeDeviceAddress0, false /* expect_disconnect */));
EXPECT_CALL(*first_conn, IsConnected())
.Times(2)
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(*device0_, CreateGattConnection_(_, _))
.Times(2)
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
first_conn))
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
CreateGattConnection(mock_adapter_, kTestLeDeviceAddress0,
false /* expect_disconnect */)));
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/reconnect_after_disconnected")));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ConnectInProgress) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
.WillRepeatedly(Return(device0_.get()));
BluetoothDevice::GattConnectionCallback connect_callback;
testing::NiceMock<MockBluetoothGattConnection>* conn =
new testing::NiceMock<MockBluetoothGattConnection>(mock_adapter_,
kTestLeDeviceAddress0);
std::unique_ptr<BluetoothGattConnection> conn_ptr(conn);
EXPECT_CALL(*conn, Disconnect()).Times(1);
EXPECT_CALL(*device0_, CreateGattConnection_(_, _))
.Times(1)
.WillOnce(MoveArg<0>(&connect_callback));
ExtensionTestMessageListener listener(false);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/connect_in_progress")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("After 2nd connect fails due to 1st connect being in progress.",
listener.message())
<< listener.message();
listener.Reset();
std::move(connect_callback).Run(std::move(conn_ptr));
EXPECT_TRUE(listener.WaitUntilSatisfied());
ASSERT_EQ("After 2nd call to disconnect.", listener.message())
<< listener.message();
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, StartStopNotifications) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service0_.get());
event_router()->GattServiceAdded(
mock_adapter_, device0_.get(), service1_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc1_.get());
event_router()->GattCharacteristicAdded(mock_adapter_, chrc2_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
.WillRepeatedly(Return(service1_.get()));
EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
.Times(1)
.WillOnce(Return(chrc2_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(2)
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId1))
.Times(1)
.WillOnce(Return(chrc1_.get()));
BluetoothGattNotifySession* session0 =
new testing::NiceMock<MockBluetoothGattNotifySession>(
chrc0_->GetWeakPtr());
MockBluetoothGattNotifySession* session1 =
new testing::NiceMock<MockBluetoothGattNotifySession>(
chrc1_->GetWeakPtr());
EXPECT_CALL(*session1, Stop_(_))
.Times(1)
.WillOnce(InvokeCallbackArgument<0>());
EXPECT_CALL(*chrc0_, StartNotifySession_(_, _))
.Times(2)
.WillOnce(InvokeCallbackArgument<1>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
session0));
EXPECT_CALL(*chrc1_, StartNotifySession_(_, _))
.Times(1)
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
session1));
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/start_stop_notifications")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
std::vector<uint8_t> value;
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc0_.get(), value);
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc1_.get(), value);
event_router()->GattCharacteristicValueChanged(
mock_adapter_, chrc2_.get(), value);
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc2_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc1_.get());
event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service1_.get());
event_router()->GattServiceRemoved(
mock_adapter_, device0_.get(), service0_.get());
}
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, AddressChange) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
event_router()->GattServiceAdded(mock_adapter_, device0_.get(),
service0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
.WillRepeatedly(Return(service0_.get()));
const std::string kTestLeDeviceNewAddress0 = std::string("11:22:33:44:55:77");
EXPECT_CALL(*device0_, GetAddress())
.WillRepeatedly(Return(kTestLeDeviceNewAddress0));
std::string old_address;
event_router()->DeviceAddressChanged(mock_adapter_, device0_.get(),
kTestLeDeviceAddress0);
// Load and wait for setup.
ExtensionTestMessageListener listener("ready", true);
listener.set_failure_message("fail");
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("bluetooth_low_energy/address_change")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattServiceRemoved(mock_adapter_, device0_.get(),
service0_.get());
}
} // namespace