| Index: device/bluetooth/test/bluetooth_test_mac.mm
|
| diff --git a/device/bluetooth/test/bluetooth_test_mac.mm b/device/bluetooth/test/bluetooth_test_mac.mm
|
| index 3f9f72f833a7cb6a13cdbf6aed93c5268a8dfe59..749f744a488ad1b4a7bd60a17b78b1bd39610b35 100644
|
| --- a/device/bluetooth/test/bluetooth_test_mac.mm
|
| +++ b/device/bluetooth/test/bluetooth_test_mac.mm
|
| @@ -2,18 +2,69 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include "base/strings/string_number_conversions.h"
|
| #include "device/bluetooth/bluetooth_adapter_mac.h"
|
| #include "device/bluetooth/test/bluetooth_test_mac.h"
|
| #include "device/bluetooth/test/mock_bluetooth_central_manager_mac.h"
|
| +#include "third_party/ocmock/OCMock/OCMock.h"
|
| +
|
| +#if defined(OS_IOS)
|
| +#import <CoreBluetooth/CoreBluetooth.h>
|
| +#else // !defined(OS_IOS)
|
| +#import <IOBluetooth/IOBluetooth.h>
|
| +#endif // defined(OS_IOS)
|
|
|
| namespace device {
|
|
|
| +namespace {
|
| +
|
| +CBPeripheral* CreateMockPeripheral(NSString* identifier) {
|
| + Class peripheral_class = NSClassFromString(@"CBPeripheral");
|
| + id mock_peripheral = [OCMockObject mockForClass:[peripheral_class class]];
|
| + [static_cast<CBPeripheral*>(
|
| + [[mock_peripheral stub] andReturnValue:@(CBPeripheralStateDisconnected)])
|
| + performSelector:@selector(state)];
|
| + [[[mock_peripheral stub] andReturn:[NSString string]] name];
|
| + Class uuid_class = NSClassFromString(@"NSUUID");
|
| + [[[mock_peripheral stub]
|
| + andReturn:[[uuid_class performSelector:@selector(UUID)]
|
| + performSelector:@selector(initWithUUIDString:)
|
| + withObject:identifier]] identifier];
|
| +
|
| + return mock_peripheral;
|
| +}
|
| +
|
| +NSDictionary* CreateAdvertisementData(NSString* name, NSArray* uuids) {
|
| + NSMutableDictionary* advertisement_data =
|
| + [NSMutableDictionary dictionaryWithDictionary:@{
|
| + @"CBAdvertisementDataLocalNameKey" : name,
|
| + @"CBAdvertisementDataServiceDataKey" : [NSDictionary dictionary],
|
| + @"CBAdvertisementDataIsConnectable" : @(YES),
|
| + }];
|
| + if (uuids)
|
| + [advertisement_data setObject:uuids
|
| + forKey:@"CBAdvertisementDataServiceUUIDsKey"];
|
| + return advertisement_data;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// UUID1 hashes to kTestDeviceAddress1, and UUID2 to kTestDeviceAddress2.
|
| +const std::string BluetoothTestMac::kTestPeripheralUUID1 =
|
| + "34045B00-0000-0000-0000-000000000000";
|
| +const std::string BluetoothTestMac::kTestPeripheralUUID2 =
|
| + "EC1B8F00-0000-0000-0000-000000000000";
|
| +
|
| BluetoothTestMac::BluetoothTestMac() {}
|
|
|
| BluetoothTestMac::~BluetoothTestMac() {}
|
|
|
| void BluetoothTestMac::SetUp() {}
|
|
|
| +bool BluetoothTestMac::PlatformSupportsLowEnergy() {
|
| + return BluetoothAdapterMac::IsLowEnergyAvailable();
|
| +}
|
| +
|
| void BluetoothTestMac::InitWithDefaultAdapter() {
|
| adapter_mac_ = BluetoothAdapterMac::CreateAdapter().get();
|
| adapter_ = adapter_mac_;
|
| @@ -46,4 +97,114 @@ void BluetoothTestMac::InitWithFakeAdapter() {
|
| }
|
| }
|
|
|
| +void BluetoothTestMac::DiscoverLowEnergyDevice(int device_ordinal) {
|
| + CBCentralManager* central_manager = adapter_mac_->low_energy_central_manager_;
|
| + BluetoothLowEnergyCentralManagerDelegate* central_manager_delegate =
|
| + adapter_mac_->low_energy_central_manager_delegate_;
|
| + Class cbuuid_class = NSClassFromString(@"CBUUID");
|
| + switch (device_ordinal) {
|
| + case 1: {
|
| + CBPeripheral* peripheral = CreateMockPeripheral(
|
| + [NSString stringWithUTF8String:kTestPeripheralUUID1.c_str()]);
|
| + NSString* name = [NSString stringWithUTF8String:kTestDeviceName.c_str()];
|
| + NSArray* uuids = @[
|
| + [cbuuid_class
|
| + UUIDWithString:[NSString stringWithUTF8String:kTestUUIDGenericAccess
|
| + .c_str()]],
|
| + [cbuuid_class
|
| + UUIDWithString:[NSString
|
| + stringWithUTF8String:kTestUUIDGenericAttribute
|
| + .c_str()]]
|
| + ];
|
| + NSDictionary* advertisement_data = CreateAdvertisementData(name, uuids);
|
| + [central_manager_delegate centralManager:central_manager
|
| + didDiscoverPeripheral:peripheral
|
| + advertisementData:advertisement_data
|
| + RSSI:0];
|
| + break;
|
| + }
|
| + case 2: {
|
| + CBPeripheral* peripheral = CreateMockPeripheral(
|
| + [NSString stringWithUTF8String:kTestPeripheralUUID1.c_str()]);
|
| + NSString* name = [NSString stringWithUTF8String:kTestDeviceName.c_str()];
|
| + NSArray* uuids = @[
|
| + [cbuuid_class
|
| + UUIDWithString:[NSString
|
| + stringWithUTF8String:kTestUUIDImmediateAlert
|
| + .c_str()]],
|
| + [cbuuid_class
|
| + UUIDWithString:[NSString
|
| + stringWithUTF8String:kTestUUIDLinkLoss.c_str()]]
|
| + ];
|
| + NSDictionary* advertisement_data = CreateAdvertisementData(name, uuids);
|
| + [central_manager_delegate centralManager:central_manager
|
| + didDiscoverPeripheral:peripheral
|
| + advertisementData:advertisement_data
|
| + RSSI:0];
|
| + break;
|
| + }
|
| + case 3: {
|
| + CBPeripheral* peripheral = CreateMockPeripheral(
|
| + [NSString stringWithUTF8String:kTestPeripheralUUID1.c_str()]);
|
| + NSString* name =
|
| + [NSString stringWithUTF8String:kTestDeviceNameEmpty.c_str()];
|
| + NSArray* uuids = nil;
|
| + NSDictionary* advertisement_data = CreateAdvertisementData(name, uuids);
|
| + [central_manager_delegate centralManager:central_manager
|
| + didDiscoverPeripheral:peripheral
|
| + advertisementData:advertisement_data
|
| + RSSI:0];
|
| + break;
|
| + }
|
| + case 4: {
|
| + CBPeripheral* peripheral = CreateMockPeripheral(
|
| + [NSString stringWithUTF8String:kTestPeripheralUUID2.c_str()]);
|
| + NSString* name =
|
| + [NSString stringWithUTF8String:kTestDeviceNameEmpty.c_str()];
|
| + NSArray* uuids = nil;
|
| + NSDictionary* advertisement_data = CreateAdvertisementData(name, uuids);
|
| + [central_manager_delegate centralManager:central_manager
|
| + didDiscoverPeripheral:peripheral
|
| + advertisementData:advertisement_data
|
| + RSSI:0];
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Utility function for generating new (CBUUID, address) pairs where CBUUID
|
| +// hashes to address. For use when adding a new device address to the testing
|
| +// suite because CoreBluetooth peripherals have CBUUIDs in place of addresses,
|
| +// and we construct fake addresses for them by hashing the CBUUID. By changing
|
| +// |target| the user can generate sequentially numbered test addresses.
|
| +//
|
| +// std::string BluetoothTestMac::FindCBUUIDForHashTarget() {
|
| +// // The desired first 6 digits of the hash. For example 0100000, 020000,
|
| +// // 030000, ...
|
| +// const std::string target = "010000";
|
| +// // 128 bit buffer to be encoded as a hex string.
|
| +// int64_t input[2] = {0};
|
| +// // There are 2^24 ~ 10^7 possible configurations for the first 6 digits,
|
| +// // ie. each input has probability 10^-7 of succeeding, under the dubious
|
| +// // assumption that traversing inputs sequentially is as good as traversing
|
| +// // them randomly. After 10^8 iterations then the probability of never
|
| +// // succeeding is ((10^7-1)/10^7)^(10^8) ~= 10^-5.
|
| +// while (input[0] < LLONG_MAX) {
|
| +// // Encode as a hexidecimal number. Note that on x86 input[0] is stored
|
| +// // as a little-endian number, and so read backwards by HexEncode.
|
| +// std::string input_str = base::HexEncode(&input, sizeof(input));
|
| +// input_str.insert(20, "-");
|
| +// input_str.insert(16, "-");
|
| +// input_str.insert(12, "-");
|
| +// input_str.insert(8, "-");
|
| +// char raw[3];
|
| +// crypto::SHA256HashString(input_str, raw, sizeof(raw));
|
| +// if (base::HexEncode(raw, sizeof(raw)) == target) {
|
| +// return input_str;
|
| +// }
|
| +// ++input[0];
|
| +// }
|
| +// return "";
|
| +// }
|
| +
|
| } // namespace device
|
|
|