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.
		
		
		
		
		
			
		
			
				
	
	
		
			198 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			198 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Objective-C
		
	
| #import <XCTest/XCTest.h>
 | |
| #import "JitterQueue.h"
 | |
| #import "TestUtil.h"
 | |
| #import "Queue.h"
 | |
| 
 | |
| #define testLoggedNothing(q) test(q->messageQueue.count == 0)
 | |
| #define testLogged(q, s) test(q->messageQueue.count > 0 && [s isEqualToString:[q->messageQueue dequeue]])
 | |
| #define testLoggedArrival(q, n) testLogged(q, ([NSString stringWithFormat:@"%d", n]))
 | |
| #define testLoggedBadArrival(q, sequenceNumber, arrivalType) testLogged(q, ([NSString stringWithFormat:@"bad +%d: %d", sequenceNumber, arrivalType]))
 | |
| #define testLoggedBadDequeueOfType(q, type) testLogged(q, ([NSString stringWithFormat:@"-%d", type]))
 | |
| #define testLoggedDequeue(q, sequenceNumber, remainingCount) testLogged(q, ([NSString stringWithFormat:@"bad -%d: %d", sequenceNumber, remainingCount]))
 | |
| #define testLoggedDiscard(q, sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"discard %d,%d,%d", sequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber]))
 | |
| #define testLoggedResync(q, oldReadHeadSequenceNumber, newReadHeadSequenceNumber) testLogged(q, ([NSString stringWithFormat:@"resync %d to %d", oldReadHeadSequenceNumber,newReadHeadSequenceNumber]))
 | |
| 
 | |
| @interface JitterQueueTest : XCTestCase
 | |
| @end
 | |
| 
 | |
| @implementation JitterQueueTest
 | |
| 
 | |
| -(void) testJitterStartsFromAnyIndex {
 | |
|     JitterQueue* r1 = [JitterQueue jitterQueue];
 | |
|     JitterQueue* r2 = [JitterQueue jitterQueue];
 | |
|     
 | |
|     EncodedAudioPacket* q1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:100];
 | |
|     test(r1.count == 0);
 | |
|     test([r1 tryEnqueue:q1]);
 | |
|     test(r1.count == 1);
 | |
|     test([r1 tryDequeue] == q1);
 | |
|     test(r1.count == 0);
 | |
| 
 | |
|     EncodedAudioPacket* q2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0xFF00];
 | |
|     test(r2.count == 0);
 | |
|     test([r2 tryEnqueue:q2]);
 | |
|     test(r2.count == 1);
 | |
|     test([r2 tryDequeue] == q2);
 | |
|     test(r2.count == 0);
 | |
| }
 | |
| -(void) testJitterAdvances {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     for (uint16_t i = 0; i < 10; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i];
 | |
|         test([r tryEnqueue:q]);
 | |
|         test(r.count == i+1);
 | |
|     }
 | |
|     
 | |
|     for (uint16_t i = 0; i < 10; i++) {
 | |
|         test([[r tryDequeue] sequenceNumber] == i);
 | |
|         test(r.count == 9-i);
 | |
|     }
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterAdvancesWithHoles {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     for (uint16_t i = 0; i < 10; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i*2+1];
 | |
|         test([r tryEnqueue:q]);
 | |
|     }
 | |
|     
 | |
|     for (uint16_t i = 0; i < 20; i++) {
 | |
|         EncodedAudioPacket* p = [r tryDequeue];
 | |
|         test((p == nil) == (i%2==1));
 | |
|         test(p == nil || [p sequenceNumber] == i+1);
 | |
|     }
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterAdvancesIncrementally {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     for (uint16_t i = 0; i < 20; i++) {
 | |
|         for (uint16_t j = 0; j < 2; j++) {
 | |
|             EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:i*2+j];
 | |
|             test([r tryEnqueue:q]);
 | |
|         }
 | |
|  
 | |
|         test([[r tryDequeue] sequenceNumber] == i);
 | |
|     }
 | |
|     test([[r tryDequeue] sequenceNumber] == 20);
 | |
| }
 | |
| -(void) testJitterQueueRejectsDuplicateSequenceNumbers {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
| 
 | |
|     EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0];
 | |
|     test([r tryEnqueue:p]);
 | |
| 
 | |
|     for (uint16_t i = 0; i < 10; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0];
 | |
|         test(![r tryEnqueue:q]);
 | |
|     }
 | |
|     
 | |
|     test([r tryDequeue] == p);
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterQueueRejectsOldSequenceNumbers {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:50];
 | |
|     test([r tryEnqueue:p]);
 | |
|     
 | |
|     for (uint16_t i = 1; i < 10; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:50 - i];
 | |
|         test(![r tryEnqueue:q]);
 | |
|     }
 | |
|     
 | |
|     test([r tryDequeue] == p);
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterQueueRejectsFarOffSequenceNumbers {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0];
 | |
|     test([r tryEnqueue:p]);
 | |
|     
 | |
|     for (uint16_t i = 0; i < 10; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0x7000+i];
 | |
|         test(![r tryEnqueue:q]);
 | |
|     }
 | |
|     
 | |
|     test([r tryDequeue] == p);
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterQueueResyncsSequenceNumber {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     EncodedAudioPacket* p = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:1];
 | |
|     test([r tryEnqueue:p]);
 | |
|     test([r tryDequeue] == p);
 | |
| 
 | |
|     EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:0];
 | |
|     test(![r tryEnqueue:q]);
 | |
| 
 | |
|     // cause desync to be detected
 | |
|     for (uint16_t i = 0; i < 5000; i++) {
 | |
|         test([r tryDequeue] == nil);
 | |
|     }
 | |
|     
 | |
|     // resync at q, before p's index
 | |
|     test([r tryEnqueue:q]);
 | |
|     test([r tryDequeue] == q);
 | |
| }
 | |
| -(void) testLoopAround {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     
 | |
|     for (int i = 0; i < 1 << 17; i++) {
 | |
|         EncodedAudioPacket* q = [EncodedAudioPacket encodedAudioPacketWithAudioData:[NSData dataWithLength:1] andSequenceNumber:(uint16_t)(i & 0xFFFF)];
 | |
|         test([r tryEnqueue:q]);
 | |
|         test([r tryDequeue] == q);
 | |
|     }
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| -(void) testJitterQueueAvoidsRacingAhead {
 | |
|     JitterQueue* r = [JitterQueue jitterQueue];
 | |
|     EncodedAudioPacket* p1 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:0];
 | |
|     EncodedAudioPacket* p2 = [EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:1];
 | |
| 
 | |
|     test([r tryEnqueue:p1]);
 | |
|     test([r tryDequeue] == p1);
 | |
|     
 | |
|     test([r tryDequeue] == nil);
 | |
|     
 | |
|     test([r tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(1) andSequenceNumber:10]]);
 | |
|     test([r tryDequeue] == nil);
 | |
|     
 | |
|     test([r tryEnqueue:p2]);
 | |
|     test([r tryDequeue] == p2);
 | |
| 
 | |
|     test([r tryDequeue] == nil);
 | |
| }
 | |
| 
 | |
| -(void) testJitterQueueMeasurement {
 | |
|     JitterQueue* q = [JitterQueue jitterQueue];
 | |
|     [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:1]];
 | |
|     test([q currentBufferDepth] == 0);
 | |
|     [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:2]];
 | |
|     test([q currentBufferDepth] == 1);
 | |
|     [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:4]];
 | |
|     test([q currentBufferDepth] == 3);
 | |
|     [q tryDequeue];
 | |
|     test([q currentBufferDepth] == 2);
 | |
|     [q tryDequeue];
 | |
|     test([q currentBufferDepth] == 1);
 | |
|     [q tryDequeue];
 | |
|     test([q currentBufferDepth] == 0);
 | |
|     [q tryDequeue];
 | |
|     test([q currentBufferDepth] == -1);
 | |
|     [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:8]];
 | |
|     test([q currentBufferDepth] == 3);
 | |
|     
 | |
|     // resyncs to 0
 | |
|     for (int i = 0; i < 500; i++) {
 | |
|         [q tryDequeue];
 | |
|     }
 | |
|     [q tryEnqueue:[EncodedAudioPacket encodedAudioPacketWithAudioData:increasingData(20) andSequenceNumber:9000]];
 | |
|     test([q currentBufferDepth] == 0);
 | |
| }
 | |
| @end
 |