[NC Apple coverage] Test implementation for Wifi LAN medium.

PiperOrigin-RevId: 802829901
This commit is contained in:
Edwin Wu
2025-09-03 20:39:01 -07:00
committed by Copybara-Service
parent 6e1fd931b7
commit f0d164fc40
14 changed files with 658 additions and 0 deletions
@@ -35,10 +35,15 @@
byte3:(uint8_t)byte3
byte4:(uint8_t)byte4 NS_DESIGNATED_INITIALIZER;
/** Creates an IPv4 address from a 4 byte integer. */
+ (nonnull instancetype)addressFromFourByteInt:(uint32_t)address;
/** Creates an IPv4 address from a 4 byte data object. */
+ (nonnull instancetype)addressFromData:(nonnull NSData *)address;
/** Creates an IPv4 address from a human readable dotted representation. */
+ (nullable instancetype)addressWithDottedRepresentation:(nonnull NSString *)address;
/** The first byte of the IP address. */
@property(nonatomic, readonly) uint8_t byte1;
@@ -47,6 +47,33 @@
byte4:bytes[3]];
}
+ (nullable instancetype)addressWithDottedRepresentation:(NSString *)address {
NSArray<NSString *> *components = [address componentsSeparatedByString:@"."];
if (components.count != 4) {
return nil;
}
uint8_t bytes[4];
for (int i = 0; i < 4; ++i) {
NSScanner *scanner = [NSScanner scannerWithString:components[i]];
int value;
// The string must be a valid integer and must not contain any other characters.
if (![scanner scanInt:&value] || ![scanner isAtEnd]) {
return nil;
}
if (value < 0 || value > 255) {
return nil;
}
bytes[i] = (uint8_t)value;
}
return [[GNCIPv4Address alloc] initWithByte1:bytes[0]
byte2:bytes[1]
byte3:bytes[2]
byte4:bytes[3]];
}
- (NSData *)binaryRepresentation {
const uint8_t bytes[] = {_byte1, _byte2, _byte3, _byte4};
return [NSData dataWithBytes:bytes length:4];
@@ -20,6 +20,25 @@ licenses(["notice"])
package(default_visibility = ["//:__subpackages__"])
objc_library(
name = "FakeNWFramework",
testonly = True,
srcs = [
"GNCFakeNWFramework.m",
"GNCFakeNWFrameworkServerSocket.m",
"GNCFakeNWFrameworkSocket.m",
],
hdrs = [
"GNCFakeNWFramework.h",
"GNCFakeNWFrameworkServerSocket.h",
"GNCFakeNWFrameworkSocket.h",
],
deps = [
"//internal/platform/implementation/apple/Mediums/WiFiCommon",
"//third_party/apple_frameworks:Foundation",
],
)
objc_library(
name = "WiFiCommonTestsLib",
testonly = True,
@@ -0,0 +1,46 @@
// 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/WiFiCommon/GNCNWFramework.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class GNCFakeNWFrameworkSocket;
@class GNCFakeNWFrameworkServerSocket;
/** A fake implementation of @c GNCNWFramework to inject for testing. */
@interface GNCFakeNWFramework : GNCNWFramework
@property(nonatomic, nullable) NSNumber* startedAdvertisingPort;
@property(nonatomic, nullable) NSString* startedAdvertisingServiceName;
@property(nonatomic, nullable) NSString* startedAdvertisingServiceType;
@property(nonatomic, nullable) NSNumber* stoppedAdvertisingPort;
@property(nonatomic, nullable) NSString* startedDiscoveryServiceType;
@property(nonatomic) BOOL startedDiscoveryIncludePeerToPeer;
@property(nonatomic, nullable) NSString* stoppedDiscoveryServiceType;
@property(nonatomic, nullable) NSString* connectedToServiceName;
@property(nonatomic, nullable) NSString* connectedToServiceType;
@property(nonatomic, nullable) GNCIPv4Address* connectedToHost;
@property(nonatomic) NSInteger connectedToPort;
@property(nonatomic) BOOL connectedToIncludePeerToPeer;
@property(nonatomic) NSInteger listenedForServiceOnPort;
@property(nonatomic) BOOL listenedForServiceIncludePeerToPeer;
@property(nonatomic, readonly) NSMutableArray<GNCFakeNWFrameworkSocket *>* sockets;
@property(nonatomic, readonly) NSMutableArray<GNCFakeNWFrameworkServerSocket *>* serverSockets;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,94 @@
// 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/WiFiCommon/Tests/GNCFakeNWFramework.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFrameworkServerSocket.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFrameworkSocket.h"
@implementation GNCFakeNWFramework
- (instancetype)init {
self = [super init];
if (self) {
_sockets = [NSMutableArray array];
_serverSockets = [NSMutableArray array];
}
return self;
}
- (void)startAdvertisingPort:(NSInteger)port
serviceName:(NSString*)serviceName
serviceType:(NSString*)serviceType
txtRecords:(NSDictionary<NSString*, NSString*>*)txtRecords {
self.startedAdvertisingPort = @(port);
self.startedAdvertisingServiceName = serviceName;
self.startedAdvertisingServiceType = serviceType;
}
- (void)stopAdvertisingPort:(NSInteger)port {
self.stoppedAdvertisingPort = @(port);
}
- (BOOL)startDiscoveryForServiceType:(NSString*)serviceType
serviceFoundHandler:(nonnull ServiceUpdateHandler)serviceFoundHandler
serviceLostHandler:(nonnull ServiceUpdateHandler)serviceLostHandler
includePeerToPeer:(BOOL)includePeerToPeer
error:(NSError**)error {
self.startedDiscoveryServiceType = serviceType;
self.startedDiscoveryIncludePeerToPeer = includePeerToPeer;
return YES;
}
- (void)stopDiscoveryForServiceType:(NSString*)serviceType {
self.stoppedDiscoveryServiceType = serviceType;
}
- (GNCNWFrameworkSocket*)connectToServiceName:(NSString*)serviceName
serviceType:(NSString*)serviceType
error:(NSError**)error {
self.connectedToServiceName = serviceName;
self.connectedToServiceType = serviceType;
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* socket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
[self.sockets addObject:socket];
return socket;
}
- (GNCNWFrameworkSocket*)connectToHost:(GNCIPv4Address*)host
port:(NSInteger)port
includePeerToPeer:(BOOL)includePeerToPeer
error:(NSError**)error {
self.connectedToHost = host;
self.connectedToPort = port;
self.connectedToIncludePeerToPeer = includePeerToPeer;
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* socket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
[self.sockets addObject:socket];
return socket;
}
- (GNCNWFrameworkServerSocket*)listenForServiceOnPort:(NSInteger)port
includePeerToPeer:(BOOL)includePeerToPeer
error:(NSError**)error {
self.listenedForServiceOnPort = port;
self.listenedForServiceIncludePeerToPeer = includePeerToPeer;
GNCFakeNWFrameworkServerSocket* serverSocket =
[[GNCFakeNWFrameworkServerSocket alloc] initWithPort:port];
[self.serverSockets addObject:serverSocket];
return serverSocket;
}
@end
@@ -0,0 +1,32 @@
// 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/WiFiCommon/GNCNWFrameworkServerSocket.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class GNCFakeNWFrameworkSocket;
/** A fake implementation of @c GNCNWFrameworkServerSocket to inject for testing. */
@interface GNCFakeNWFrameworkServerSocket : GNCNWFrameworkServerSocket
@property(nonatomic) BOOL isClosed;
@property(nonatomic, nullable) NSError* acceptError;
@property(nonatomic, nullable) GNCFakeNWFrameworkSocket* socketToReturnOnAccept;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,54 @@
// 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/WiFiCommon/Tests/GNCFakeNWFrameworkServerSocket.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/GNCIPv4Address.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFrameworkSocket.h"
@implementation GNCFakeNWFrameworkServerSocket {
GNCIPv4Address *_ipAddress;
}
- (instancetype)initWithPort:(NSInteger)port {
self = [super initWithPort:port];
if (self) {
_ipAddress = [[GNCIPv4Address alloc] initWithByte1:192 byte2:168 byte3:1 byte4:1];
}
return self;
}
- (GNCIPv4Address *)ipAddress {
return _ipAddress;
}
- (nullable GNCNWFrameworkSocket *)acceptWithError:(NSError **)error {
if (self.acceptError) {
if (error) {
*error = self.acceptError;
}
return nil;
}
if (self.socketToReturnOnAccept) {
return self.socketToReturnOnAccept;
}
nw_connection_t connection = (nw_connection_t) @"mock connection";
return [[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
}
- (void)close {
self.isClosed = YES;
}
@end
@@ -0,0 +1,32 @@
// 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/WiFiCommon/GNCNWFrameworkSocket.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** A fake implementation of @c GNCNWFrameworkSocket to inject for testing. */
@interface GNCFakeNWFrameworkSocket : GNCNWFrameworkSocket
@property(nonatomic, nullable) NSData* dataToRead;
@property(nonatomic, readonly) NSMutableData* writtenData;
@property(nonatomic) BOOL isClosed;
@property(nonatomic, nullable) NSError* readError;
@property(nonatomic, nullable) NSError* writeError;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,57 @@
// 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/WiFiCommon/Tests/GNCFakeNWFrameworkSocket.h"
@implementation GNCFakeNWFrameworkSocket
- (instancetype)initWithConnection:(nw_connection_t)connection {
self = [super initWithConnection:connection];
if (self) {
_writtenData = [NSMutableData data];
}
return self;
}
- (nullable NSData *)readMaxLength:(NSUInteger)length error:(NSError **)error {
if (self.readError) {
if (error) {
*error = self.readError;
}
return nil;
}
if (self.dataToRead) {
NSData *data = self.dataToRead;
self.dataToRead = nil;
return data;
}
return [NSData data];
}
- (BOOL)write:(NSData *)data error:(NSError **)error {
if (self.writeError) {
if (error) {
*error = self.writeError;
}
return NO;
}
[self.writtenData appendData:data];
return YES;
}
- (void)close {
self.isClosed = YES;
}
@end
@@ -111,4 +111,32 @@
XCTAssertEqual(bytes[3], 171);
}
- (void)testAddressWithDottedRepresentationWithValidAddress {
GNCIPv4Address *address =
[GNCIPv4Address addressWithDottedRepresentation:@"192.168.1.1"];
XCTAssertNotNil(address);
XCTAssertEqual(address.byte1, 192);
XCTAssertEqual(address.byte2, 168);
XCTAssertEqual(address.byte3, 1);
XCTAssertEqual(address.byte4, 1);
}
- (void)testAddressWithDottedRepresentationWithOutOfRangeAddress {
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"256.1.1.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"-1.1.1.1"]);
}
- (void)testAddressWithDottedRepresentationWithNonNumericAddress {
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"foo.1.1.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"1.foo.1.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"1.1.foo.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"1.1.1.foo"]);
}
- (void)testAddressWithDottedRepresentationWithInvalidFormatAddress {
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"1.1.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@"1.1.1.1.1"]);
XCTAssertNil([GNCIPv4Address addressWithDottedRepresentation:@""]);
}
@end
@@ -31,6 +31,7 @@ objc_library(
"GNCScheduledExecutorTest.mm",
"GNCSingleThreadExecutorTest.mm",
"GNCUtilsTest.m",
"GNCWifiLanMediumTest.mm",
"UtilsTest.mm",
],
deps = [
@@ -40,6 +41,8 @@ objc_library(
"//internal/platform/implementation/apple", # buildcleaner: keep
"//internal/platform/implementation/apple:Shared",
"//internal/platform/implementation/apple:ble_v2",
"//internal/platform/implementation/apple/Mediums/WiFiCommon",
"//internal/platform/implementation/apple/Mediums/WiFiCommon/Tests:FakeNWFramework",
"//third_party/apple_frameworks:CommonCrypto",
"//third_party/apple_frameworks:Foundation",
"//third_party/apple_frameworks:XCTest",
@@ -0,0 +1,257 @@
// 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 <XCTest/XCTest.h>
#include "internal/platform/implementation/apple/wifi_lan.h"
#include <string>
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/GNCIPv4Address.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/GNCNWFramework.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFramework.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFrameworkServerSocket.h"
#import "internal/platform/implementation/apple/Mediums/WiFiCommon/Tests/GNCFakeNWFrameworkSocket.h"
@interface GNCWifiLanMediumTest : XCTestCase
@end
@implementation GNCWifiLanMediumTest {
GNCFakeNWFramework* _fakeNWFramework;
std::unique_ptr<nearby::apple::WifiLanMedium> _wifiLanMedium;
}
- (void)setUp {
[super setUp];
_fakeNWFramework = [[GNCFakeNWFramework alloc] init];
_wifiLanMedium = std::make_unique<nearby::apple::WifiLanMedium>(_fakeNWFramework);
}
- (void)tearDown {
_wifiLanMedium.reset();
_fakeNWFramework = nil;
[super tearDown];
}
- (void)testStartAdvertising {
nearby::NsdServiceInfo nsdServiceInfo;
nsdServiceInfo.SetServiceType("_my-service._tcp");
nsdServiceInfo.SetServiceName("My Service");
nsdServiceInfo.SetPort(1234);
XCTAssertTrue(_wifiLanMedium->StartAdvertising(nsdServiceInfo));
XCTAssertEqualObjects(_fakeNWFramework.startedAdvertisingPort, @(1234));
XCTAssertEqualObjects(_fakeNWFramework.startedAdvertisingServiceName, @"My Service");
XCTAssertEqualObjects(_fakeNWFramework.startedAdvertisingServiceType, @"_my-service._tcp");
}
- (void)testStopAdvertising {
nearby::NsdServiceInfo nsdServiceInfo;
nsdServiceInfo.SetPort(1234);
XCTAssertTrue(_wifiLanMedium->StopAdvertising(nsdServiceInfo));
XCTAssertEqualObjects(_fakeNWFramework.stoppedAdvertisingPort, @(1234));
}
- (void)testStartDiscovery {
std::string serviceType = "_my-service._tcp";
XCTAssertTrue(_wifiLanMedium->StartDiscovery(
serviceType, nearby::api::WifiLanMedium::DiscoveredServiceCallback{}));
XCTAssertEqualObjects(_fakeNWFramework.startedDiscoveryServiceType, @"_my-service._tcp");
XCTAssertFalse(_fakeNWFramework.startedDiscoveryIncludePeerToPeer);
}
- (void)testStopDiscovery {
std::string serviceType = "_my-service._tcp";
XCTAssertTrue(_wifiLanMedium->StopDiscovery(serviceType));
XCTAssertEqualObjects(_fakeNWFramework.stoppedDiscoveryServiceType, @"_my-service._tcp");
}
- (void)testConnectToServiceWithNsdServiceInfo {
nearby::NsdServiceInfo nsdServiceInfo;
nsdServiceInfo.SetServiceType("_my-service._tcp");
nsdServiceInfo.SetServiceName("My Service");
nearby::CancellationFlag cancellationFlag;
_wifiLanMedium->ConnectToService(nsdServiceInfo, &cancellationFlag);
XCTAssertEqualObjects(_fakeNWFramework.connectedToServiceName, @"My Service");
XCTAssertEqualObjects(_fakeNWFramework.connectedToServiceType, @"_my-service._tcp");
}
- (void)testConnectToServiceWithIpAddressAndPort {
std::string ipAddress = "\xC0\xA8\x01\x01"; // 192.168.1.1
int port = 1234;
nearby::CancellationFlag cancellationFlag;
_wifiLanMedium->ConnectToService(ipAddress, port, &cancellationFlag);
XCTAssertEqualObjects([_fakeNWFramework.connectedToHost dottedRepresentation], @"192.168.1.1");
XCTAssertEqual(_fakeNWFramework.connectedToPort, 1234);
XCTAssertFalse(_fakeNWFramework.connectedToIncludePeerToPeer);
}
- (void)testListenForService {
int port = 1234;
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(port);
XCTAssertTrue(serverSocket != nullptr);
XCTAssertEqual(_fakeNWFramework.listenedForServiceOnPort, 1234);
XCTAssertFalse(_fakeNWFramework.listenedForServiceIncludePeerToPeer);
}
- (void)testSocketAndStream {
// Create a server socket.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
XCTAssertTrue(serverSocket != nullptr);
GNCFakeNWFrameworkServerSocket* fakeServerSocket =
(GNCFakeNWFrameworkServerSocket*)_fakeNWFramework.serverSockets[0];
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* fakeSocket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
fakeServerSocket.socketToReturnOnAccept = fakeSocket;
// Accept a client socket.
std::unique_ptr<nearby::api::WifiLanSocket> clientSocket = serverSocket->Accept();
XCTAssertTrue(clientSocket != nullptr);
// Test input stream.
nearby::InputStream& inputStream = clientSocket->GetInputStream();
fakeSocket.dataToRead = [@"test data" dataUsingEncoding:NSUTF8StringEncoding];
nearby::ExceptionOr<nearby::ByteArray> readData = inputStream.Read(9);
XCTAssertTrue(readData.ok());
XCTAssertEqual(std::string(readData.result()), "test data");
// Test output stream.
nearby::OutputStream& outputStream = clientSocket->GetOutputStream();
nearby::ByteArray writeData("write data");
XCTAssertTrue(outputStream.Write(writeData).Ok());
XCTAssertEqualObjects(fakeSocket.writtenData,
[@"write data" dataUsingEncoding:NSUTF8StringEncoding]);
// Test closing the socket.
XCTAssertTrue(clientSocket->Close().Ok());
XCTAssertTrue(fakeSocket.isClosed);
// Test closing the server socket.
XCTAssertTrue(serverSocket->Close().Ok());
XCTAssertTrue(fakeServerSocket.isClosed);
}
- (void)testServerSocketGetIPAddress {
// Create a server socket.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
XCTAssertTrue(serverSocket != nullptr);
// IP address is hardcoded in GNCFakeNWFrameworkServerSocket to 192.168.1.1
GNCIPv4Address* ipAddress = [GNCIPv4Address addressWithDottedRepresentation:@"192.168.1.1"];
NSData* ipAddressData = ipAddress.binaryRepresentation;
XCTAssertEqual(serverSocket->GetIPAddress(),
std::string((char*)ipAddressData.bytes, ipAddressData.length));
// Test closing the server socket.
XCTAssertTrue(serverSocket->Close().Ok());
}
- (void)testServerSocketGetPort {
// Create a server socket.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
XCTAssertTrue(serverSocket != nullptr);
XCTAssertEqual(serverSocket->GetPort(), 1234);
// Test closing the server socket.
XCTAssertTrue(serverSocket->Close().Ok());
}
- (void)testOutputStreamClose {
// Create a server socket and accept a client.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
GNCFakeNWFrameworkServerSocket* fakeServerSocket =
(GNCFakeNWFrameworkServerSocket*)_fakeNWFramework.serverSockets[0];
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* fakeSocket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
fakeServerSocket.socketToReturnOnAccept = fakeSocket;
std::unique_ptr<nearby::api::WifiLanSocket> clientSocket = serverSocket->Accept();
XCTAssertTrue(clientSocket != nullptr);
// Get the output stream.
nearby::OutputStream& outputStream = clientSocket->GetOutputStream();
// Close the output stream.
XCTAssertTrue(outputStream.Close().Ok());
XCTAssertFalse(fakeSocket.isClosed);
// Close the server socket.
XCTAssertTrue(serverSocket->Close().Ok());
}
- (void)testOutputStreamFlush {
// Create a server socket and accept a client.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
GNCFakeNWFrameworkServerSocket* fakeServerSocket =
(GNCFakeNWFrameworkServerSocket*)_fakeNWFramework.serverSockets[0];
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* fakeSocket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
fakeServerSocket.socketToReturnOnAccept = fakeSocket;
std::unique_ptr<nearby::api::WifiLanSocket> clientSocket = serverSocket->Accept();
XCTAssertTrue(clientSocket != nullptr);
// Get the output stream.
nearby::OutputStream& outputStream = clientSocket->GetOutputStream();
// Flush the output stream.
XCTAssertTrue(outputStream.Flush().Ok());
// Close the socket and server socket.
XCTAssertTrue(clientSocket->Close().Ok());
XCTAssertTrue(serverSocket->Close().Ok());
}
- (void)testInputStreamClose {
// Create a server socket and accept a client.
std::unique_ptr<nearby::api::WifiLanServerSocket> serverSocket =
_wifiLanMedium->ListenForService(1234);
GNCFakeNWFrameworkServerSocket* fakeServerSocket =
(GNCFakeNWFrameworkServerSocket*)_fakeNWFramework.serverSockets[0];
nw_connection_t connection = (nw_connection_t) @"mock connection";
GNCFakeNWFrameworkSocket* fakeSocket =
[[GNCFakeNWFrameworkSocket alloc] initWithConnection:connection];
fakeServerSocket.socketToReturnOnAccept = fakeSocket;
std::unique_ptr<nearby::api::WifiLanSocket> clientSocket = serverSocket->Accept();
XCTAssertTrue(clientSocket != nullptr);
// Get the input stream.
nearby::InputStream& inputStream = clientSocket->GetInputStream();
// Close the input stream.
XCTAssertTrue(inputStream.Close().Ok());
XCTAssertFalse(fakeSocket.isClosed);
// Close the server socket.
XCTAssertTrue(serverSocket->Close().Ok());
}
@end
@@ -103,6 +103,8 @@ class WifiLanServerSocket : public api::WifiLanServerSocket {
class WifiLanMedium : public api::WifiLanMedium {
public:
WifiLanMedium();
// For testing only.
explicit WifiLanMedium(GNCNWFramework* medium);
~WifiLanMedium() override = default;
WifiLanMedium(const WifiLanMedium&) = delete;
@@ -124,6 +124,8 @@ Exception WifiLanServerSocket::Close() {
WifiLanMedium::WifiLanMedium() { medium_ = [[GNCNWFramework alloc] init]; }
WifiLanMedium::WifiLanMedium(GNCNWFramework* medium) : medium_(medium) {}
bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
return network_utils::StartAdvertising(medium_, nsd_service_info);
}