| // Copyright 2016 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 "device/bluetooth/test/mock_bluetooth_cbcharacteristic_mac.h" |
| |
| #include "base/mac/foundation_util.h" |
| #include "base/mac/scoped_nsobject.h" |
| #include "device/bluetooth/bluetooth_gatt_characteristic.h" |
| #include "device/bluetooth/test/mock_bluetooth_cbdescriptor_mac.h" |
| |
| using base::mac::ObjCCast; |
| using base::scoped_nsobject; |
| |
| namespace device { |
| |
| namespace { |
| |
| CBCharacteristicProperties AddCBCharacteristicProperties( |
| CBCharacteristicProperties value1, |
| CBCharacteristicProperties value2) { |
| return static_cast<CBCharacteristicProperties>(value1 | value2); |
| } |
| |
| CBCharacteristicProperties GattCharacteristicPropertyToCBCharacteristicProperty( |
| BluetoothGattCharacteristic::Properties gatt_property) { |
| CBCharacteristicProperties result = |
| static_cast<CBCharacteristicProperties>(0); |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_BROADCAST) { |
| result = AddCBCharacteristicProperties(result, |
| CBCharacteristicPropertyBroadcast); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_READ) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyRead); |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE) { |
| result = AddCBCharacteristicProperties( |
| result, CBCharacteristicPropertyWriteWithoutResponse); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_WRITE) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyWrite); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_NOTIFY) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyNotify); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_INDICATE) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyIndicate); |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_AUTHENTICATED_SIGNED_WRITES) { |
| result = AddCBCharacteristicProperties( |
| result, CBCharacteristicPropertyAuthenticatedSignedWrites); |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES) { |
| result = AddCBCharacteristicProperties( |
| result, CBCharacteristicPropertyExtendedProperties); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_RELIABLE_WRITE) { |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_WRITABLE_AUXILIARIES) { |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_READ_ENCRYPTED) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyRead); |
| } |
| if (gatt_property & BluetoothGattCharacteristic::PROPERTY_WRITE_ENCRYPTED) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyWrite); |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_READ_ENCRYPTED_AUTHENTICATED) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyRead); |
| } |
| if (gatt_property & |
| BluetoothGattCharacteristic::PROPERTY_WRITE_ENCRYPTED_AUTHENTICATED) { |
| result = |
| AddCBCharacteristicProperties(result, CBCharacteristicPropertyWrite); |
| } |
| return result; |
| } |
| } // namespace |
| } // device |
| |
| @interface MockCBCharacteristic () { |
| // Owner of this instance. |
| CBService* _service; |
| scoped_nsobject<CBUUID> _UUID; |
| CBCharacteristicProperties _cb_properties; |
| scoped_nsobject<NSMutableArray> _descriptors; |
| scoped_nsobject<NSObject> _value; |
| BOOL _notifying; |
| } |
| @end |
| |
| @implementation MockCBCharacteristic |
| |
| - (instancetype)initWithService:(CBService*)service |
| CBUUID:(CBUUID*)uuid |
| properties:(int)properties { |
| self = [super init]; |
| if (self) { |
| _service = service; |
| _UUID.reset([uuid retain]); |
| _cb_properties = |
| device::GattCharacteristicPropertyToCBCharacteristicProperty( |
| properties); |
| _descriptors.reset([[NSMutableArray alloc] init]); |
| } |
| return self; |
| } |
| |
| - (BOOL)isKindOfClass:(Class)aClass { |
| if (aClass == [CBCharacteristic class] || |
| [aClass isSubclassOfClass:[CBCharacteristic class]]) { |
| return YES; |
| } |
| return [super isKindOfClass:aClass]; |
| } |
| |
| - (BOOL)isMemberOfClass:(Class)aClass { |
| if (aClass == [CBCharacteristic class] || |
| [aClass isSubclassOfClass:[CBCharacteristic class]]) { |
| return YES; |
| } |
| return [super isKindOfClass:aClass]; |
| } |
| |
| - (void)simulateReadWithValue:(id)value error:(NSError*)error { |
| _value.reset([value copy]); |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateValueForCharacteristic:self.characteristic |
| error:error]; |
| } |
| |
| - (void)simulateWriteWithError:(NSError*)error { |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didWriteValueForCharacteristic:self.characteristic |
| error:error]; |
| } |
| |
| - (void)simulateGattNotifySessionStarted { |
| _notifying = YES; |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateNotificationStateForCharacteristic:self.characteristic |
| error:nil]; |
| } |
| |
| - (void)simulateGattNotifySessionFailedWithError:(NSError*)error { |
| _notifying = NO; |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateNotificationStateForCharacteristic:self.characteristic |
| error:error]; |
| } |
| |
| - (void)simulateGattNotifySessionStopped { |
| _notifying = NO; |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateNotificationStateForCharacteristic:self.characteristic |
| error:nil]; |
| } |
| |
| - (void)simulateGattNotifySessionStoppedWithError:(NSError*)error { |
| _notifying = NO; |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateNotificationStateForCharacteristic:self.characteristic |
| error:error]; |
| } |
| |
| - (void)simulateGattCharacteristicChangedWithValue:(NSData*)value { |
| _value.reset([value copy]); |
| CBPeripheral* peripheral = _service.peripheral; |
| [peripheral.delegate peripheral:peripheral |
| didUpdateValueForCharacteristic:self.characteristic |
| error:nil]; |
| } |
| |
| - (void)addDescriptorWithUUID:(CBUUID*)uuid { |
| scoped_nsobject<MockCBDescriptor> descriptor_mock([[MockCBDescriptor alloc] |
| initWithCharacteristic:self.characteristic |
| CBUUID:uuid]); |
| [_descriptors addObject:descriptor_mock]; |
| } |
| |
| - (CBUUID*)UUID { |
| return _UUID; |
| } |
| |
| - (CBCharacteristic*)characteristic { |
| return ObjCCast<CBCharacteristic>(self); |
| } |
| |
| - (CBService*)service { |
| return _service; |
| } |
| |
| - (CBCharacteristicProperties)properties { |
| return _cb_properties; |
| } |
| |
| - (NSArray*)descriptors { |
| return _descriptors; |
| } |
| |
| - (id)value { |
| return _value; |
| } |
| |
| - (BOOL)isNotifying { |
| return _notifying; |
| } |
| |
| @end |