SRAutobahnTests.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //
  2. // Copyright 2012 Square Inc.
  3. // Portions Copyright (c) 2016-present, Facebook, Inc.
  4. //
  5. // All rights reserved.
  6. //
  7. // This source code is licensed under the BSD-style license found in the
  8. // LICENSE file in the root directory of this source tree. An additional grant
  9. // of patent rights can be found in the PATENTS file in the same directory.
  10. //
  11. @import XCTest;
  12. @import ObjectiveC;
  13. #import <SocketRocket/SRWebSocket.h>
  14. #import "SRTWebSocketOperation.h"
  15. #import "SRAutobahnOperation.h"
  16. #import "SRAutobahnUtilities.h"
  17. @interface SRAutobahnTests : XCTestCase
  18. @end
  19. @implementation SRAutobahnTests
  20. ///--------------------------------------
  21. #pragma mark - Init
  22. ///--------------------------------------
  23. /**
  24. This method is called if Xcode is targeting a specific test or a set of them.
  25. If you change this method - please make sure you test this behavior in Xcode by running all tests, then running 1+ test.
  26. */
  27. + (instancetype)testCaseWithSelector:(SEL)selector
  28. {
  29. NSArray<NSInvocation *> *invocations = [self testInvocations];
  30. for (NSInvocation *invocation in invocations) {
  31. if (invocation.selector == selector) {
  32. return [super testCaseWithSelector:selector];
  33. }
  34. }
  35. return nil;
  36. }
  37. ///--------------------------------------
  38. #pragma mark - Setup
  39. ///--------------------------------------
  40. /**
  41. This method is called by xctest to figure out all the tests that are available.
  42. All the selector names are also reported back to Xcode and displayed in Test Navigator/Console.
  43. */
  44. + (NSArray<NSInvocation *> *)testInvocations
  45. {
  46. __block NSArray<NSInvocation *> *array = nil;
  47. static dispatch_once_t onceToken;
  48. dispatch_once(&onceToken, ^{
  49. NSMutableArray<NSInvocation *> *invocations = [NSMutableArray array];
  50. for (NSUInteger i = 1; i <= SRAutobahnTestCaseCount(); i++) {
  51. NSDictionary *caseInfo = SRAutobahnTestCaseInfo(i);
  52. NSString *identifier = caseInfo[@"id"];
  53. NSInvocation *invocation = [self invocationWithCaseNumber:i identifier:identifier];
  54. [invocations addObject:invocation];
  55. }
  56. array = [invocations sortedArrayUsingComparator:^NSComparisonResult(NSInvocation *_Nonnull obj1, NSInvocation *_Nonnull obj2) {
  57. return [NSStringFromSelector(obj1.selector) compare:NSStringFromSelector(obj2.selector) options:NSNumericSearch];
  58. }];
  59. });
  60. return array;
  61. }
  62. + (NSInvocation *)invocationWithCaseNumber:(NSUInteger)caseNumber identifier:(NSString *)identifier
  63. {
  64. SEL selector = [self addInstanceMethodForTestCaseNumber:caseNumber identifier:identifier];
  65. NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector];
  66. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
  67. invocation.selector = selector;
  68. return invocation;
  69. }
  70. + (SEL)addInstanceMethodForTestCaseNumber:(NSInteger)caseNumber identifier:(NSString *)identifier
  71. {
  72. NSString *selectorName = [NSString stringWithFormat:@"Case #%@", identifier];
  73. SEL selector = NSSelectorFromString(selectorName);
  74. IMP implementation = imp_implementationWithBlock(^(SRAutobahnTests *sself) {
  75. [sself performTestWithCaseNumber:caseNumber identifier:identifier];
  76. });
  77. NSString *typeString = [NSString stringWithFormat:@"%s%s%s", @encode(id), @encode(id), @encode(SEL)];
  78. class_addMethod(self, selector, implementation, typeString.UTF8String);
  79. return selector;
  80. }
  81. ///--------------------------------------
  82. #pragma mark - Teardown
  83. ///--------------------------------------
  84. + (void)tearDown
  85. {
  86. [self updateReports];
  87. [super tearDown];
  88. }
  89. + (void)updateReports
  90. {
  91. SRAutobahnOperation *operation = SRAutobahnTestUpdateReportsOperation(SRAutobahnTestServerURL(), SRAutobahnTestAgentName());
  92. [operation start];
  93. NSAssert([operation waitUntilFinishedWithTimeout:60], @"Timed out on updating reports.");
  94. NSAssert(!operation.error, @"Updating the report should not have errored %@", operation.error);
  95. }
  96. ///--------------------------------------
  97. #pragma mark - Test
  98. ///--------------------------------------
  99. - (void)performTestWithCaseNumber:(NSInteger)caseNumber identifier:(NSString *)identifier
  100. {
  101. NSURL *serverURL = SRAutobahnTestServerURL();
  102. NSString *agent = SRAutobahnTestAgentName();
  103. NSOperationQueue *testQueue = [[NSOperationQueue alloc] init];
  104. testQueue.maxConcurrentOperationCount = 1;
  105. SRAutobahnOperation *testOp = SRAutobahnTestOperation(serverURL, caseNumber, agent);
  106. [testQueue addOperation:testOp];
  107. __block NSDictionary *resultInfo = nil;
  108. SRAutobahnOperation *resultOp = SRAutobahnTestResultOperation(serverURL, caseNumber, agent, ^(NSDictionary * _Nullable result) {
  109. resultInfo = result;
  110. });
  111. [resultOp addDependency:testOp];
  112. [testQueue addOperation:resultOp];
  113. XCTAssertTrue([resultOp waitUntilFinishedWithTimeout:60 * 5], @"Test operation timed out.");
  114. XCTAssertTrue(!testOp.error, @"Test operation should not have failed");
  115. if (!SRAutobahnIsValidResultBehavior(identifier, resultInfo[@"behavior"])) {
  116. XCTFail(@"Invalid test behavior %@ for %@.", resultInfo[@"behavior"], identifier);
  117. }
  118. }
  119. @end