1*cc02d7e2SAndroid Build Coastguard Worker/* 2*cc02d7e2SAndroid Build Coastguard Worker * 3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2018 gRPC authors. 4*cc02d7e2SAndroid Build Coastguard Worker * 5*cc02d7e2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker * You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker * 9*cc02d7e2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker * 11*cc02d7e2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker * limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker * 17*cc02d7e2SAndroid Build Coastguard Worker */ 18*cc02d7e2SAndroid Build Coastguard Worker 19*cc02d7e2SAndroid Build Coastguard Worker#import <XCTest/XCTest.h> 20*cc02d7e2SAndroid Build Coastguard Worker 21*cc02d7e2SAndroid Build Coastguard Worker#import <Cronet/Cronet.h> 22*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCCallOptions.h> 23*cc02d7e2SAndroid Build Coastguard Worker#import <RxLibrary/GRXBufferedPipe.h> 24*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Messages.pbobjc.h" 25*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Test.pbobjc.h" 26*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Test.pbrpc.h" 27*cc02d7e2SAndroid Build Coastguard Worker 28*cc02d7e2SAndroid Build Coastguard Worker#import "../Common/TestUtils.h" 29*cc02d7e2SAndroid Build Coastguard Worker#import "../ConfigureCronet.h" 30*cc02d7e2SAndroid Build Coastguard Worker#import "InteropTestsBlockCallbacks.h" 31*cc02d7e2SAndroid Build Coastguard Worker 32*cc02d7e2SAndroid Build Coastguard Worker#define NSStringize_helper(x) #x 33*cc02d7e2SAndroid Build Coastguard Worker#define NSStringize(x) @NSStringize_helper(x) 34*cc02d7e2SAndroid Build Coastguard Worker 35*cc02d7e2SAndroid Build Coastguard Workerstatic const NSTimeInterval TEST_TIMEOUT = 8000; 36*cc02d7e2SAndroid Build Coastguard Worker 37*cc02d7e2SAndroid Build Coastguard Worker@interface RMTStreamingOutputCallRequest (Constructors) 38*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize 39*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:(NSNumber *)responseSize; 40*cc02d7e2SAndroid Build Coastguard Worker@end 41*cc02d7e2SAndroid Build Coastguard Worker 42*cc02d7e2SAndroid Build Coastguard Worker@implementation RMTStreamingOutputCallRequest (Constructors) 43*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize 44*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:(NSNumber *)responseSize { 45*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingOutputCallRequest *request = [self message]; 46*cc02d7e2SAndroid Build Coastguard Worker RMTResponseParameters *parameters = [RMTResponseParameters message]; 47*cc02d7e2SAndroid Build Coastguard Worker parameters.size = responseSize.intValue; 48*cc02d7e2SAndroid Build Coastguard Worker [request.responseParametersArray addObject:parameters]; 49*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; 50*cc02d7e2SAndroid Build Coastguard Worker return request; 51*cc02d7e2SAndroid Build Coastguard Worker} 52*cc02d7e2SAndroid Build Coastguard Worker@end 53*cc02d7e2SAndroid Build Coastguard Worker 54*cc02d7e2SAndroid Build Coastguard Worker@interface RMTStreamingOutputCallResponse (Constructors) 55*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; 56*cc02d7e2SAndroid Build Coastguard Worker@end 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard Worker@implementation RMTStreamingOutputCallResponse (Constructors) 59*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { 60*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingOutputCallResponse *response = [self message]; 61*cc02d7e2SAndroid Build Coastguard Worker response.payload.type = RMTPayloadType_Compressable; 62*cc02d7e2SAndroid Build Coastguard Worker response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; 63*cc02d7e2SAndroid Build Coastguard Worker return response; 64*cc02d7e2SAndroid Build Coastguard Worker} 65*cc02d7e2SAndroid Build Coastguard Worker@end 66*cc02d7e2SAndroid Build Coastguard Worker 67*cc02d7e2SAndroid Build Coastguard Worker@interface InteropTestsMultipleChannels : XCTestCase 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Worker@end 70*cc02d7e2SAndroid Build Coastguard Worker 71*cc02d7e2SAndroid Build Coastguard Workerdispatch_once_t initCronet; 72*cc02d7e2SAndroid Build Coastguard Worker 73*cc02d7e2SAndroid Build Coastguard Worker@implementation InteropTestsMultipleChannels { 74*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *_remoteService; 75*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *_remoteCronetService; 76*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *_localCleartextService; 77*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *_localSSLService; 78*cc02d7e2SAndroid Build Coastguard Worker} 79*cc02d7e2SAndroid Build Coastguard Worker 80*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 81*cc02d7e2SAndroid Build Coastguard Worker [super setUp]; 82*cc02d7e2SAndroid Build Coastguard Worker 83*cc02d7e2SAndroid Build Coastguard Worker self.continueAfterFailure = NO; 84*cc02d7e2SAndroid Build Coastguard Worker 85*cc02d7e2SAndroid Build Coastguard Worker _remoteService = [RMTTestService serviceWithHost:GRPCGetRemoteInteropTestServerAddress() 86*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 87*cc02d7e2SAndroid Build Coastguard Worker configureCronet(/*enable_netlog=*/false); 88*cc02d7e2SAndroid Build Coastguard Worker 89*cc02d7e2SAndroid Build Coastguard Worker // Default stack with remote host 90*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 91*cc02d7e2SAndroid Build Coastguard Worker options.transportType = GRPCTransportTypeCronet; 92*cc02d7e2SAndroid Build Coastguard Worker // Cronet stack with remote host 93*cc02d7e2SAndroid Build Coastguard Worker _remoteCronetService = [RMTTestService serviceWithHost:GRPCGetRemoteInteropTestServerAddress() 94*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 95*cc02d7e2SAndroid Build Coastguard Worker 96*cc02d7e2SAndroid Build Coastguard Worker // Local stack with no SSL 97*cc02d7e2SAndroid Build Coastguard Worker options = [[GRPCMutableCallOptions alloc] init]; 98*cc02d7e2SAndroid Build Coastguard Worker options.transportType = GRPCTransportTypeInsecure; 99*cc02d7e2SAndroid Build Coastguard Worker _localCleartextService = 100*cc02d7e2SAndroid Build Coastguard Worker [RMTTestService serviceWithHost:GRPCGetLocalInteropTestServerAddressPlainText() 101*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 102*cc02d7e2SAndroid Build Coastguard Worker 103*cc02d7e2SAndroid Build Coastguard Worker // Local stack with SSL 104*cc02d7e2SAndroid Build Coastguard Worker NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 105*cc02d7e2SAndroid Build Coastguard Worker NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" 106*cc02d7e2SAndroid Build Coastguard Worker ofType:@"pem"]; 107*cc02d7e2SAndroid Build Coastguard Worker NSError *error = nil; 108*cc02d7e2SAndroid Build Coastguard Worker NSString *certs = [NSString stringWithContentsOfFile:certsPath 109*cc02d7e2SAndroid Build Coastguard Worker encoding:NSUTF8StringEncoding 110*cc02d7e2SAndroid Build Coastguard Worker error:&error]; 111*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 112*cc02d7e2SAndroid Build Coastguard Worker 113*cc02d7e2SAndroid Build Coastguard Worker options = [[GRPCMutableCallOptions alloc] init]; 114*cc02d7e2SAndroid Build Coastguard Worker options.transportType = GRPCTransportTypeChttp2BoringSSL; 115*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = certs; 116*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = @"foo.test.google.fr"; 117*cc02d7e2SAndroid Build Coastguard Worker _localSSLService = [RMTTestService serviceWithHost:GRPCGetLocalInteropTestServerAddressSSL() 118*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 119*cc02d7e2SAndroid Build Coastguard Worker} 120*cc02d7e2SAndroid Build Coastguard Worker 121*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyUnaryRPC { 122*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"]; 123*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectCronetRemote = 124*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Remote RPC finish"]; 125*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectCleartext = 126*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Remote RPC finish"]; 127*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"]; 128*cc02d7e2SAndroid Build Coastguard Worker 129*cc02d7e2SAndroid Build Coastguard Worker GPBEmpty *request = [GPBEmpty message]; 130*cc02d7e2SAndroid Build Coastguard Worker 131*cc02d7e2SAndroid Build Coastguard Worker void (^messageHandler)(id message) = ^(id message) { 132*cc02d7e2SAndroid Build Coastguard Worker id expectedResponse = [GPBEmpty message]; 133*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(message, expectedResponse); 134*cc02d7e2SAndroid Build Coastguard Worker }; 135*cc02d7e2SAndroid Build Coastguard Worker 136*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *callRemote = [_remoteService 137*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 138*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] 139*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 140*cc02d7e2SAndroid Build Coastguard Worker messageCallback:messageHandler 141*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 142*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 143*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 144*cc02d7e2SAndroid Build Coastguard Worker [expectRemote fulfill]; 145*cc02d7e2SAndroid Build Coastguard Worker } 146*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 147*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 148*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *callCronet = [_remoteCronetService 149*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 150*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] 151*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 152*cc02d7e2SAndroid Build Coastguard Worker messageCallback:messageHandler 153*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 154*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 155*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 156*cc02d7e2SAndroid Build Coastguard Worker [expectCronetRemote fulfill]; 157*cc02d7e2SAndroid Build Coastguard Worker } 158*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 159*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 160*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *callCleartext = [_localCleartextService 161*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 162*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] 163*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 164*cc02d7e2SAndroid Build Coastguard Worker messageCallback:messageHandler 165*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 166*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 167*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 168*cc02d7e2SAndroid Build Coastguard Worker [expectCleartext fulfill]; 169*cc02d7e2SAndroid Build Coastguard Worker } 170*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 171*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 172*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *callSSL = [_localSSLService 173*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 174*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] 175*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 176*cc02d7e2SAndroid Build Coastguard Worker messageCallback:messageHandler 177*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 178*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 179*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 180*cc02d7e2SAndroid Build Coastguard Worker [expectSSL fulfill]; 181*cc02d7e2SAndroid Build Coastguard Worker } 182*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 183*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 184*cc02d7e2SAndroid Build Coastguard Worker [callRemote start]; 185*cc02d7e2SAndroid Build Coastguard Worker [callCronet start]; 186*cc02d7e2SAndroid Build Coastguard Worker [callCleartext start]; 187*cc02d7e2SAndroid Build Coastguard Worker [callSSL start]; 188*cc02d7e2SAndroid Build Coastguard Worker 189*cc02d7e2SAndroid Build Coastguard Worker [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; 190*cc02d7e2SAndroid Build Coastguard Worker} 191*cc02d7e2SAndroid Build Coastguard Worker 192*cc02d7e2SAndroid Build Coastguard Worker- (void)testFullDuplexRPC { 193*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"]; 194*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectCronetRemote = 195*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Remote RPC finish"]; 196*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectCleartext = 197*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Remote RPC finish"]; 198*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"]; 199*cc02d7e2SAndroid Build Coastguard Worker 200*cc02d7e2SAndroid Build Coastguard Worker NSArray *requestSizes = @[ @100, @101, @102, @103 ]; 201*cc02d7e2SAndroid Build Coastguard Worker NSArray *responseSizes = @[ @104, @105, @106, @107 ]; 202*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([requestSizes count], [responseSizes count]); 203*cc02d7e2SAndroid Build Coastguard Worker NSUInteger kRounds = [requestSizes count]; 204*cc02d7e2SAndroid Build Coastguard Worker NSMutableArray<GRPCStreamingProtoCall *> *calls = [NSMutableArray arrayWithCapacity:4]; 205*cc02d7e2SAndroid Build Coastguard Worker 206*cc02d7e2SAndroid Build Coastguard Worker NSMutableArray *requests = [NSMutableArray arrayWithCapacity:kRounds]; 207*cc02d7e2SAndroid Build Coastguard Worker NSMutableArray *responses = [NSMutableArray arrayWithCapacity:kRounds]; 208*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kRounds; i++) { 209*cc02d7e2SAndroid Build Coastguard Worker requests[i] = [RMTStreamingOutputCallRequest messageWithPayloadSize:requestSizes[i] 210*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responseSizes[i]]; 211*cc02d7e2SAndroid Build Coastguard Worker responses[i] = [RMTStreamingOutputCallResponse messageWithPayloadSize:responseSizes[i]]; 212*cc02d7e2SAndroid Build Coastguard Worker } 213*cc02d7e2SAndroid Build Coastguard Worker 214*cc02d7e2SAndroid Build Coastguard Worker __block NSMutableArray *steps = [NSMutableArray arrayWithCapacity:4]; 215*cc02d7e2SAndroid Build Coastguard Worker __block NSMutableArray *requestsBuffers = [NSMutableArray arrayWithCapacity:4]; 216*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) { 217*cc02d7e2SAndroid Build Coastguard Worker steps[i] = [NSNumber numberWithUnsignedInteger:0]; 218*cc02d7e2SAndroid Build Coastguard Worker requestsBuffers[i] = [[GRXBufferedPipe alloc] init]; 219*cc02d7e2SAndroid Build Coastguard Worker [requestsBuffers[i] writeValue:requests[0]]; 220*cc02d7e2SAndroid Build Coastguard Worker } 221*cc02d7e2SAndroid Build Coastguard Worker 222*cc02d7e2SAndroid Build Coastguard Worker void (^handler)(NSUInteger index, id message) = ^(NSUInteger index, id message) { 223*cc02d7e2SAndroid Build Coastguard Worker NSUInteger step = [steps[index] unsignedIntegerValue]; 224*cc02d7e2SAndroid Build Coastguard Worker step++; 225*cc02d7e2SAndroid Build Coastguard Worker steps[index] = [NSNumber numberWithUnsignedInteger:step]; 226*cc02d7e2SAndroid Build Coastguard Worker if (step < kRounds) { 227*cc02d7e2SAndroid Build Coastguard Worker [calls[index] writeMessage:requests[step]]; 228*cc02d7e2SAndroid Build Coastguard Worker } else { 229*cc02d7e2SAndroid Build Coastguard Worker [calls[index] finish]; 230*cc02d7e2SAndroid Build Coastguard Worker } 231*cc02d7e2SAndroid Build Coastguard Worker }; 232*cc02d7e2SAndroid Build Coastguard Worker 233*cc02d7e2SAndroid Build Coastguard Worker calls[0] = [_remoteService 234*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 235*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 236*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 237*cc02d7e2SAndroid Build Coastguard Worker handler(0, message); 238*cc02d7e2SAndroid Build Coastguard Worker } 239*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 240*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 241*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 242*cc02d7e2SAndroid Build Coastguard Worker [expectRemote fulfill]; 243*cc02d7e2SAndroid Build Coastguard Worker } 244*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 245*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 246*cc02d7e2SAndroid Build Coastguard Worker calls[1] = [_remoteCronetService 247*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 248*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 249*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 250*cc02d7e2SAndroid Build Coastguard Worker handler(1, message); 251*cc02d7e2SAndroid Build Coastguard Worker } 252*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 253*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 254*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 255*cc02d7e2SAndroid Build Coastguard Worker [expectCronetRemote fulfill]; 256*cc02d7e2SAndroid Build Coastguard Worker } 257*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 258*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 259*cc02d7e2SAndroid Build Coastguard Worker calls[2] = [_localCleartextService 260*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 261*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 262*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 263*cc02d7e2SAndroid Build Coastguard Worker handler(2, message); 264*cc02d7e2SAndroid Build Coastguard Worker } 265*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 266*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 267*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 268*cc02d7e2SAndroid Build Coastguard Worker [expectCleartext fulfill]; 269*cc02d7e2SAndroid Build Coastguard Worker } 270*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 271*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 272*cc02d7e2SAndroid Build Coastguard Worker calls[3] = [_localSSLService 273*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 274*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 275*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 276*cc02d7e2SAndroid Build Coastguard Worker handler(3, message); 277*cc02d7e2SAndroid Build Coastguard Worker } 278*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 279*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 280*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error); 281*cc02d7e2SAndroid Build Coastguard Worker [expectSSL fulfill]; 282*cc02d7e2SAndroid Build Coastguard Worker } 283*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:nil] 284*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 285*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) { 286*cc02d7e2SAndroid Build Coastguard Worker [calls[i] start]; 287*cc02d7e2SAndroid Build Coastguard Worker [calls[i] writeMessage:requests[0]]; 288*cc02d7e2SAndroid Build Coastguard Worker } 289*cc02d7e2SAndroid Build Coastguard Worker 290*cc02d7e2SAndroid Build Coastguard Worker [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; 291*cc02d7e2SAndroid Build Coastguard Worker} 292*cc02d7e2SAndroid Build Coastguard Worker 293*cc02d7e2SAndroid Build Coastguard Worker@end 294