blob: e5fcab26d86756efc0743d184b30aae621c8e0dd [file] [log] [blame]
Jorge Canizales73076842015-05-30 12:04:43 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Jorge Canizales73076842015-05-30 12:04:43 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Jorge Canizales73076842015-05-30 12:04:43 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Jorge Canizales73076842015-05-30 12:04:43 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Jorge Canizales73076842015-05-30 12:04:43 -070016 *
17 */
18
Jorge Canizales91952332015-07-31 17:50:49 -070019#import "InteropTests.h"
Jorge Canizales73076842015-05-30 12:04:43 -070020
Jorge Canizales91952332015-07-31 17:50:49 -070021#include <grpc/status.h>
Jorge Canizales73076842015-05-30 12:04:43 -070022
Makarand Dharmapurikarde733bd2016-05-25 10:38:56 -070023#import <Cronet/Cronet.h>
Jorge Canizalesfa70dac2016-04-29 19:58:52 -070024#import <GRPCClient/GRPCCall+ChannelArg.h>
Muxi Yan8e6aec52017-02-10 09:40:18 -080025#import <GRPCClient/GRPCCall+Tests.h>
26#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h>
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -070027#import <GRPCClient/GRPCCall+Cronet.h>
Jorge Canizalesc42a38e2015-06-21 14:44:25 -070028#import <ProtoRPC/ProtoRPC.h>
Jorge Canizales73076842015-05-30 12:04:43 -070029#import <RemoteTest/Messages.pbobjc.h>
30#import <RemoteTest/Test.pbobjc.h>
31#import <RemoteTest/Test.pbrpc.h>
Jorge Canizalesc42a38e2015-06-21 14:44:25 -070032#import <RxLibrary/GRXBufferedPipe.h>
33#import <RxLibrary/GRXWriter+Immediate.h>
Muxi Yana40ccd82016-11-05 21:39:44 -070034#import <grpc/support/log.h>
35#import <grpc/grpc.h>
Jorge Canizales73076842015-05-30 12:04:43 -070036
Muxi Yanb1341a32016-12-05 16:38:02 -080037#define TEST_TIMEOUT 32
38
Jorge Canizales73076842015-05-30 12:04:43 -070039// Convenience constructors for the generated proto messages:
40
41@interface RMTStreamingOutputCallRequest (Constructors)
42+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize
43 requestedResponseSize:(NSNumber *)responseSize;
44@end
45
46@implementation RMTStreamingOutputCallRequest (Constructors)
47+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize
48 requestedResponseSize:(NSNumber *)responseSize {
49 RMTStreamingOutputCallRequest *request = [self message];
50 RMTResponseParameters *parameters = [RMTResponseParameters message];
Yuchen Zengafb62f82016-06-24 19:11:08 -070051 parameters.size = responseSize.intValue;
Jorge Canizales73076842015-05-30 12:04:43 -070052 [request.responseParametersArray addObject:parameters];
53 request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
54 return request;
55}
56@end
57
58@interface RMTStreamingOutputCallResponse (Constructors)
59+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize;
60@end
61
62@implementation RMTStreamingOutputCallResponse (Constructors)
63+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize {
64 RMTStreamingOutputCallResponse * response = [self message];
65 response.payload.type = RMTPayloadType_Compressable;
66 response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
67 return response;
68}
69@end
70
Jorge Canizalesb2bd0672015-08-01 23:19:11 -070071#pragma mark Tests
72
Jorge Canizales73076842015-05-30 12:04:43 -070073@implementation InteropTests {
74 RMTTestService *_service;
75}
76
Jorge Canizales945f72c2015-07-31 17:40:59 -070077+ (NSString *)host {
Jorge Canizales91db5ac2015-10-28 14:53:38 -070078 return nil;
Jorge Canizales945f72c2015-07-31 17:40:59 -070079}
Jorge Canizalesce8ee612015-07-24 20:52:49 -070080
Muxi Yan88a41bf2017-03-08 14:54:11 -080081// This number indicates how many bytes of overhead does Protocol Buffers encoding add onto the
82// message. The number varies as different message.proto is used on different servers. The actual
83// number for each interop server is overridden in corresponding derived test classes.
Jorge Canizales9e83d7e2016-08-01 12:51:31 -070084- (int32_t)encodingOverhead {
85 return 0;
86}
87
Muxi Yanda2f0cf2017-04-09 15:34:28 -070088+ (void)setUp {
89#ifdef GRPC_COMPILE_WITH_CRONET
90 // Cronet setup
91 [Cronet setHttp2Enabled:YES];
92 [Cronet start];
93 [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]];
94#endif
95}
96
Jorge Canizales73076842015-05-30 12:04:43 -070097- (void)setUp {
Jorge Canizales6af4add2016-07-28 23:05:18 -070098 self.continueAfterFailure = NO;
99
Jorge Canizales32fde7a2016-07-29 17:31:07 -0700100 [GRPCCall resetHostSettings];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700101
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700102 _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
Jorge Canizales73076842015-05-30 12:04:43 -0700103}
104
Jorge Canizales73076842015-05-30 12:04:43 -0700105- (void)testEmptyUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700106 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700107 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
108
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700109 GPBEmpty *request = [GPBEmpty message];
Jorge Canizales73076842015-05-30 12:04:43 -0700110
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700111 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700112 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
113
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700114 id expectedResponse = [GPBEmpty message];
Jorge Canizales73076842015-05-30 12:04:43 -0700115 XCTAssertEqualObjects(response, expectedResponse);
116
117 [expectation fulfill];
118 }];
119
Muxi Yanb1341a32016-12-05 16:38:02 -0800120 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700121}
122
123- (void)testLargeUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700124 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700125 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"];
126
127 RMTSimpleRequest *request = [RMTSimpleRequest message];
128 request.responseType = RMTPayloadType_Compressable;
129 request.responseSize = 314159;
130 request.payload.body = [NSMutableData dataWithLength:271828];
131
132 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
133 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
134
135 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
136 expectedResponse.payload.type = RMTPayloadType_Compressable;
137 expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
138 XCTAssertEqualObjects(response, expectedResponse);
139
140 [expectation fulfill];
141 }];
142
Muxi Yanb1341a32016-12-05 16:38:02 -0800143 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700144}
145
Muxi Yana40ccd82016-11-05 21:39:44 -0700146- (void)testPacketCoalescing {
Muxi Yana40ccd82016-11-05 21:39:44 -0700147 XCTAssertNotNil(self.class.host);
148 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"];
149
150 RMTSimpleRequest *request = [RMTSimpleRequest message];
151 request.responseType = RMTPayloadType_Compressable;
152 request.responseSize = 10;
153 request.payload.body = [NSMutableData dataWithLength:10];
154
Muxi Yan40d7c622017-02-08 14:41:45 -0800155 [GRPCCall enableOpBatchLog:YES];
Muxi Yana40ccd82016-11-05 21:39:44 -0700156 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
157 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
158
159 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
160 expectedResponse.payload.type = RMTPayloadType_Compressable;
161 expectedResponse.payload.body = [NSMutableData dataWithLength:10];
162 XCTAssertEqualObjects(response, expectedResponse);
163
Muxi Yan1fb35b52017-03-07 17:42:25 -0800164 // The test is a success if there is a batch of exactly 3 ops (SEND_INITIAL_METADATA,
165 // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). Without packet coalescing each batch of ops contains
166 // only one op.
Muxi Yan40d7c622017-02-08 14:41:45 -0800167 NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog];
Muxi Yan1fb35b52017-03-07 17:42:25 -0800168 const NSInteger kExpectedOpBatchSize = 3;
Muxi Yan40d7c622017-02-08 14:41:45 -0800169 for (NSObject *o in opBatches) {
170 if ([o isKindOfClass:[NSArray class]]) {
171 NSArray *batch = (NSArray *)o;
Muxi Yan1fb35b52017-03-07 17:42:25 -0800172 if ([batch count] == kExpectedOpBatchSize) {
Muxi Yan40d7c622017-02-08 14:41:45 -0800173 [expectation fulfill];
174 break;
175 }
176 }
177 }
Muxi Yana40ccd82016-11-05 21:39:44 -0700178 }];
179
180 [self waitForExpectationsWithTimeout:16 handler:nil];
Muxi Yan40d7c622017-02-08 14:41:45 -0800181 [GRPCCall enableOpBatchLog:NO];
Muxi Yana40ccd82016-11-05 21:39:44 -0700182}
183
Jorge Canizales6af4add2016-07-28 23:05:18 -0700184- (void)test4MBResponsesAreAccepted {
185 XCTAssertNotNil(self.class.host);
186 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"];
187
188 RMTSimpleRequest *request = [RMTSimpleRequest message];
Jorge Canizales9e83d7e2016-08-01 12:51:31 -0700189 const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead
Jorge Canizales6af4add2016-07-28 23:05:18 -0700190 request.responseSize = kPayloadSize;
191
192 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
193 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
194 XCTAssertEqual(response.payload.body.length, kPayloadSize);
195 [expectation fulfill];
196 }];
197
Muxi Yanb1341a32016-12-05 16:38:02 -0800198 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700199}
200
201- (void)testResponsesOverMaxSizeFailWithActionableMessage {
202 XCTAssertNotNil(self.class.host);
203 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
204
205 RMTSimpleRequest *request = [RMTSimpleRequest message];
Jorge Canizales9e83d7e2016-08-01 12:51:31 -0700206 const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size
Jorge Canizales6af4add2016-07-28 23:05:18 -0700207 request.responseSize = kPayloadSize;
208
209 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
Jorge Canizalesec0743e2016-07-29 01:50:06 -0700210 // TODO(jcanizales): Catch the error and rethrow it with an actionable message:
211 // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit.
212 // - If you're developing the server, consider using response streaming, or let clients filter
213 // responses by setting a google.protobuf.FieldMask in the request:
214 // https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
Mark D. Rotha4d9ee22016-08-31 13:17:26 -0700215 XCTAssertEqualObjects(error.localizedDescription, @"Received message larger than max (4194305 vs. 4194304)");
Jorge Canizales6af4add2016-07-28 23:05:18 -0700216 [expectation fulfill];
217 }];
218
Muxi Yanb1341a32016-12-05 16:38:02 -0800219 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700220}
221
222- (void)testResponsesOver4MBAreAcceptedIfOptedIn {
223 XCTAssertNotNil(self.class.host);
224 __weak XCTestExpectation *expectation =
225 [self expectationWithDescription:@"HigherResponseSizeLimit"];
226
227 RMTSimpleRequest *request = [RMTSimpleRequest message];
228 const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB
229 request.responseSize = kPayloadSize;
230
231 [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host];
232
233 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
234 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
235 XCTAssertEqual(response.payload.body.length, kPayloadSize);
236 [expectation fulfill];
237 }];
238
Muxi Yanb1341a32016-12-05 16:38:02 -0800239 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700240}
241
Jorge Canizales73076842015-05-30 12:04:43 -0700242- (void)testClientStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700243 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700244 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"];
245
246 RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message];
247 request1.payload.body = [NSMutableData dataWithLength:27182];
248
249 RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message];
250 request2.payload.body = [NSMutableData dataWithLength:8];
251
252 RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message];
253 request3.payload.body = [NSMutableData dataWithLength:1828];
254
255 RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
256 request4.payload.body = [NSMutableData dataWithLength:45904];
257
Jorge Canizalesa8c5d962015-07-16 18:55:31 -0700258 GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
Jorge Canizales73076842015-05-30 12:04:43 -0700259
260 [_service streamingInputCallWithRequestsWriter:writer
261 handler:^(RMTStreamingInputCallResponse *response,
262 NSError *error) {
263 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
264
265 RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message];
266 expectedResponse.aggregatedPayloadSize = 74922;
267 XCTAssertEqualObjects(response, expectedResponse);
268
269 [expectation fulfill];
270 }];
271
Muxi Yanb1341a32016-12-05 16:38:02 -0800272 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700273}
274
275- (void)testServerStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700276 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700277 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"];
278
279 NSArray *expectedSizes = @[@31415, @9, @2653, @58979];
280
281 RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message];
282 for (NSNumber *size in expectedSizes) {
283 RMTResponseParameters *parameters = [RMTResponseParameters message];
Yuchen Zengafb62f82016-06-24 19:11:08 -0700284 parameters.size = [size intValue];
Jorge Canizales73076842015-05-30 12:04:43 -0700285 [request.responseParametersArray addObject:parameters];
286 }
287
288 __block int index = 0;
289 [_service streamingOutputCallWithRequest:request
murgatroid9925a26612015-06-25 11:22:23 -0700290 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700291 RMTStreamingOutputCallResponse *response,
292 NSError *error){
293 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
294 XCTAssertTrue(done || response, @"Event handler called without an event.");
295
296 if (response) {
297 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
298 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]];
299 XCTAssertEqualObjects(response, expected);
300 index += 1;
301 }
302
303 if (done) {
304 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
305 [expectation fulfill];
306 }
307 }];
308
Muxi Yanb1341a32016-12-05 16:38:02 -0800309 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700310}
311
312- (void)testPingPongRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700313 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700314 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"];
315
316 NSArray *requests = @[@27182, @8, @1828, @45904];
317 NSArray *responses = @[@31415, @9, @2653, @58979];
318
319 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
320
321 __block int index = 0;
322
323 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
324 requestedResponseSize:responses[index]];
325 [requestsBuffer writeValue:request];
326
327 [_service fullDuplexCallWithRequestsWriter:requestsBuffer
murgatroid9925a26612015-06-25 11:22:23 -0700328 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700329 RMTStreamingOutputCallResponse *response,
330 NSError *error) {
331 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
332 XCTAssertTrue(done || response, @"Event handler called without an event.");
333
334 if (response) {
335 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
336 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]];
337 XCTAssertEqualObjects(response, expected);
338 index += 1;
339 if (index < 4) {
340 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
341 requestedResponseSize:responses[index]];
342 [requestsBuffer writeValue:request];
343 } else {
344 [requestsBuffer writesFinishedWithError:nil];
345 }
346 }
347
348 if (done) {
349 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
350 [expectation fulfill];
351 }
352 }];
Muxi Yanb1341a32016-12-05 16:38:02 -0800353 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700354}
355
356- (void)testEmptyStreamRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700357 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700358 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
359 [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter]
murgatroid9925a26612015-06-25 11:22:23 -0700360 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700361 RMTStreamingOutputCallResponse *response,
362 NSError *error) {
363 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
364 XCTAssert(done, @"Unexpected response: %@", response);
365 [expectation fulfill];
366 }];
Muxi Yanb1341a32016-12-05 16:38:02 -0800367 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700368}
369
370- (void)testCancelAfterBeginRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700371 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700372 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"];
373
374 // A buffered pipe to which we never write any value acts as a writer that just hangs.
375 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
376
Yuchen Zeng3d399cb2016-06-21 11:57:46 -0700377 GRPCProtoCall *call =
378 [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
379 handler:^(RMTStreamingInputCallResponse *response,
380 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700381 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
382 [expectation fulfill];
383 }];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700384 XCTAssertEqual(call.state, GRXWriterStateNotStarted);
385
Jorge Canizales73076842015-05-30 12:04:43 -0700386 [call start];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700387 XCTAssertEqual(call.state, GRXWriterStateStarted);
388
Jorge Canizales73076842015-05-30 12:04:43 -0700389 [call cancel];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700390 XCTAssertEqual(call.state, GRXWriterStateFinished);
391
Muxi Yanb1341a32016-12-05 16:38:02 -0800392 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700393}
394
395- (void)testCancelAfterFirstResponseRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700396 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700397 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"];
Nate Kibler2d327712015-09-25 11:56:05 -0700398
Jorge Canizales73076842015-05-30 12:04:43 -0700399 // A buffered pipe to which we write a single value but never close
400 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
Nate Kibler2d327712015-09-25 11:56:05 -0700401
Jorge Canizales73076842015-05-30 12:04:43 -0700402 __block BOOL receivedResponse = NO;
Nate Kibler2d327712015-09-25 11:56:05 -0700403
Jorge Canizales73076842015-05-30 12:04:43 -0700404 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782
405 requestedResponseSize:@31415];
Nate Kibler2d327712015-09-25 11:56:05 -0700406
Jorge Canizales73076842015-05-30 12:04:43 -0700407 [requestsBuffer writeValue:request];
Nate Kibler2d327712015-09-25 11:56:05 -0700408
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -0700409 __block GRPCProtoCall *call =
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700410 [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
411 eventHandler:^(BOOL done,
412 RMTStreamingOutputCallResponse *response,
413 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700414 if (receivedResponse) {
415 XCTAssert(done, @"Unexpected extra response %@", response);
416 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
417 [expectation fulfill];
418 } else {
419 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
420 XCTAssertFalse(done, @"Finished without response");
421 XCTAssertNotNil(response);
422 receivedResponse = YES;
423 [call cancel];
424 }
425 }];
426 [call start];
Muxi Yanb1341a32016-12-05 16:38:02 -0800427 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700428}
429
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700430- (void)testRPCAfterClosingOpenConnections {
431 XCTAssertNotNil(self.class.host);
432 __weak XCTestExpectation *expectation =
433 [self expectationWithDescription:@"RPC after closing connection"];
434
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700435 GPBEmpty *request = [GPBEmpty message];
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700436
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700437 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700438 XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error);
439
Jorge Canizales00ca8ea2016-06-24 16:02:56 -0700440#pragma clang diagnostic push
441#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700442 [GRPCCall closeOpenConnections];
Jorge Canizales00ca8ea2016-06-24 16:02:56 -0700443#pragma clang diagnostic pop
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700444
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700445 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700446 XCTAssertNil(error, @"Second RPC finished with unexpected error: %@", error);
447 [expectation fulfill];
448 }];
449 }];
450
Muxi Yanb1341a32016-12-05 16:38:02 -0800451 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700452}
453
Jorge Canizales73076842015-05-30 12:04:43 -0700454@end