mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			191 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			191 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Objective-C
		
	
#import <XCTest/XCTest.h>
 | 
						|
#import <CoreFoundation/CFSocket.h>
 | 
						|
#import "IpAddress.h"
 | 
						|
#import "TestUtil.h"
 | 
						|
#import "ThreadManager.h"
 | 
						|
#import "UdpSocket.h"
 | 
						|
#import "Util.h"
 | 
						|
 | 
						|
@interface UdpSocketTest : XCTestCase
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
@implementation UdpSocketTest
 | 
						|
-(void) testSpecifiedPortLocally {
 | 
						|
    TOCCancelTokenSource* receiverLife = [TOCCancelTokenSource new];
 | 
						|
    TOCCancelTokenSource* senderLife = [TOCCancelTokenSource new];
 | 
						|
    
 | 
						|
    __block NSData* received = nil;
 | 
						|
    __block bool senderReceivedData = false;
 | 
						|
    NSData* r1 = [@[@2,@3,@5] ows_toUint8Data];
 | 
						|
    NSData* r2 = [@[@7,@11,@13] ows_toUint8Data];
 | 
						|
    NSData* r3 = [@[@17,@19,@23] ows_toUint8Data];
 | 
						|
    
 | 
						|
    in_port_t port1 = (in_port_t)(arc4random_uniform(40000) + 10000);
 | 
						|
    in_port_t port2 = port1 + (in_port_t)1;
 | 
						|
    
 | 
						|
    UdpSocket* receiver = [UdpSocket udpSocketFromLocalPort:port1 toRemoteEndPoint:[IpEndPoint ipEndPointAtAddress:IpAddress.localhost onPort:port2]];
 | 
						|
    UdpSocket* sender = [UdpSocket udpSocketFromLocalPort:port2 toRemoteEndPoint:[IpEndPoint ipEndPointAtAddress:IpAddress.localhost onPort:port1]];
 | 
						|
    [receiver startWithHandler:[PacketHandler packetHandler:^(id packet) {
 | 
						|
        received = packet;
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        test(false);
 | 
						|
    }] untilCancelled:receiverLife.token];
 | 
						|
    __block bool failed = false;
 | 
						|
    [sender startWithHandler:[PacketHandler packetHandler:^(NSData* packet) {
 | 
						|
        // there's a length check here because when the destination is unreachable the sender sometimes gets a superfluous empty data callback... no idea why.
 | 
						|
        senderReceivedData |= packet.length > 0;
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        failed = true;
 | 
						|
    }] untilCancelled:senderLife.token];
 | 
						|
    
 | 
						|
    test(receiver.isLocalPortKnown);
 | 
						|
    test(receiver.localPort == port1);
 | 
						|
    test(sender.isLocalPortKnown);
 | 
						|
    test(sender.localPort == port2);
 | 
						|
 | 
						|
    testChurnAndConditionMustStayTrue(received == nil, 0.1);
 | 
						|
    
 | 
						|
    [sender send:r1];
 | 
						|
    testChurnUntil([received isEqualToData:r1], 1.0);
 | 
						|
    test([received isEqualToData:r1]);
 | 
						|
    
 | 
						|
    [sender send:r2];
 | 
						|
    testChurnUntil([received isEqualToData:r2], 1.0);
 | 
						|
    
 | 
						|
    [receiverLife cancel];
 | 
						|
    test(!failed);
 | 
						|
    [sender send:r3];
 | 
						|
    testChurnUntil(failed, 1.0);
 | 
						|
    test([received isEqualToData:r2]);
 | 
						|
    
 | 
						|
    [senderLife cancel];
 | 
						|
    test(!senderReceivedData);
 | 
						|
}
 | 
						|
-(void) testArbitraryPortLocally {
 | 
						|
    TOCCancelTokenSource* receiverLife = [TOCCancelTokenSource new];
 | 
						|
    TOCCancelTokenSource* senderLife = [TOCCancelTokenSource new];
 | 
						|
    
 | 
						|
    __block NSData* received = nil;
 | 
						|
    __block bool senderReceivedData = false;
 | 
						|
    NSData* r1 = [@[@2,@3,@5] ows_toUint8Data];
 | 
						|
    NSData* r2 = [@[@7,@11,@13] ows_toUint8Data];
 | 
						|
    NSData* r3 = [@[@17,@19,@23] ows_toUint8Data];
 | 
						|
    
 | 
						|
    in_port_t unusedPort = (in_port_t)(arc4random_uniform(40000) + 10000);
 | 
						|
    
 | 
						|
    UdpSocket* receiver = [UdpSocket udpSocketTo:[IpEndPoint ipEndPointAtAddress:IpAddress.localhost
 | 
						|
                                                                          onPort:unusedPort]];
 | 
						|
    [receiver startWithHandler:[PacketHandler packetHandler:^(id packet) {
 | 
						|
        @synchronized (churnLock()) {
 | 
						|
            received = packet;
 | 
						|
        }
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        test(false);
 | 
						|
    }] untilCancelled:receiverLife.token];
 | 
						|
    
 | 
						|
    __block bool failed = false;
 | 
						|
    UdpSocket* sender = [UdpSocket udpSocketFromLocalPort:unusedPort
 | 
						|
                                         toRemoteEndPoint:[IpEndPoint ipEndPointAtAddress:IpAddress.localhost
 | 
						|
                                                                                   onPort:receiver.localPort]];
 | 
						|
    [sender startWithHandler:[PacketHandler packetHandler:^(NSData* packet) {
 | 
						|
        // there's a length check here because when the destination is unreachable the sender sometimes gets a superfluous empty data callback... no idea why.
 | 
						|
        senderReceivedData |= packet.length > 0;
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        failed = true;
 | 
						|
    }] untilCancelled:senderLife.token];
 | 
						|
    
 | 
						|
    
 | 
						|
    testChurnAndConditionMustStayTrue(received == nil, 0.1);
 | 
						|
    
 | 
						|
    [sender send:r1];
 | 
						|
    testChurnUntil([received isEqualToData:r1], 1.0);
 | 
						|
    
 | 
						|
    [sender send:r2];
 | 
						|
    testChurnUntil([received isEqualToData:r2], 1.0);
 | 
						|
    
 | 
						|
    [receiverLife cancel];
 | 
						|
    test(!failed);
 | 
						|
    [sender send:r3];
 | 
						|
    testChurnAndConditionMustStayTrue([received isEqualToData:r2], 0.1);
 | 
						|
    test([received isEqualToData:r2]);
 | 
						|
    
 | 
						|
    [senderLife cancel];
 | 
						|
    test(!senderReceivedData);
 | 
						|
}
 | 
						|
-(void) testUdpListen {
 | 
						|
    TOCCancelTokenSource* receiverLife = [TOCCancelTokenSource new];
 | 
						|
    TOCCancelTokenSource* senderLife = [TOCCancelTokenSource new];
 | 
						|
    
 | 
						|
    __block NSUInteger listenerReceiveCount = 0;
 | 
						|
    __block NSUInteger listenerReceiveLength = 0;
 | 
						|
    __block NSData* listenerReceivedLast = nil;
 | 
						|
    __block NSUInteger clientReceiveCount = 0;
 | 
						|
    __block NSUInteger clientReceiveLength = 0;
 | 
						|
    __block NSData* clientReceivedLast = nil;
 | 
						|
    
 | 
						|
    in_port_t port = (in_port_t)(arc4random_uniform(40000) + 10000);
 | 
						|
    
 | 
						|
    UdpSocket* listener = [UdpSocket udpSocketToFirstSenderOnLocalPort:port];
 | 
						|
    [listener startWithHandler:[PacketHandler packetHandler:^(NSData* packet) {
 | 
						|
        listenerReceiveCount += 1;
 | 
						|
        listenerReceiveLength += packet.length;
 | 
						|
        listenerReceivedLast = packet;
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        test(false);
 | 
						|
    }] untilCancelled:receiverLife.token];
 | 
						|
    
 | 
						|
    IpEndPoint* e = [IpEndPoint ipEndPointAtAddress:IpAddress.localhost onPort:port];
 | 
						|
    UdpSocket* client = [UdpSocket udpSocketTo:e];
 | 
						|
    [client startWithHandler:[PacketHandler packetHandler:^(NSData* packet) {
 | 
						|
        clientReceiveCount += 1;
 | 
						|
        clientReceiveLength += packet.length;
 | 
						|
        clientReceivedLast = packet;
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        test(false);
 | 
						|
    }] untilCancelled:senderLife.token];
 | 
						|
    
 | 
						|
    test(!listener.isRemoteEndPointKnown);
 | 
						|
    testThrows([listener remoteEndPoint]);
 | 
						|
    test(client.isRemoteEndPointKnown);
 | 
						|
    test([client remoteEndPoint] == e);
 | 
						|
    test(listenerReceiveCount == 0);
 | 
						|
    test(clientReceiveCount == 0);
 | 
						|
    
 | 
						|
    [client send:increasingData(10)];
 | 
						|
    testChurnUntil(listenerReceiveCount > 0, 1.0);
 | 
						|
    test(clientReceiveCount == 0);
 | 
						|
    test(listener.isRemoteEndPointKnown);
 | 
						|
    test([[[[listener remoteEndPoint] address] description] isEqualToString:@"127.0.0.1"]);
 | 
						|
    test(listenerReceiveLength == 10);
 | 
						|
    test([listenerReceivedLast isEqualToData:increasingData(10)]);
 | 
						|
    
 | 
						|
    [listener send:increasingData(20)];
 | 
						|
    testChurnUntil(clientReceiveCount > 0, 1.0);
 | 
						|
    test(listenerReceiveCount == 1);
 | 
						|
    test(clientReceiveCount == 1);
 | 
						|
    test(clientReceiveLength == 20);
 | 
						|
    test([clientReceivedLast isEqualToData:increasingData(20)]);
 | 
						|
    
 | 
						|
    [receiverLife cancel];
 | 
						|
    [senderLife cancel];
 | 
						|
}
 | 
						|
-(void) testUdpFail {
 | 
						|
    TOCCancelTokenSource* life = [TOCCancelTokenSource new];
 | 
						|
    
 | 
						|
    in_port_t unusedPort = 10000 + (in_port_t)arc4random_uniform(30000);
 | 
						|
    UdpSocket* udp = [UdpSocket udpSocketTo:[IpEndPoint ipEndPointAtAddress:IpAddress.localhost onPort:unusedPort]];
 | 
						|
    __block bool failed = false;
 | 
						|
    [udp startWithHandler:[PacketHandler packetHandler:^(id packet) {
 | 
						|
        test(false);
 | 
						|
    } withErrorHandler:^(id error, id relatedInfo, bool causedTermination) {
 | 
						|
        failed = true;
 | 
						|
    }] untilCancelled:life.token];
 | 
						|
    
 | 
						|
    [udp send:increasingData(20)];
 | 
						|
    testChurnUntil(failed, 1.0);
 | 
						|
    
 | 
						|
    [life cancel];
 | 
						|
}
 | 
						|
@end
 |