mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
[NC Apple coverage]Add more comprehensive tests for BLE L2CAP components.
PiperOrigin-RevId: 821886071
This commit is contained in:
committed by
Copybara-Service
parent
ed2d8ab7c3
commit
3878ce99c8
@@ -35,6 +35,7 @@ objc_library(
|
||||
"GNCBLEMediumTest.m",
|
||||
"GNCFakeBLEGATTServer.m",
|
||||
"GNCFakeBLEMedium.m",
|
||||
"GNCFakeCBL2CAPChannel.m",
|
||||
"GNCFakeCentralManager.m",
|
||||
"GNCFakePeripheral.m",
|
||||
"GNCFakePeripheralManager.m",
|
||||
@@ -53,9 +54,11 @@ objc_library(
|
||||
"GNCBLEGATTServer+Testing.h",
|
||||
"GNCBLEL2CAPClient+Testing.h",
|
||||
"GNCBLEL2CAPFakeInputOutputStream.h",
|
||||
"GNCBLEL2CAPServer+Testing.h",
|
||||
"GNCBLEMedium+Testing.h",
|
||||
"GNCFakeBLEGATTServer.h",
|
||||
"GNCFakeBLEMedium.h",
|
||||
"GNCFakeCBL2CAPChannel.h",
|
||||
"GNCFakeCentralManager.h",
|
||||
"GNCFakePeripheral.h",
|
||||
"GNCFakePeripheralManager.h",
|
||||
|
||||
+12
-3
@@ -16,11 +16,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCPeripheral.h"
|
||||
|
||||
@protocol GNCPeripheral;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GNCBLEL2CAPClient (Testing)
|
||||
@interface GNCBLEL2CAPClient (Testing) <GNCPeripheralDelegate>
|
||||
|
||||
/**
|
||||
* Initializes the L2CAP client with a provided queue and request disconnection handler.
|
||||
@@ -32,8 +34,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* @param requestDisconnectionHandler Called on a private queue with @c peripheral when the
|
||||
* connection to the peripheral should be cancelled.
|
||||
*/
|
||||
-(instancetype)initWithQueue:(nullable dispatch_queue_t)queue
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
|
||||
- (instancetype)initWithQueue:(nullable dispatch_queue_t)queue
|
||||
requestDisconnectionHandler:(GNCRequestDisconnectionHandler)requestDisconnectionHandler;
|
||||
|
||||
/**
|
||||
* Closes the L2CAP channel and disconnects the peripheral.
|
||||
*
|
||||
* This is only exposed for testing.
|
||||
*/
|
||||
- (void)closeL2CAPChannel;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCPeripheral.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCBLEL2CAPClient+Testing.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCBLEL2CAPFakeInputOutputStream.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCFakePeripheral.h"
|
||||
|
||||
static const NSTimeInterval kTestTimeout = 1.0;
|
||||
|
||||
@interface GNCBLEL2CAPClientTest : XCTestCase
|
||||
@property(nonatomic) GNCFakePeripheral *fakePeripheral;
|
||||
@property(nonatomic) GNCBLEL2CAPClient *l2capClient;
|
||||
@@ -58,10 +61,11 @@
|
||||
peripheral:self.fakePeripheral
|
||||
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error) {
|
||||
XCTAssertNil(error, @"Error should be nil");
|
||||
XCTAssertNil(stream, @"Stream should be nil due to testing limitation");
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testOpenL2CAPChannelWithError {
|
||||
@@ -79,7 +83,7 @@
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testDisconnect {
|
||||
@@ -94,7 +98,96 @@
|
||||
|
||||
[self.l2capClient disconnect];
|
||||
|
||||
[self waitForExpectations:@[ self.requestDisconnectionHandlerExpectation ] timeout:1.0];
|
||||
[self waitForExpectations:@[ self.requestDisconnectionHandlerExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testOpenL2CAPChannelSetsPeripheralDelegate {
|
||||
uint16_t psm = 123;
|
||||
|
||||
[self.l2capClient openL2CAPChannelWithPSM:psm
|
||||
peripheral:self.fakePeripheral
|
||||
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error){
|
||||
}];
|
||||
|
||||
XCTAssertEqualObjects(self.fakePeripheral.peripheralDelegate, self.l2capClient);
|
||||
}
|
||||
|
||||
- (void)testInitWithRequestDisconnectionHandlerAndDisconnect {
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"Disconnection handler called"];
|
||||
GNCBLEL2CAPClient *client = [[GNCBLEL2CAPClient alloc]
|
||||
initWithRequestDisconnectionHandler:^(id<GNCPeripheral> _Nullable peripheral) {
|
||||
XCTAssertNil(peripheral);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[client disconnect];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testCloseL2CAPChannel {
|
||||
self.requestDisconnectionHandlerExpectation =
|
||||
[self expectationWithDescription:@"Request disconnection handler should be called"];
|
||||
uint16_t psm = 123;
|
||||
|
||||
[self.l2capClient openL2CAPChannelWithPSM:psm
|
||||
peripheral:self.fakePeripheral
|
||||
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error){
|
||||
}];
|
||||
|
||||
[self.l2capClient closeL2CAPChannel];
|
||||
|
||||
[self waitForExpectations:@[ self.requestDisconnectionHandlerExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testDidOpenL2CAPChannelWithStreams {
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"L2CAP channel opened successfully"];
|
||||
uint16_t psm = 123;
|
||||
GNCBLEL2CAPFakeInputOutputStream *fakeStreams =
|
||||
[[GNCBLEL2CAPFakeInputOutputStream alloc] initWithBufferSize:1];
|
||||
self.fakePeripheral.channelInputStream = fakeStreams.inputStream;
|
||||
self.fakePeripheral.channelOutputStream = fakeStreams.outputStream;
|
||||
|
||||
[self.l2capClient openL2CAPChannelWithPSM:psm
|
||||
peripheral:self.fakePeripheral
|
||||
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(stream);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testDidOpenL2CAPChannelCalledTwice {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"L2CAP channel opened twice"];
|
||||
expectation.expectedFulfillmentCount = 2;
|
||||
self.requestDisconnectionHandlerExpectation =
|
||||
[self expectationWithDescription:@"Request disconnection handler should be called"];
|
||||
uint16_t psm = 123;
|
||||
GNCBLEL2CAPFakeInputOutputStream *fakeStreams =
|
||||
[[GNCBLEL2CAPFakeInputOutputStream alloc] initWithBufferSize:1];
|
||||
self.fakePeripheral.channelInputStream = fakeStreams.inputStream;
|
||||
self.fakePeripheral.channelOutputStream = fakeStreams.outputStream;
|
||||
|
||||
[self.l2capClient openL2CAPChannelWithPSM:psm
|
||||
peripheral:self.fakePeripheral
|
||||
completionHandler:^(GNCBLEL2CAPStream *stream, NSError *error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(stream);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
// Calling gnc_peripheral again to simulate channel opened again.
|
||||
CBL2CAPChannel *channel = [[CBL2CAPChannel alloc] init];
|
||||
[channel setValue:fakeStreams.inputStream forKey:@"inputStream"];
|
||||
[channel setValue:fakeStreams.outputStream forKey:@"outputStream"];
|
||||
[self.l2capClient peripheral:(CBPeripheral *)self.fakePeripheral
|
||||
didOpenL2CAPChannel:channel
|
||||
error:nil];
|
||||
|
||||
[self waitForExpectations:@[ expectation, self.requestDisconnectionHandlerExpectation ]
|
||||
timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+179
-18
@@ -18,10 +18,13 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCBLEL2CAPStream.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCMBleUtils.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCMConnection.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCBLEL2CAPFakeInputOutputStream.h"
|
||||
|
||||
// TODO: b/399815436 - More tests for GNCBLEL2CAPConnection.
|
||||
@interface GNCBLEL2CAPConnection (Testing)
|
||||
static const NSTimeInterval kTestTimeout = 1.0;
|
||||
|
||||
@interface GNCBLEL2CAPConnection (Testing) <GNCBLEL2CAPStreamDelegate>
|
||||
- (NSData *_Nullable)extractRealDataFromData:(NSData *)data;
|
||||
@property(nonatomic) NSUInteger expectedDataLength;
|
||||
@property(nonatomic) dispatch_queue_t selfQueue;
|
||||
@@ -33,13 +36,14 @@
|
||||
@property(nonatomic) GNCBLEL2CAPConnection *connection;
|
||||
@property(nonatomic) dispatch_queue_t testCallbackQueue;
|
||||
@property(nonatomic) NSString *serviceID;
|
||||
@property(nonatomic) NSData *serviceIDHash;
|
||||
@end
|
||||
|
||||
@implementation GNCBLEL2CAPConnectionTest
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
_fakeInputOutputStream = [[GNCBLEL2CAPFakeInputOutputStream alloc] initWithBufferSize:100];
|
||||
_fakeInputOutputStream = [[GNCBLEL2CAPFakeInputOutputStream alloc] initWithBufferSize:1024];
|
||||
_stream = [[GNCBLEL2CAPStream alloc]
|
||||
initWithClosedBlock:^{
|
||||
}
|
||||
@@ -47,6 +51,7 @@
|
||||
outputStream:_fakeInputOutputStream.outputStream];
|
||||
_testCallbackQueue = dispatch_queue_create("com.google.test.callback", DISPATCH_QUEUE_SERIAL);
|
||||
_serviceID = @"testServiceID";
|
||||
_serviceIDHash = GNCMServiceIDHash(_serviceID);
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
@@ -71,10 +76,11 @@
|
||||
return connection;
|
||||
}
|
||||
|
||||
- (NSData *)createDataWithLength:(NSUInteger)length prefix:(NSData *)prefix {
|
||||
NSMutableData *data = [NSMutableData dataWithLength:length];
|
||||
if (prefix) {
|
||||
[data appendData:prefix];
|
||||
- (NSData *)createDataWithLength:(NSUInteger)length {
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
for (NSUInteger i = 0; i < length; ++i) {
|
||||
uint8_t byte = i % 256;
|
||||
[data appendBytes:&byte length:1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -90,45 +96,200 @@
|
||||
return packet;
|
||||
}
|
||||
|
||||
- (NSData *)prefixDataWithServiceIDHash:(NSData *)serviceIDHash data:(NSData *)data {
|
||||
NSMutableData *combinedData = [NSMutableData dataWithCapacity:serviceIDHash.length + data.length];
|
||||
[combinedData appendData:serviceIDHash];
|
||||
[combinedData appendData:data];
|
||||
return combinedData;
|
||||
}
|
||||
|
||||
- (void)waitForCallbackQueue {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Wait for callback queue"];
|
||||
dispatch_async(_testCallbackQueue, ^{
|
||||
[expectation fulfill];
|
||||
});
|
||||
[self waitForExpectations:@[ expectation ] timeout:1];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)waitForSelfQueueWithConnection:(GNCBLEL2CAPConnection *)connection {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Wait for self queue"];
|
||||
dispatch_async(connection.selfQueue, ^{
|
||||
[expectation fulfill];
|
||||
});
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
#pragma mark - Tests
|
||||
|
||||
- (void)testExtractRealDataFromData_validData {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
NSData *testData = [self createDataWithLength:10 prefix:nil];
|
||||
NSData *prefixData = [self prefixLengthData:[self createDataWithLength:testData.length
|
||||
prefix:nil]];
|
||||
_connection.expectedDataLength = testData.length;
|
||||
NSData *realData = [_connection extractRealDataFromData:prefixData];
|
||||
NSData *testData = [self createDataWithLength:10];
|
||||
NSData *prefixData = [self prefixLengthData:testData];
|
||||
NSMutableData *streamData = [NSMutableData dataWithData:prefixData];
|
||||
[streamData appendData:[self createDataWithLength:5]];
|
||||
_connection.expectedDataLength = 0;
|
||||
NSData *realData = [_connection extractRealDataFromData:streamData];
|
||||
XCTAssertEqualObjects(realData, testData);
|
||||
XCTAssertEqual(_connection.expectedDataLength, testData.length);
|
||||
}
|
||||
|
||||
- (void)testExtractRealDataFromData_notEnoughData {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
NSData *prefixData = [self createDataWithLength:2 prefix:nil];
|
||||
NSData *prefixData = [self createDataWithLength:2];
|
||||
NSData *realData = [_connection extractRealDataFromData:prefixData];
|
||||
XCTAssertNil(realData);
|
||||
}
|
||||
|
||||
- (void)testExtractRealDataFromData_moreThanExpectedData {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
NSData *testData = [self createDataWithLength:10 prefix:nil];
|
||||
NSData *moreData = [self createDataWithLength:5 prefix:nil];
|
||||
NSData *testData = [self createDataWithLength:10];
|
||||
NSData *moreData = [self createDataWithLength:5];
|
||||
NSMutableData *combinedData = [NSMutableData dataWithData:testData];
|
||||
[combinedData appendData:moreData];
|
||||
NSData *prefixData = [self prefixLengthData:[self createDataWithLength:combinedData.length
|
||||
prefix:nil]];
|
||||
NSData *prefixData = [self prefixLengthData:combinedData];
|
||||
_connection.expectedDataLength = testData.length;
|
||||
NSData *receivedData = [NSMutableData dataWithData:prefixData];
|
||||
NSData *realData = [_connection extractRealDataFromData:receivedData];
|
||||
XCTAssertEqualObjects(realData, testData);
|
||||
}
|
||||
|
||||
- (void)testSendData {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
NSData *payload = [@"test data" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"send data completion"];
|
||||
|
||||
[_connection sendData:payload
|
||||
completion:^(BOOL result) {
|
||||
XCTAssertTrue(result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTestTimeout handler:nil];
|
||||
|
||||
NSData *expectedPacket = [self prefixLengthData:[self prefixDataWithServiceIDHash:_serviceIDHash
|
||||
data:payload]];
|
||||
NSData *writtenData = [_fakeInputOutputStream dataSentToWatchWithMaxBytes:expectedPacket.length];
|
||||
XCTAssertEqualObjects(writtenData, expectedPacket);
|
||||
}
|
||||
|
||||
- (void)testRequestDataConnectionSuccess {
|
||||
_connection = [self createConnectionWithIncoming:NO];
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"request data connection completion"];
|
||||
__block BOOL success = NO;
|
||||
[_connection requestDataConnectionWithCompletion:^(BOOL result) {
|
||||
success = result;
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
// Verify RequestDataConnection packet is sent.
|
||||
NSData *requestPacket = [self
|
||||
prefixLengthData:GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommandRequestDataConnection, nil)];
|
||||
NSData *writtenReqData =
|
||||
[_fakeInputOutputStream dataSentToWatchWithMaxBytes:requestPacket.length];
|
||||
XCTAssertEqualObjects(writtenReqData, requestPacket);
|
||||
|
||||
// Simulate receiving ResponseDataConnectionReady packet.
|
||||
NSData *responsePacket =
|
||||
[self prefixLengthData:GNCMGenerateBLEL2CAPPacket(
|
||||
GNCMBLEL2CAPCommandResponseDataConnectionReady, nil)];
|
||||
[_fakeInputOutputStream writeFromDevice:responsePacket];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTestTimeout handler:nil];
|
||||
XCTAssertTrue(success);
|
||||
|
||||
// Verify Introduction packet is sent.
|
||||
NSData *introPacket =
|
||||
[self prefixLengthData:GNCMGenerateBLEFramesIntroductionPacket(_serviceIDHash)];
|
||||
NSData *writtenIntroData =
|
||||
[_fakeInputOutputStream dataSentToWatchWithMaxBytes:introPacket.length];
|
||||
XCTAssertEqualObjects(writtenIntroData, introPacket);
|
||||
}
|
||||
|
||||
- (void)testRequestDataConnectionTimeout {
|
||||
_connection = [self createConnectionWithIncoming:NO];
|
||||
XCTestExpectation *expectation =
|
||||
[self expectationWithDescription:@"request data connection completion"];
|
||||
__block BOOL success = YES;
|
||||
[_connection requestDataConnectionWithCompletion:^(BOOL result) {
|
||||
success = result;
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
// Verify RequestDataConnection packet is sent.
|
||||
NSData *requestPacket = [self
|
||||
prefixLengthData:GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommandRequestDataConnection, nil)];
|
||||
NSData *writtenReqData =
|
||||
[_fakeInputOutputStream dataSentToWatchWithMaxBytes:requestPacket.length];
|
||||
XCTAssertEqualObjects(writtenReqData, requestPacket);
|
||||
|
||||
// Don't send ResponseDataConnectionReady packet to simulate timeout.
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTestTimeout * 10 handler:nil];
|
||||
XCTAssertFalse(success);
|
||||
}
|
||||
|
||||
- (void)testIncomingConnectionReceiveRequestDataConnection {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
|
||||
// Simulate receiving RequestDataConnection packet.
|
||||
NSData *requestPacket = [self
|
||||
prefixLengthData:GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommandRequestDataConnection, nil)];
|
||||
[_fakeInputOutputStream writeFromDevice:requestPacket];
|
||||
|
||||
// Verify ResponseDataConnectionReady packet is sent.
|
||||
NSData *responsePacket =
|
||||
[self prefixLengthData:GNCMGenerateBLEL2CAPPacket(
|
||||
GNCMBLEL2CAPCommandResponseDataConnectionReady, nil)];
|
||||
NSData *writtenData = [_fakeInputOutputStream dataSentToWatchWithMaxBytes:responsePacket.length];
|
||||
XCTAssertEqualObjects(writtenData, responsePacket);
|
||||
}
|
||||
|
||||
- (void)testReceivePayload {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
NSData *payload = [@"test data" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
XCTestExpectation *payloadExpectation = [self expectationWithDescription:@"payload handler"];
|
||||
_connection.connectionHandlers = [GNCMConnectionHandlers
|
||||
payloadHandler:^(NSData *data) {
|
||||
XCTAssertEqualObjects(data, payload);
|
||||
[payloadExpectation fulfill];
|
||||
}
|
||||
disconnectedHandler:^{
|
||||
}];
|
||||
|
||||
// For incoming connection, need to receive RequestDataConnection and Introduction packet first.
|
||||
NSData *requestConnectionPacket = [self
|
||||
prefixLengthData:GNCMGenerateBLEL2CAPPacket(GNCMBLEL2CAPCommandRequestDataConnection, nil)];
|
||||
[_fakeInputOutputStream writeFromDevice:requestConnectionPacket];
|
||||
[self waitForSelfQueueWithConnection:_connection];
|
||||
|
||||
NSData *introPacket =
|
||||
[self prefixLengthData:GNCMGenerateBLEFramesIntroductionPacket(_serviceIDHash)];
|
||||
[_fakeInputOutputStream writeFromDevice:introPacket];
|
||||
[self waitForSelfQueueWithConnection:_connection];
|
||||
|
||||
// Send payload packet.
|
||||
NSData *payloadPacket = [self prefixLengthData:[self prefixDataWithServiceIDHash:_serviceIDHash
|
||||
data:payload]];
|
||||
[_fakeInputOutputStream writeFromDevice:payloadPacket];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTestTimeout handler:nil];
|
||||
}
|
||||
|
||||
- (void)testDidDisconnectWithError {
|
||||
_connection = [self createConnectionWithIncoming:YES];
|
||||
XCTestExpectation *disconnectionExpectation =
|
||||
[self expectationWithDescription:@"disconnection handler"];
|
||||
_connection.connectionHandlers = [GNCMConnectionHandlers
|
||||
payloadHandler:^(NSData *data) {
|
||||
}
|
||||
disconnectedHandler:^{
|
||||
[disconnectionExpectation fulfill];
|
||||
}];
|
||||
|
||||
[_connection stream:_stream didDisconnectWithError:nil];
|
||||
|
||||
[self waitForExpectationsWithTimeout:kTestTimeout handler:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+10
-1
@@ -16,11 +16,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCPeripheralManager.h"
|
||||
|
||||
@protocol GNCPeripheralManager;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface GNCBLEL2CAPServer (Testing)
|
||||
@interface GNCBLEL2CAPServer (Testing) <GNCPeripheralManagerDelegate>
|
||||
|
||||
/**
|
||||
* Creates a L2CAP server with a provided peripheral manager.
|
||||
@@ -31,6 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (instancetype)initWithPeripheralManager:(id<GNCPeripheralManager>)peripheralManager;
|
||||
|
||||
/**
|
||||
* Closes the L2CAP channel.
|
||||
*
|
||||
* This is only exposed for testing.
|
||||
*/
|
||||
- (void)closeL2CAPChannel;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCBLEL2CAPServer+Testing.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCFakePeripheralManager.h"
|
||||
|
||||
static const NSTimeInterval kTestTimeout = 1.0;
|
||||
|
||||
@interface GNCBLEL2CAPServerTest : XCTestCase
|
||||
@end
|
||||
|
||||
@@ -27,11 +30,19 @@
|
||||
|
||||
#pragma mark Tests
|
||||
|
||||
- (void)testInit {
|
||||
GNCBLEL2CAPServer *l2capServer = [[GNCBLEL2CAPServer alloc] init];
|
||||
XCTAssertNotNil(l2capServer);
|
||||
XCTAssertNil([l2capServer valueForKey:@"_peripheralManager"]);
|
||||
}
|
||||
|
||||
- (void)testPublishL2CAPChannelAndOpenChannelWhenStartListeningChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *psmPublishedExpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"PSM published."];
|
||||
XCTestExpectation *channelOpenedexpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Channel opened."];
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
@@ -41,12 +52,18 @@
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(error, nil);
|
||||
XCTAssertEqual(PSM, fakePeripheralManager.PSM);
|
||||
[psmPublishedExpectation fulfill];
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
XCTAssertNotNil(stream);
|
||||
[channelOpenedexpectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ channelOpenedexpectation ] timeout:0.5];
|
||||
[self waitForExpectations:@[ psmPublishedExpectation, channelOpenedexpectation ]
|
||||
timeout:kTestTimeout];
|
||||
XCTAssertNotNil([l2capServer valueForKey:@"l2CAPChannel"]);
|
||||
XCTAssertNotNil([l2capServer valueForKey:@"l2CAPStream"]);
|
||||
}
|
||||
|
||||
- (void)testFailedToPublishL2CAPChannel {
|
||||
@@ -57,6 +74,8 @@
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *psmPublishedExpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"PSM published with error."];
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
|
||||
[l2capServer
|
||||
@@ -64,10 +83,12 @@
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(error, fakePeripheralManager.didPublishL2CAPChannelError);
|
||||
XCTAssertEqual(PSM, 0);
|
||||
[psmPublishedExpectation fulfill];
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error){
|
||||
}];
|
||||
[self waitForExpectations:@[ psmPublishedExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testPoweredOffUnpublishesChannel {
|
||||
@@ -89,14 +110,17 @@
|
||||
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOff];
|
||||
|
||||
[self waitForExpectations:@[ fakePeripheralManager.unpublishExpectation ] timeout:0.0];
|
||||
[self waitForExpectations:@[ fakePeripheralManager.unpublishExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testStartPeripheralManagerInitiallyOff {
|
||||
- (void)testPeripheralManagerDidUpdateStatePoweredOffUnpublishesChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
fakePeripheralManager.state = CBManagerStatePoweredOn;
|
||||
[(id<CBPeripheralManagerDelegate>)l2capServer
|
||||
peripheralManagerDidUpdateState:(CBPeripheralManager *)fakePeripheralManager];
|
||||
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
@@ -108,7 +132,38 @@
|
||||
NSError *_Nullable error){
|
||||
}];
|
||||
|
||||
fakePeripheralManager.state = CBManagerStatePoweredOff;
|
||||
[(id<CBPeripheralManagerDelegate>)l2capServer
|
||||
peripheralManagerDidUpdateState:(CBPeripheralManager *)fakePeripheralManager];
|
||||
|
||||
[self waitForExpectations:@[ fakePeripheralManager.unpublishExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testStartPeripheralManagerInitiallyOff {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *psmPublishedExpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"PSM published."];
|
||||
XCTestExpectation *channelOpenedexpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Channel opened."];
|
||||
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(error, nil);
|
||||
XCTAssertEqual(PSM, fakePeripheralManager.PSM);
|
||||
[psmPublishedExpectation fulfill];
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error) {
|
||||
[channelOpenedexpectation fulfill];
|
||||
}];
|
||||
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
[self waitForExpectations:@[ psmPublishedExpectation, channelOpenedexpectation ]
|
||||
timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testClose {
|
||||
@@ -142,7 +197,133 @@
|
||||
|
||||
[l2capServer close];
|
||||
|
||||
[self waitForExpectations:@[ fakePeripheralManager.unpublishExpectation ] timeout:1.0];
|
||||
[self waitForExpectations:@[ fakePeripheralManager.unpublishExpectation ] timeout:kTestTimeout];
|
||||
}
|
||||
|
||||
- (void)testFailedToOpenL2CAPChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
fakePeripheralManager.didOpenL2CAPChannelError = [NSError errorWithDomain:@"fake"
|
||||
code:0
|
||||
userInfo:nil];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *channelOpenedexpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Channel opened."];
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(error, nil);
|
||||
XCTAssertEqual(PSM, fakePeripheralManager.PSM);
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertNil(stream);
|
||||
XCTAssertEqual(error, fakePeripheralManager.didOpenL2CAPChannelError);
|
||||
[channelOpenedexpectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ channelOpenedexpectation ] timeout:kTestTimeout];
|
||||
XCTAssertNil([l2capServer valueForKey:@"l2CAPChannel"]);
|
||||
XCTAssertNil([l2capServer valueForKey:@"l2CAPStream"]);
|
||||
}
|
||||
|
||||
- (void)testPeripheralManagerDidUnpublishL2CAPChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error){
|
||||
}];
|
||||
|
||||
[(id<CBPeripheralManagerDelegate>)l2capServer
|
||||
peripheralManager:(CBPeripheralManager *)fakePeripheralManager
|
||||
didUnpublishL2CAPChannel:l2capServer.PSM
|
||||
error:[NSError errorWithDomain:@"fake" code:0 userInfo:nil]];
|
||||
|
||||
XCTAssertEqual(l2capServer.PSM, 0);
|
||||
}
|
||||
|
||||
- (void)testCloseL2CAPChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *channelOpenedexpectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"Channel opened."];
|
||||
[fakePeripheralManager simulatePeripheralManagerDidUpdateState:CBManagerStatePoweredOn];
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error) {
|
||||
[channelOpenedexpectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ channelOpenedexpectation ] timeout:kTestTimeout];
|
||||
|
||||
[l2capServer closeL2CAPChannel];
|
||||
|
||||
XCTAssertNil([l2capServer valueForKey:@"l2CAPChannel"]);
|
||||
XCTAssertNil([l2capServer valueForKey:@"l2CAPStream"]);
|
||||
}
|
||||
|
||||
- (void)testPeripheralManagerDidPublishL2CAPChannel {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *expectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"completion called"];
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(PSM, 1);
|
||||
XCTAssertNil(error);
|
||||
[expectation fulfill];
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error){
|
||||
}];
|
||||
[(id<CBPeripheralManagerDelegate>)l2capServer
|
||||
peripheralManager:(CBPeripheralManager *)fakePeripheralManager
|
||||
didPublishL2CAPChannel:1
|
||||
error:nil];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
XCTAssertEqual(l2capServer.PSM, 1);
|
||||
}
|
||||
|
||||
- (void)testPeripheralManagerDidPublishL2CAPChannelWithError {
|
||||
GNCFakePeripheralManager *fakePeripheralManager = [[GNCFakePeripheralManager alloc] init];
|
||||
GNCBLEL2CAPServer *l2capServer =
|
||||
[[GNCBLEL2CAPServer alloc] initWithPeripheralManager:fakePeripheralManager
|
||||
queue:dispatch_get_main_queue()];
|
||||
XCTestExpectation *expectation =
|
||||
[[XCTestExpectation alloc] initWithDescription:@"completion called"];
|
||||
NSError *publishError = [NSError errorWithDomain:@"test" code:0 userInfo:nil];
|
||||
[l2capServer
|
||||
startListeningChannelWithPSMPublishedCompletionHandler:^(uint16_t PSM,
|
||||
NSError *_Nullable error) {
|
||||
XCTAssertEqual(PSM, 0);
|
||||
XCTAssertEqualObjects(error, publishError);
|
||||
[expectation fulfill];
|
||||
}
|
||||
channelOpenedCompletionHandler:^(GNCBLEL2CAPStream *_Nullable stream,
|
||||
NSError *_Nullable error){
|
||||
}];
|
||||
[(id<CBPeripheralManagerDelegate>)l2capServer
|
||||
peripheralManager:(CBPeripheralManager *)fakePeripheralManager
|
||||
didPublishL2CAPChannel:0
|
||||
error:publishError];
|
||||
[self waitForExpectations:@[ expectation ] timeout:kTestTimeout];
|
||||
XCTAssertEqual(l2capServer.PSM, 0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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 <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* A fake CBL2CAPChannel for testing.
|
||||
*/
|
||||
@interface GNCFakeCBL2CAPChannel : NSObject
|
||||
|
||||
/** The input stream for the L2CAP channel. */
|
||||
@property(nonatomic, nullable) NSInputStream *inputStream;
|
||||
/** The output stream for the L2CAP channel. */
|
||||
@property(nonatomic, nullable) NSOutputStream *outputStream;
|
||||
/** The socket file descriptor for the L2CAP channel. */
|
||||
@property(nonatomic, readonly) int socketFD;
|
||||
/** The PSM (Protocol/Service Multiplexer) of the L2CAP channel. */
|
||||
@property(nonatomic, readonly) CBL2CAPPSM PSM;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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/GNCFakeCBL2CAPChannel.h"
|
||||
|
||||
@implementation GNCFakeCBL2CAPChannel
|
||||
@end
|
||||
@@ -67,6 +67,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property(nonatomic, nullable, readwrite) NSError *openL2CAPChannelError;
|
||||
|
||||
/** Fake input stream to inject into CBL2CAPChannel. */
|
||||
@property(nonatomic, nullable) NSInputStream *channelInputStream;
|
||||
/** Fake output stream to inject into CBL2CAPChannel. */
|
||||
@property(nonatomic, nullable) NSOutputStream *channelOutputStream;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -117,12 +117,20 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)openL2CAPChannel:(CBL2CAPPSM)PSM {
|
||||
[self delayDelegateUsingBlock:^() {
|
||||
CBL2CAPChannel *channel = [[CBL2CAPChannel alloc] init];
|
||||
if (self.channelInputStream) {
|
||||
[channel setValue:self.channelInputStream forKey:@"inputStream"];
|
||||
}
|
||||
if (self.channelOutputStream) {
|
||||
[channel setValue:self.channelOutputStream forKey:@"outputStream"];
|
||||
}
|
||||
if (_openL2CAPChannelError) {
|
||||
[self.peripheralDelegate gnc_peripheral:self
|
||||
didOpenL2CAPChannel:channel
|
||||
error:_openL2CAPChannelError];
|
||||
[self.peripheralDelegate peripheral:(CBPeripheral *)self
|
||||
didOpenL2CAPChannel:channel
|
||||
error:_openL2CAPChannelError];
|
||||
} else {
|
||||
[self.peripheralDelegate gnc_peripheral:self didOpenL2CAPChannel:channel error:nil];
|
||||
[self.peripheralDelegate peripheral:(CBPeripheral *)self
|
||||
didOpenL2CAPChannel:channel
|
||||
error:nil];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** The PSM of the L2CAP channel. */
|
||||
@property(nonatomic) CBL2CAPPSM PSM;
|
||||
|
||||
/** The fake peripheral manager state. */
|
||||
@property(nonatomic, readwrite) CBManagerState state;
|
||||
|
||||
/** Expectation fulfilled when peripheral responds to a request with success. */
|
||||
@property(nonatomic, readonly) XCTestExpectation *respondToRequestSuccessExpectation;
|
||||
|
||||
@@ -83,6 +86,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property(nonatomic, nullable, readwrite) NSError *didUnPublishL2CAPChannelError;
|
||||
|
||||
/**
|
||||
* Similates a @c openL2CAPChannel: error.
|
||||
*
|
||||
* Setting this error to a value other than @c nil will simulate a failure when calling @c
|
||||
* openL2CAPChannel: and will call the @c gnc_peripheralManager:didOpenL2CAPChannel:error:
|
||||
* delegate method with the provided error.
|
||||
*/
|
||||
@property(nonatomic, nullable, readwrite) NSError *didOpenL2CAPChannelError;
|
||||
|
||||
/**
|
||||
* Simulates a state update event.
|
||||
*
|
||||
@@ -93,6 +105,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)simulatePeripheralManagerDidUpdateState:(CBManagerState)fakeState;
|
||||
|
||||
/**
|
||||
* Simulates a read request event.
|
||||
*
|
||||
* Creates a fake read request for the given service and characteristic UUIDs and calls the
|
||||
* @c gnc_peripheralManager:didReceiveReadRequest: delegate method.
|
||||
*
|
||||
* @param service The service UUID of the characteristic to read from.
|
||||
* @param characteristic The characteristic UUID to read from.
|
||||
*/
|
||||
- (void)simulatePeripheralManagerDidReceiveReadRequestForService:(CBUUID *)service
|
||||
characteristic:(CBUUID *)characteristic;
|
||||
|
||||
|
||||
+10
-10
@@ -19,6 +19,8 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/GNCPeripheralManager.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCBLEL2CAPFakeInputOutputStream.h"
|
||||
#import "internal/platform/implementation/apple/Mediums/BLE/Tests/GNCFakeCBL2CAPChannel.h"
|
||||
|
||||
@interface CBCharacteristic ()
|
||||
|
||||
@@ -59,7 +61,6 @@
|
||||
static const uint16_t kPSM = 192;
|
||||
|
||||
@implementation GNCFakePeripheralManager {
|
||||
CBManagerState _state;
|
||||
BOOL _isAdvertising;
|
||||
NSDictionary<NSString *, id> *_advertisementData;
|
||||
NSMutableArray<CBService *> *_services;
|
||||
@@ -87,10 +88,6 @@ static const uint16_t kPSM = 192;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CBManagerState)state {
|
||||
return _state;
|
||||
}
|
||||
|
||||
- (BOOL)isAdvertising {
|
||||
return _isAdvertising;
|
||||
}
|
||||
@@ -99,9 +96,7 @@ static const uint16_t kPSM = 192;
|
||||
if (!_didAddServiceError) {
|
||||
[_services addObject:service];
|
||||
}
|
||||
[_peripheralDelegate gnc_peripheralManager:self
|
||||
didAddService:service
|
||||
error:_didAddServiceError];
|
||||
[_peripheralDelegate gnc_peripheralManager:self didAddService:service error:_didAddServiceError];
|
||||
}
|
||||
|
||||
- (void)removeService:(CBMutableService *)service {
|
||||
@@ -140,9 +135,14 @@ static const uint16_t kPSM = 192;
|
||||
didPublishL2CAPChannel:localPSM
|
||||
error:_didPublishL2CAPChannelError];
|
||||
if (!_didPublishL2CAPChannelError) {
|
||||
GNCBLEL2CAPFakeInputOutputStream *fakeStream =
|
||||
[[GNCBLEL2CAPFakeInputOutputStream alloc] initWithBufferSize:1024];
|
||||
GNCFakeCBL2CAPChannel *fakeChannel = [[GNCFakeCBL2CAPChannel alloc] init];
|
||||
fakeChannel.inputStream = fakeStream.inputStream;
|
||||
fakeChannel.outputStream = fakeStream.outputStream;
|
||||
[_peripheralDelegate gnc_peripheralManager:self
|
||||
didOpenL2CAPChannel:[[CBL2CAPChannel alloc] init]
|
||||
error:nil];
|
||||
didOpenL2CAPChannel:(CBL2CAPChannel *)fakeChannel
|
||||
error:_didOpenL2CAPChannelError];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user