mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
[NC Apple coverage] Add unit tests for GNCMBleUtils.
PiperOrigin-RevId: 808614106
This commit is contained in:
committed by
Copybara-Service
parent
ae94fa2cdc
commit
8ded7ccfca
@@ -74,7 +74,7 @@ NSData *GNCMGenerateBLEFramesIntroductionPacket(NSData *serviceIDHash);
|
||||
* Parses the packet for Ble SocketControlFrame introduction packet and returns
|
||||
* serviceIdHash if succeed.
|
||||
*/
|
||||
NSData *GNCMParseBLEFramesIntroductionPacket(NSData *data);
|
||||
NSData *_Nullable GNCMParseBLEFramesIntroductionPacket(NSData *_Nullable data);
|
||||
|
||||
/** Creates the disconnection packet for Ble SocketControlFrame. */
|
||||
NSData *GNCMGenerateBLEFramesDisconnectionPacket(NSData *serviceIDHash);
|
||||
@@ -83,7 +83,7 @@ NSData *GNCMGenerateBLEFramesDisconnectionPacket(NSData *serviceIDHash);
|
||||
NSData *GNCMGenerateBLEFramesPacketAcknowledgementPacket(NSData *serviceIDHash, int receivedSize);
|
||||
|
||||
/** Parses the BLE L2CAP packet from the data. */
|
||||
GNCMBLEL2CAPPacket *_Nullable GNCMParseBLEL2CAPPacket(NSData *data);
|
||||
GNCMBLEL2CAPPacket *_Nullable GNCMParseBLEL2CAPPacket(NSData *_Nullable data);
|
||||
|
||||
/** Creates the BLE L2CAP packet from the command and data. */
|
||||
NSData *_Nullable GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommand command, NSData *_Nullable data);
|
||||
|
||||
@@ -63,9 +63,11 @@ NSData *GNCMGenerateBLEFramesIntroductionPacket(NSData *serviceIDHash) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
NSData *_Nullable GNCMParseBLEFramesIntroductionPacket(NSData *data) {
|
||||
NSData *_Nullable GNCMParseBLEFramesIntroductionPacket(NSData *_Nullable data) {
|
||||
if (!data) return nil;
|
||||
::location::nearby::mediums::SocketControlFrame socket_control_frame;
|
||||
NSUInteger prefixLength = sizeof(kGNCMControlPacketServiceIDHash);
|
||||
if (data.length <= prefixLength) return nil;
|
||||
NSData *packet = [data subdataWithRange:NSMakeRange(prefixLength, data.length - prefixLength)];
|
||||
if (socket_control_frame.ParseFromArray(packet.bytes, (int)packet.length)) {
|
||||
if (socket_control_frame.type() ==
|
||||
@@ -132,9 +134,12 @@ NSData *GNCMGenerateBLEFramesPacketAcknowledgementPacket(NSData *serviceIDHash,
|
||||
|
||||
@end
|
||||
|
||||
// TODO: b/399815436 - Add unit tests for this function.
|
||||
GNCMBLEL2CAPPacket *_Nullable GNCMParseBLEL2CAPPacket(NSData *data) {
|
||||
if (data.length < 1) {
|
||||
GNCMBLEL2CAPPacket *_Nullable GNCMParseBLEL2CAPPacket(NSData *_Nullable data) {
|
||||
const NSUInteger kCommandLength = 1;
|
||||
const NSUInteger kLengthFieldLength = 2;
|
||||
const NSUInteger kHeaderLength = kCommandLength + kLengthFieldLength;
|
||||
|
||||
if (!data || data.length < kCommandLength) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -148,26 +153,29 @@ GNCMBLEL2CAPPacket *_Nullable GNCMParseBLEL2CAPPacket(NSData *data) {
|
||||
|
||||
// Extract data
|
||||
NSData *packetData = nil;
|
||||
if (receivedDataLength > 3) {
|
||||
if (receivedDataLength > kHeaderLength) {
|
||||
// Extract data length (2 bytes, big endian)
|
||||
int dataLength = (bytes[1] << 8) | bytes[2];
|
||||
|
||||
// Validate data length
|
||||
if (dataLength != (int)(receivedDataLength - 3)) {
|
||||
if (dataLength != (int)(receivedDataLength - kHeaderLength)) {
|
||||
GNCLoggerError(@"[NEARBY] Data length mismatch. Expected: %d, Actual: %lu", dataLength,
|
||||
receivedDataLength - 3);
|
||||
receivedDataLength - kHeaderLength);
|
||||
return nil;
|
||||
}
|
||||
if (dataLength > 0) {
|
||||
packetData = [NSData dataWithBytes:&bytes[3] length:dataLength];
|
||||
packetData = [NSData dataWithBytes:&bytes[kHeaderLength] length:dataLength];
|
||||
} else {
|
||||
packetData = nil;
|
||||
}
|
||||
} else if (receivedDataLength > kCommandLength) {
|
||||
// Header is incomplete
|
||||
GNCLoggerError(@"[NEARBY] Incomplete L2CAP packet header.");
|
||||
return nil;
|
||||
}
|
||||
return [[GNCMBLEL2CAPPacket alloc] initWithCommand:command data:packetData];
|
||||
}
|
||||
|
||||
// TODO: b/399815436 - Add unit tests for this function.
|
||||
NSData *_Nullable GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommand command, NSData *_Nullable data) {
|
||||
if (!IsSupportedCommand(command)) {
|
||||
GNCLoggerError(@"[NEARBY] Invalid command to generate packet: %lu", command);
|
||||
|
||||
@@ -33,10 +33,11 @@ objc_library(
|
||||
"GNCBLEL2CAPServerTest.m",
|
||||
"GNCBLEL2CAPStreamTest.m",
|
||||
"GNCBLEMediumTest.m",
|
||||
"GNCBLEUtilsTest.mm",
|
||||
"GNCFakeCentralManager.m",
|
||||
"GNCFakePeripheral.m",
|
||||
"GNCFakePeripheralManager.m",
|
||||
"GNCFakeSocket.m",
|
||||
"GNCMBleUtilsTest.m",
|
||||
"GNCMFakeConnection.mm",
|
||||
"NSData+GNCBase85Test.m",
|
||||
"NSData+GNCWebSafeBase64Test.m",
|
||||
@@ -50,6 +51,7 @@ objc_library(
|
||||
"GNCFakeCentralManager.h",
|
||||
"GNCFakePeripheral.h",
|
||||
"GNCFakePeripheralManager.h",
|
||||
"GNCFakeSocket.h",
|
||||
"GNCMFakeConnection.h",
|
||||
],
|
||||
deps = [
|
||||
@@ -58,9 +60,11 @@ objc_library(
|
||||
"//internal/platform/implementation/apple", # buildcleaner: keep
|
||||
"//internal/platform/implementation/apple:ble_v2",
|
||||
"//internal/platform/implementation/apple/Mediums/BLE",
|
||||
"//internal/platform/implementation/apple/Mediums/BLE/Sockets:Shared",
|
||||
"//third_party/apple_frameworks:CoreBluetooth",
|
||||
"//third_party/apple_frameworks:Foundation",
|
||||
"//third_party/apple_frameworks:XCTest",
|
||||
"//third_party/objective_c/ocmock/v3:OCMock",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCBLEGATTCharacteristic.h"
|
||||
#import "internal/platform/implementation/apple/ble_utils.h"
|
||||
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
|
||||
using GattCharacteristic = ::nearby::api::ble_v2::GattCharacteristic;
|
||||
using Property = ::nearby::api::ble_v2::GattCharacteristic::Property;
|
||||
using Permission = ::nearby::api::ble_v2::GattCharacteristic::Permission;
|
||||
using WriteType = ::nearby::api::ble_v2::GattClient::WriteType;
|
||||
using Uuid = ::nearby::Uuid;
|
||||
using ByteArray = ::nearby::ByteArray;
|
||||
|
||||
@interface GNCBLEUtilsTest : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GNCBLEUtilsTest
|
||||
|
||||
#pragma mark - C++ to Objective-C
|
||||
|
||||
- (void)testCBUUID16FromCPP {
|
||||
CBUUID *expected = [CBUUID UUIDWithString:@"FEF3"];
|
||||
CBUUID *actual = ::nearby::apple::CBUUID16FromCPP(Uuid(0x0000FEF300001000, 0x800000805F9B34FB));
|
||||
XCTAssertEqualObjects(actual.UUIDString, expected.UUIDString);
|
||||
}
|
||||
|
||||
- (void)testCBUUID128FromCPP {
|
||||
CBUUID *expected = [CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"];
|
||||
CBUUID *actual = ::nearby::apple::CBUUID128FromCPP(Uuid(0x0000FEF300001000, 0x800000805F9B34FB));
|
||||
XCTAssertEqualObjects(actual.UUIDString, expected.UUIDString);
|
||||
}
|
||||
|
||||
- (void)testCBCharacteristicWriteTypeFromCPPWithResponse {
|
||||
CBCharacteristicWriteType expected = CBCharacteristicWriteWithResponse;
|
||||
CBCharacteristicWriteType actual =
|
||||
::nearby::apple::CBCharacteristicWriteTypeFromCPP(WriteType::kWithResponse);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBCharacteristicWriteTypeFromCPPWithoutResponse {
|
||||
CBCharacteristicWriteType expected = CBCharacteristicWriteWithoutResponse;
|
||||
CBCharacteristicWriteType actual =
|
||||
::nearby::apple::CBCharacteristicWriteTypeFromCPP(WriteType::kWithoutResponse);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBCharacteristicPropertiesFromCPPEmptyProperty {
|
||||
CBCharacteristicProperties expected = 0;
|
||||
CBCharacteristicProperties actual =
|
||||
::nearby::apple::CBCharacteristicPropertiesFromCPP(Property::kNone);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBCharacteristicPropertiesFromCPPSingleProperty {
|
||||
CBCharacteristicProperties expected = CBCharacteristicPropertyRead;
|
||||
CBCharacteristicProperties actual =
|
||||
::nearby::apple::CBCharacteristicPropertiesFromCPP(Property::kRead);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBCharacteristicPropertiesFromCPPMultipleProperties {
|
||||
CBCharacteristicProperties expected = CBCharacteristicPropertyWrite |
|
||||
CBCharacteristicPropertyNotify |
|
||||
CBCharacteristicPropertyIndicate;
|
||||
CBCharacteristicProperties actual = ::nearby::apple::CBCharacteristicPropertiesFromCPP(
|
||||
Property::kWrite | Property::kNotify | Property::kIndicate);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBAttributePermissionsFromCPPEmptyPermission {
|
||||
CBAttributePermissions expected = 0;
|
||||
CBAttributePermissions actual = ::nearby::apple::CBAttributePermissionsFromCPP(Permission::kNone);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBAttributePermissionsFromCPPSinglePermission {
|
||||
CBAttributePermissions expected = CBAttributePermissionsReadable;
|
||||
CBAttributePermissions actual =
|
||||
::nearby::apple::CBAttributePermissionsFromCPP(Permission::kRead);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCBAttributePermissionsFromCPPMultiplePermissions {
|
||||
CBAttributePermissions expected =
|
||||
CBAttributePermissionsReadable | CBAttributePermissionsWriteable;
|
||||
CBAttributePermissions actual =
|
||||
::nearby::apple::CBAttributePermissionsFromCPP(Permission::kRead | Permission::kWrite);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testObjCGATTCharacteristicFromCPP {
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:@"00000000-0000-3000-8000-000000000000"];
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"];
|
||||
CBAttributePermissions permissions = CBAttributePermissionsReadable;
|
||||
CBCharacteristicProperties properties = CBCharacteristicPropertyRead;
|
||||
|
||||
GattCharacteristic characteristic = {Uuid(0x0000000000003000, 0x8000000000000000),
|
||||
Uuid(0x0000FEF300001000, 0x800000805F9B34FB),
|
||||
Permission::kRead, Property::kRead};
|
||||
|
||||
GNCBLEGATTCharacteristic *actual = ::nearby::apple::ObjCGATTCharacteristicFromCPP(characteristic);
|
||||
XCTAssertEqualObjects(actual.characteristicUUID, characteristicUUID);
|
||||
XCTAssertEqualObjects(actual.serviceUUID, serviceUUID);
|
||||
XCTAssertEqual(actual.permissions, permissions);
|
||||
XCTAssertEqual(actual.properties, properties);
|
||||
}
|
||||
|
||||
- (void)testObjCServiceDataFromCpp {
|
||||
CBUUID *serviceUUID1 = [CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"];
|
||||
CBUUID *serviceUUID2 = [CBUUID UUIDWithString:@"0000FEF4-0000-1000-8000-00805F9B34FB"];
|
||||
NSData *data1 = [@"one" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *data2 = [@"two" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
absl::flat_hash_map<Uuid, ByteArray> service_data;
|
||||
service_data[Uuid(0x0000FEF300001000, 0x800000805F9B34FB)] = ByteArray("one");
|
||||
service_data[Uuid(0x0000FEF400001000, 0x800000805F9B34FB)] = ByteArray("two");
|
||||
|
||||
NSMutableDictionary<CBUUID *, NSData *> *actual =
|
||||
::nearby::apple::ObjCServiceDataFromCPP(service_data);
|
||||
XCTAssertEqualObjects(actual[serviceUUID1], data1);
|
||||
XCTAssertEqualObjects(actual[serviceUUID2], data2);
|
||||
}
|
||||
|
||||
#pragma mark - Objective-C to C++
|
||||
|
||||
- (void)testCPPUUIDFromObjC16Bit {
|
||||
Uuid expected = Uuid(0x0000FEF300001000, 0x800000805F9B34FB);
|
||||
Uuid actual = ::nearby::apple::CPPUUIDFromObjC([CBUUID UUIDWithString:@"FEF3"]);
|
||||
XCTAssertEqualObjects(@(std::string(actual).c_str()), @(std::string(expected).c_str()));
|
||||
}
|
||||
|
||||
- (void)testCPPUUIDFromObjC128Bit {
|
||||
Uuid expected = Uuid(0x0000FEF300001000, 0x800000805F9B34FB);
|
||||
Uuid actual = ::nearby::apple::CPPUUIDFromObjC(
|
||||
[CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"]);
|
||||
XCTAssertEqualObjects(@(std::string(actual).c_str()), @(std::string(expected).c_str()));
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPropertyFromObjCEmptyProperty {
|
||||
Property expected = Property::kNone;
|
||||
Property actual = ::nearby::apple::CPPGATTCharacteristicPropertyFromObjC(0);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPropertyFromObjCSingleProperty {
|
||||
Property expected = Property::kRead;
|
||||
Property actual =
|
||||
::nearby::apple::CPPGATTCharacteristicPropertyFromObjC(CBCharacteristicPropertyRead);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPropertyFromObjCMultipleProperties {
|
||||
Property expected = Property::kWrite | Property::kNotify | Property::kIndicate;
|
||||
Property actual = ::nearby::apple::CPPGATTCharacteristicPropertyFromObjC(
|
||||
CBCharacteristicPropertyWrite | CBCharacteristicPropertyNotify |
|
||||
CBCharacteristicPropertyIndicate);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPermissionFromObjCEmptyPermission {
|
||||
Permission expected = Permission::kNone;
|
||||
Permission actual = ::nearby::apple::CPPGATTCharacteristicPermissionFromObjC(0);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPermissionFromObjCSinglePermission {
|
||||
Permission expected = Permission::kRead;
|
||||
Permission actual =
|
||||
::nearby::apple::CPPGATTCharacteristicPermissionFromObjC(CBAttributePermissionsReadable);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicPermissionFromObjCMultiplePermissions {
|
||||
Permission expected = Permission::kRead | Permission::kWrite;
|
||||
Permission actual = ::nearby::apple::CPPGATTCharacteristicPermissionFromObjC(
|
||||
CBAttributePermissionsReadable | CBAttributePermissionsWriteable);
|
||||
XCTAssertEqual(actual, expected);
|
||||
}
|
||||
|
||||
- (void)testCPPGATTCharacteristicFromObjC {
|
||||
CBUUID *characteristicUUID = [CBUUID UUIDWithString:@"00000000-0000-3000-8000-000000000000"];
|
||||
CBUUID *serviceUUID = [CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"];
|
||||
CBAttributePermissions permissions = CBAttributePermissionsReadable;
|
||||
CBCharacteristicProperties properties = CBCharacteristicPropertyRead;
|
||||
|
||||
GNCBLEGATTCharacteristic *characteristic =
|
||||
[[GNCBLEGATTCharacteristic alloc] initWithUUID:characteristicUUID
|
||||
serviceUUID:serviceUUID
|
||||
permissions:permissions
|
||||
properties:properties];
|
||||
|
||||
GattCharacteristic actual = ::nearby::apple::CPPGATTCharacteristicFromObjC(characteristic);
|
||||
XCTAssertEqual(actual.uuid, Uuid(0x0000000000003000, 0x8000000000000000));
|
||||
XCTAssertEqual(actual.service_uuid, Uuid(0x0000FEF300001000, 0x800000805F9B34FB));
|
||||
XCTAssertEqual(actual.permission, Permission::kRead);
|
||||
XCTAssertEqual(actual.property, Property::kRead);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Sockets/Source/Shared/GNSSocket.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/** A fake implementation of @c GNSSocket to inject for testing. */
|
||||
@interface GNCFakeSocket : NSObject
|
||||
|
||||
/** The socket's delegate. */
|
||||
@property(nonatomic, weak) id<GNSSocketDelegate> delegate;
|
||||
|
||||
/** Simulates a socket connection event. */
|
||||
- (void)simulateSocketDidConnect;
|
||||
|
||||
/** Simulates a socket disconnection event. */
|
||||
- (void)simulateSocketDidDisconnectWithError:(nullable NSError *)error;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCFakeSocket.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation GNCFakeSocket
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
- (void)simulateSocketDidConnect {
|
||||
[self.delegate socketDidConnect:(GNSSocket *)self];
|
||||
}
|
||||
|
||||
- (void)simulateSocketDidDisconnectWithError:(nullable NSError *)error {
|
||||
[self.delegate socket:(GNSSocket *)self didDisconnectWithError:error];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,175 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCMBleUtils.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCFakeSocket.h"
|
||||
|
||||
static const NSTimeInterval kTimeout = 1.0;
|
||||
static const NSTimeInterval kWaitForConnectionTimeout = 6.0; // Allow for the 5s internal timeout
|
||||
|
||||
@interface GNCMBleUtilsTest : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GNCMBleUtilsTest
|
||||
|
||||
- (void)testServiceIDHash {
|
||||
NSString *serviceID = @"TestServiceID";
|
||||
NSData *hash = GNCMServiceIDHash(serviceID);
|
||||
XCTAssertNotNil(hash);
|
||||
XCTAssertEqual(hash.length, GNCMBleAdvertisementLengthServiceIDHash);
|
||||
// Check for consistency
|
||||
NSData *hash2 = GNCMServiceIDHash(serviceID);
|
||||
XCTAssertEqualObjects(hash, hash2);
|
||||
}
|
||||
|
||||
- (void)testGenerateAndParseBLEFramesIntroductionPacket {
|
||||
NSData *serviceIDHash = [@"123" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *packet = GNCMGenerateBLEFramesIntroductionPacket(serviceIDHash);
|
||||
XCTAssertNotNil(packet);
|
||||
|
||||
NSData *parsedHash = GNCMParseBLEFramesIntroductionPacket(packet);
|
||||
XCTAssertEqualObjects(parsedHash, serviceIDHash);
|
||||
}
|
||||
|
||||
- (void)testParseBLEFramesIntroductionPacketFailure_NilData {
|
||||
NSData *parsedHash = GNCMParseBLEFramesIntroductionPacket(nil);
|
||||
XCTAssertNil(parsedHash);
|
||||
}
|
||||
|
||||
- (void)testParseBLEFramesIntroductionPacketFailure_ShortData {
|
||||
NSData *invalidPacket = [@"12" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *parsedHash = GNCMParseBLEFramesIntroductionPacket(invalidPacket);
|
||||
XCTAssertNil(parsedHash);
|
||||
}
|
||||
|
||||
- (void)testGenerateBLEFramesDisconnectionPacket {
|
||||
NSData *serviceIDHash = [@"ABC" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *packet = GNCMGenerateBLEFramesDisconnectionPacket(serviceIDHash);
|
||||
XCTAssertNotNil(packet);
|
||||
XCTAssertTrue(packet.length > serviceIDHash.length);
|
||||
}
|
||||
|
||||
- (void)testGenerateBLEFramesPacketAcknowledgementPacket {
|
||||
NSData *serviceIDHash = [@"DEF" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
int receivedSize = 1024;
|
||||
NSData *packet = GNCMGenerateBLEFramesPacketAcknowledgementPacket(serviceIDHash, receivedSize);
|
||||
XCTAssertNotNil(packet);
|
||||
XCTAssertTrue(packet.length > serviceIDHash.length);
|
||||
}
|
||||
|
||||
- (void)testGenerateAndParseBLEL2CAPPacketWithData {
|
||||
GNCMBLEL2CAPCommand command = GNCMBLEL2CAPCommandRequestAdvertisement;
|
||||
NSData *data = [@"test_data" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *packetData = GNCMGenerateBLEL2CAPPacket(command, data);
|
||||
XCTAssertNotNil(packetData);
|
||||
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(packetData);
|
||||
XCTAssertNotNil(packet);
|
||||
XCTAssertEqual(packet.command, command);
|
||||
XCTAssertEqualObjects(packet.data, data);
|
||||
}
|
||||
|
||||
- (void)testGenerateAndParseBLEL2CAPPacketWithoutData {
|
||||
GNCMBLEL2CAPCommand command = GNCMBLEL2CAPCommandRequestAdvertisementFinish;
|
||||
NSData *packetData = GNCMGenerateBLEL2CAPPacket(command, nil);
|
||||
XCTAssertNotNil(packetData);
|
||||
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(packetData);
|
||||
XCTAssertNotNil(packet);
|
||||
XCTAssertEqual(packet.command, command);
|
||||
XCTAssertNil(packet.data);
|
||||
}
|
||||
|
||||
- (void)testParseBLEL2CAPPacketInvalidData_Nil {
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(nil);
|
||||
XCTAssertNil(packet);
|
||||
}
|
||||
|
||||
- (void)testParseBLEL2CAPPacketInvalidData_Empty {
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket([[NSData alloc] init]);
|
||||
XCTAssertNil(packet);
|
||||
}
|
||||
|
||||
- (void)testParseBLEL2CAPPacketShortData_NoLength {
|
||||
uint8_t commandByte = (uint8_t)GNCMBLEL2CAPCommandRequestAdvertisement;
|
||||
NSData *shortPacketData = [NSData dataWithBytes:&commandByte length:1];
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(shortPacketData);
|
||||
XCTAssertNotNil(packet);
|
||||
XCTAssertEqual(packet.command, GNCMBLEL2CAPCommandRequestAdvertisement);
|
||||
XCTAssertNil(packet.data);
|
||||
}
|
||||
|
||||
- (void)testParseBLEL2CAPPacketShortData_IncompleteLength {
|
||||
uint8_t bytes[] = {GNCMBLEL2CAPCommandRequestAdvertisement, 0x01};
|
||||
NSData *shortPacketData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(shortPacketData);
|
||||
XCTAssertNil(packet);
|
||||
}
|
||||
|
||||
- (void)testParseBLEL2CAPPacketShortData_IncompleteData {
|
||||
uint8_t bytes[] = {GNCMBLEL2CAPCommandRequestAdvertisement, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04};
|
||||
NSData *shortPacketData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
|
||||
GNCMBLEL2CAPPacket *packet = GNCMParseBLEL2CAPPacket(shortPacketData);
|
||||
XCTAssertNil(packet);
|
||||
}
|
||||
|
||||
- (void)testWaitForConnection_Success {
|
||||
GNCFakeSocket *fakeSocket = [[GNCFakeSocket alloc] init];
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Connection success"];
|
||||
GNCMWaitForConnection((GNSSocket *)fakeSocket, ^(BOOL flag) {
|
||||
XCTAssertTrue(flag);
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
||||
// Simulate the connection callback
|
||||
[fakeSocket simulateSocketDidConnect];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTimeout handler:nil];
|
||||
}
|
||||
|
||||
- (void)testWaitForConnection_Failure_Disconnect {
|
||||
GNCFakeSocket *fakeSocket = [[GNCFakeSocket alloc] init];
|
||||
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"Connection failed on disconnect"];
|
||||
GNCMWaitForConnection((GNSSocket *)fakeSocket, ^(BOOL flag) {
|
||||
XCTAssertFalse(flag);
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
||||
// Simulate the disconnection callback
|
||||
[fakeSocket simulateSocketDidDisconnectWithError:nil];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTimeout handler:nil];
|
||||
}
|
||||
|
||||
- (void)testWaitForConnection_Failure_Timeout {
|
||||
GNCFakeSocket *fakeSocket = [[GNCFakeSocket alloc] init];
|
||||
// No delegate call - let it time out
|
||||
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"Connection failed on timeout"];
|
||||
GNCMWaitForConnection((GNSSocket *)fakeSocket, ^(BOOL flag) {
|
||||
XCTAssertFalse(flag);
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
||||
[self waitForExpectationsWithTimeout:kWaitForConnectionTimeout handler:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user