#import #import "TestUtil.h" #import "PriorityQueue.h" #import "Util.h" @interface PriorityQueueTest : XCTestCase @end NSArray* RandomPermutation(uint32_t count); NSArray* Permutations(uint32_t count); NSArray* RandomPermutation(uint32_t count) { uint32_t d[count]; for (uint32_t i = 0; i < count; i++) d[i] = i; for (uint32_t i = 0; i < count; i++) { uint32_t j = arc4random_uniform(count - i) + i; uint32_t t = d[i]; d[i] = d[j]; d[j] = t; } NSMutableArray* r = [NSMutableArray array]; for (uint32_t i = 0; i < count; i++) [r addObject:@(d[i])]; return r; } NSArray* Permutations(uint32_t count) { if (count == 0) return @[]; NSMutableArray* r = [NSMutableArray array]; for (NSArray* s in Permutations(count - 1)) { for (uint32_t e = 0; e < count; e++) { NSMutableArray* a = [NSMutableArray array]; [a addObject:@(e)]; for (NSNumber* x in s) { [a addObject:[x unsignedIntegerValue] < e ? x : @([x unsignedIntegerValue] + 1)]; } [r addObject:a]; } } return r; } @implementation PriorityQueueTest -(void) testTrivialPrioritizing { PriorityQueue* q = [PriorityQueue priorityQueueAscendingWithComparator:^(NSNumber* obj1, NSNumber* obj2){ return [obj1 compare:obj2]; }]; test(q.count == 0); testThrows(q.peek); testThrows([q dequeue]); [q enqueue:@1]; [q enqueue:@2]; [q enqueue:@3]; test(q.count == 3); test([q.peek intValue] == 1); test([[q dequeue] intValue] == 1); test([q.peek intValue] == 2); test([[q dequeue] intValue] == 2); test([q.peek intValue] == 3); test([[q dequeue] intValue] == 3); testThrows(q.peek); testThrows([q dequeue]); } -(void) testOrdersByComparatorInverse { PriorityQueue* q = [PriorityQueue priorityQueueAscendingWithComparator:^(NSNumber* obj1, NSNumber* obj2){ return [obj2 compare:obj1]; }]; [q enqueue:@1]; [q enqueue:@2]; [q enqueue:@3]; test([[q dequeue] intValue] == 3); test([[q dequeue] intValue] == 2); test([[q dequeue] intValue] == 1); } -(void) testSortsAllSmallPermutations { const uint32_t N = 7; for (NSArray* permutation in Permutations(N)) { PriorityQueue* q = [PriorityQueue priorityQueueAscendingWithComparator:^(NSNumber* obj1, NSNumber* obj2){ return [obj1 compare:obj2]; }]; for (NSNumber* e in permutation) { [q enqueue:e]; } // dequeues in order for (uint32_t i = 0; i < N; i++) { test(q.count == N - i); test([[q dequeue] unsignedIntegerValue] == i); } test(q.count == 0); } } -(void) testSortsRandomLargePermutations { const uint32_t Size = 500; const uint32_t Repetitions = 50; for (uint32_t repeat = 0; repeat < Repetitions; repeat++) { PriorityQueue* q = [PriorityQueue priorityQueueAscendingWithComparator:^(NSNumber* obj1, NSNumber* obj2){ return [obj1 compare:obj2]; }]; NSArray* permutation = RandomPermutation(Size); for (NSNumber* e in permutation) { [q enqueue:e]; } // dequeues in order for (uint32_t i = 0; i < Size; i++) { test(q.count == Size - i); test([[q dequeue] unsignedIntegerValue] == i); } test(q.count == 0); } } @end