1/** 2 * Copyright 2022 gRPC authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#import "TestUtils.h" 18 19#import <XCTest/XCTest.h> 20 21#import <GRPCClient/GRPCCall+ChannelArg.h> 22#import <GRPCClient/GRPCCall+Tests.h> 23 24// Utility macro to stringize preprocessor defines 25#define NSStringize_helper(x) #x 26#define NSStringize(x) @NSStringize_helper(x) 27 28// Default test flake repeat counts 29static const NSUInteger kGRPCDefaultTestFlakeRepeats = 1; 30 31// Default interop local test timeout. 32const NSTimeInterval GRPCInteropTestTimeoutDefault = 15.0; 33 34NSString *GRPCGetLocalInteropTestServerAddressPlainText() { 35 static NSString *address; 36 static dispatch_once_t onceToken; 37 dispatch_once(&onceToken, ^{ 38 address = 39 [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCAL"] ?: NSStringize(HOST_PORT_LOCAL); 40 }); 41 return address; 42} 43 44NSString *GRPCGetLocalInteropTestServerAddressSSL() { 45 static NSString *address; 46 static dispatch_once_t onceToken; 47 dispatch_once(&onceToken, ^{ 48 address = [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCALSSL"] 49 ?: NSStringize(HOST_PORT_LOCALSSL); 50 }); 51 return address; 52} 53 54NSString *GRPCGetRemoteInteropTestServerAddress() { 55 static NSString *address; 56 static dispatch_once_t onceToken; 57 dispatch_once(&onceToken, ^{ 58 address = [NSProcessInfo processInfo].environment[@"HOST_PORT_REMOTE"] 59 ?: NSStringize(HOST_PORT_REMOTE); 60 }); 61 return address; 62} 63 64// Helper function to retrieve falke repeat from env variable settings. 65static NSUInteger GRPCGetTestFlakeRepeats() { 66 static NSUInteger repeats = kGRPCDefaultTestFlakeRepeats; 67 static dispatch_once_t onceToken; 68 dispatch_once(&onceToken, ^{ 69 NSString *repeatStr = [NSProcessInfo processInfo].environment[@"FLAKE_TEST_REPEATS"]; 70 if (repeatStr != nil) { 71 repeats = [repeatStr integerValue]; 72 } 73 }); 74 return repeats; 75} 76 77void GRPCResetCallConnections() { 78#pragma clang diagnostic push 79#pragma clang diagnostic ignored "-Wdeprecated-declarations" 80 [GRPCCall closeOpenConnections]; 81#pragma clang diagnostic pop 82} 83 84void GRPCPrintInteropTestServerDebugInfo() { 85 NSLog(@"local interop env: %@ macro: %@", 86 [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCAL"], NSStringize(HOST_PORT_LOCAL)); 87 NSLog(@"local interop ssl env: %@ macro: %@", 88 [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCALSSL"], 89 NSStringize(HOST_PORT_LOCALSSL)); 90 NSLog(@"remote interop env: %@ macro: %@", 91 [NSProcessInfo processInfo].environment[@"HOST_PORT_REMOTE"], 92 NSStringize(HOST_PORT_REMOTE)); 93} 94 95BOOL GRPCTestRunWithFlakeRepeats(XCTestCase *testCase, GRPCTestRunBlock testBlock) { 96 NSInteger repeats = GRPCGetTestFlakeRepeats(); 97 NSInteger runs = 0; 98 99 while (runs < repeats) { 100 GRPCResetCallConnections(); 101 102 const BOOL isLastRun = (runs == repeats - 1); 103 __block XCTWaiterResult result; 104 __block BOOL assertionSuccess = YES; 105 106 GRPCTestWaiter waiterBlock = 107 ^(NSArray<XCTestExpectation *> *expectations, NSTimeInterval timeout) { 108 if (isLastRun) { 109 XCTWaiter *waiter = [[XCTWaiter alloc] initWithDelegate:testCase]; 110 result = [waiter waitForExpectations:expectations timeout:timeout]; 111 } else { 112 result = [XCTWaiter waitForExpectations:expectations timeout:timeout]; 113 } 114 }; 115 116 GRPCTestAssert assertBlock = ^(BOOL expressionValue, NSString *message) { 117 BOOL result = !!(expressionValue); 118 assertionSuccess = assertionSuccess && result; 119 if (isLastRun && !result) { 120 _XCTPrimitiveFail(testCase, @"%@", message); 121 } 122 }; 123 124 testBlock(waiterBlock, assertBlock); 125 126 if (result == XCTWaiterResultCompleted && assertionSuccess) { 127 return YES; 128 } 129 130 if (!isLastRun) { 131 NSLog(@"test attempt %@ failed, will retry.", NSStringize(runs)); 132 } 133 runs += 1; 134 } 135 136 return NO; 137} 138