/** * Copyright 2022 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #import "TestUtils.h" #import #import #import // Utility macro to stringize preprocessor defines #define NSStringize_helper(x) #x #define NSStringize(x) @NSStringize_helper(x) // Default test flake repeat counts static const NSUInteger kGRPCDefaultTestFlakeRepeats = 1; // Default interop local test timeout. const NSTimeInterval GRPCInteropTestTimeoutDefault = 15.0; NSString *GRPCGetLocalInteropTestServerAddressPlainText() { static NSString *address; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ address = [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCAL"] ?: NSStringize(HOST_PORT_LOCAL); }); return address; } NSString *GRPCGetLocalInteropTestServerAddressSSL() { static NSString *address; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ address = [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCALSSL"] ?: NSStringize(HOST_PORT_LOCALSSL); }); return address; } NSString *GRPCGetRemoteInteropTestServerAddress() { static NSString *address; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ address = [NSProcessInfo processInfo].environment[@"HOST_PORT_REMOTE"] ?: NSStringize(HOST_PORT_REMOTE); }); return address; } // Helper function to retrieve falke repeat from env variable settings. static NSUInteger GRPCGetTestFlakeRepeats() { static NSUInteger repeats = kGRPCDefaultTestFlakeRepeats; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSString *repeatStr = [NSProcessInfo processInfo].environment[@"FLAKE_TEST_REPEATS"]; if (repeatStr != nil) { repeats = [repeatStr integerValue]; } }); return repeats; } void GRPCResetCallConnections() { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" [GRPCCall closeOpenConnections]; #pragma clang diagnostic pop } void GRPCPrintInteropTestServerDebugInfo() { NSLog(@"local interop env: %@ macro: %@", [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCAL"], NSStringize(HOST_PORT_LOCAL)); NSLog(@"local interop ssl env: %@ macro: %@", [NSProcessInfo processInfo].environment[@"HOST_PORT_LOCALSSL"], NSStringize(HOST_PORT_LOCALSSL)); NSLog(@"remote interop env: %@ macro: %@", [NSProcessInfo processInfo].environment[@"HOST_PORT_REMOTE"], NSStringize(HOST_PORT_REMOTE)); } BOOL GRPCTestRunWithFlakeRepeats(XCTestCase *testCase, GRPCTestRunBlock testBlock) { NSInteger repeats = GRPCGetTestFlakeRepeats(); NSInteger runs = 0; while (runs < repeats) { GRPCResetCallConnections(); const BOOL isLastRun = (runs == repeats - 1); __block XCTWaiterResult result; __block BOOL assertionSuccess = YES; GRPCTestWaiter waiterBlock = ^(NSArray *expectations, NSTimeInterval timeout) { if (isLastRun) { XCTWaiter *waiter = [[XCTWaiter alloc] initWithDelegate:testCase]; result = [waiter waitForExpectations:expectations timeout:timeout]; } else { result = [XCTWaiter waitForExpectations:expectations timeout:timeout]; } }; GRPCTestAssert assertBlock = ^(BOOL expressionValue, NSString *message) { BOOL result = !!(expressionValue); assertionSuccess = assertionSuccess && result; if (isLastRun && !result) { _XCTPrimitiveFail(testCase, @"%@", message); } }; testBlock(waiterBlock, assertBlock); if (result == XCTWaiterResultCompleted && assertionSuccess) { return YES; } if (!isLastRun) { NSLog(@"test attempt %@ failed, will retry.", NSStringize(runs)); } runs += 1; } return NO; }