xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/tests/InteropTests/InteropTestsMultipleChannels.m (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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