blob: 0be8669aa2f6967a3019d193a762407f6a569d4f [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 {
Muxi Yan4b947d32017-11-30 09:36:29 -080089 NSLog(@"InteropTest Started, class: %@", [[self class] description]);
Muxi Yanda2f0cf2017-04-09 15:34:28 -070090#ifdef GRPC_COMPILE_WITH_CRONET
91 // Cronet setup
92 [Cronet setHttp2Enabled:YES];
93 [Cronet start];
94 [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]];
95#endif
96}
97
Jorge Canizales73076842015-05-30 12:04:43 -070098- (void)setUp {
Jorge Canizales6af4add2016-07-28 23:05:18 -070099 self.continueAfterFailure = NO;
100
Jorge Canizales32fde7a2016-07-29 17:31:07 -0700101 [GRPCCall resetHostSettings];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700102
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700103 _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
Jorge Canizales73076842015-05-30 12:04:43 -0700104}
105
Jorge Canizales73076842015-05-30 12:04:43 -0700106- (void)testEmptyUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700107 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700108 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
109
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700110 GPBEmpty *request = [GPBEmpty message];
Jorge Canizales73076842015-05-30 12:04:43 -0700111
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700112 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700113 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
114
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700115 id expectedResponse = [GPBEmpty message];
Jorge Canizales73076842015-05-30 12:04:43 -0700116 XCTAssertEqualObjects(response, expectedResponse);
117
118 [expectation fulfill];
119 }];
120
Muxi Yanb1341a32016-12-05 16:38:02 -0800121 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700122}
123
124- (void)testLargeUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700125 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700126 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"];
127
128 RMTSimpleRequest *request = [RMTSimpleRequest message];
129 request.responseType = RMTPayloadType_Compressable;
130 request.responseSize = 314159;
131 request.payload.body = [NSMutableData dataWithLength:271828];
132
133 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
134 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
135
136 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
137 expectedResponse.payload.type = RMTPayloadType_Compressable;
138 expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
139 XCTAssertEqualObjects(response, expectedResponse);
140
141 [expectation fulfill];
142 }];
143
Muxi Yanb1341a32016-12-05 16:38:02 -0800144 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700145}
146
Muxi Yana40ccd82016-11-05 21:39:44 -0700147- (void)testPacketCoalescing {
Muxi Yana40ccd82016-11-05 21:39:44 -0700148 XCTAssertNotNil(self.class.host);
149 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"];
150
151 RMTSimpleRequest *request = [RMTSimpleRequest message];
152 request.responseType = RMTPayloadType_Compressable;
153 request.responseSize = 10;
154 request.payload.body = [NSMutableData dataWithLength:10];
155
Muxi Yan40d7c622017-02-08 14:41:45 -0800156 [GRPCCall enableOpBatchLog:YES];
Muxi Yana40ccd82016-11-05 21:39:44 -0700157 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
158 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
159
160 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
161 expectedResponse.payload.type = RMTPayloadType_Compressable;
162 expectedResponse.payload.body = [NSMutableData dataWithLength:10];
163 XCTAssertEqualObjects(response, expectedResponse);
164
Muxi Yan1fb35b52017-03-07 17:42:25 -0800165 // The test is a success if there is a batch of exactly 3 ops (SEND_INITIAL_METADATA,
166 // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). Without packet coalescing each batch of ops contains
167 // only one op.
Muxi Yan40d7c622017-02-08 14:41:45 -0800168 NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog];
Muxi Yan1fb35b52017-03-07 17:42:25 -0800169 const NSInteger kExpectedOpBatchSize = 3;
Muxi Yan40d7c622017-02-08 14:41:45 -0800170 for (NSObject *o in opBatches) {
171 if ([o isKindOfClass:[NSArray class]]) {
172 NSArray *batch = (NSArray *)o;
Muxi Yan1fb35b52017-03-07 17:42:25 -0800173 if ([batch count] == kExpectedOpBatchSize) {
Muxi Yan40d7c622017-02-08 14:41:45 -0800174 [expectation fulfill];
175 break;
176 }
177 }
178 }
Muxi Yana40ccd82016-11-05 21:39:44 -0700179 }];
180
181 [self waitForExpectationsWithTimeout:16 handler:nil];
Muxi Yan40d7c622017-02-08 14:41:45 -0800182 [GRPCCall enableOpBatchLog:NO];
Muxi Yana40ccd82016-11-05 21:39:44 -0700183}
184
Jorge Canizales6af4add2016-07-28 23:05:18 -0700185- (void)test4MBResponsesAreAccepted {
186 XCTAssertNotNil(self.class.host);
187 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"];
188
189 RMTSimpleRequest *request = [RMTSimpleRequest message];
Jorge Canizales9e83d7e2016-08-01 12:51:31 -0700190 const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead
Jorge Canizales6af4add2016-07-28 23:05:18 -0700191 request.responseSize = kPayloadSize;
192
193 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
194 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
195 XCTAssertEqual(response.payload.body.length, kPayloadSize);
196 [expectation fulfill];
197 }];
198
Muxi Yanb1341a32016-12-05 16:38:02 -0800199 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700200}
201
202- (void)testResponsesOverMaxSizeFailWithActionableMessage {
203 XCTAssertNotNil(self.class.host);
204 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
205
206 RMTSimpleRequest *request = [RMTSimpleRequest message];
Jorge Canizales9e83d7e2016-08-01 12:51:31 -0700207 const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size
Jorge Canizales6af4add2016-07-28 23:05:18 -0700208 request.responseSize = kPayloadSize;
209
210 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
Jorge Canizalesec0743e2016-07-29 01:50:06 -0700211 // TODO(jcanizales): Catch the error and rethrow it with an actionable message:
212 // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit.
213 // - If you're developing the server, consider using response streaming, or let clients filter
214 // responses by setting a google.protobuf.FieldMask in the request:
215 // https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
Mark D. Rotha4d9ee22016-08-31 13:17:26 -0700216 XCTAssertEqualObjects(error.localizedDescription, @"Received message larger than max (4194305 vs. 4194304)");
Jorge Canizales6af4add2016-07-28 23:05:18 -0700217 [expectation fulfill];
218 }];
219
Muxi Yanb1341a32016-12-05 16:38:02 -0800220 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700221}
222
223- (void)testResponsesOver4MBAreAcceptedIfOptedIn {
224 XCTAssertNotNil(self.class.host);
225 __weak XCTestExpectation *expectation =
226 [self expectationWithDescription:@"HigherResponseSizeLimit"];
227
228 RMTSimpleRequest *request = [RMTSimpleRequest message];
229 const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB
230 request.responseSize = kPayloadSize;
231
232 [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host];
233
234 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
235 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
236 XCTAssertEqual(response.payload.body.length, kPayloadSize);
237 [expectation fulfill];
238 }];
239
Muxi Yanb1341a32016-12-05 16:38:02 -0800240 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales6af4add2016-07-28 23:05:18 -0700241}
242
Jorge Canizales73076842015-05-30 12:04:43 -0700243- (void)testClientStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700244 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700245 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"];
246
247 RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message];
248 request1.payload.body = [NSMutableData dataWithLength:27182];
249
250 RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message];
251 request2.payload.body = [NSMutableData dataWithLength:8];
252
253 RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message];
254 request3.payload.body = [NSMutableData dataWithLength:1828];
255
256 RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
257 request4.payload.body = [NSMutableData dataWithLength:45904];
258
Jorge Canizalesa8c5d962015-07-16 18:55:31 -0700259 GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
Jorge Canizales73076842015-05-30 12:04:43 -0700260
261 [_service streamingInputCallWithRequestsWriter:writer
262 handler:^(RMTStreamingInputCallResponse *response,
263 NSError *error) {
264 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
265
266 RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message];
267 expectedResponse.aggregatedPayloadSize = 74922;
268 XCTAssertEqualObjects(response, expectedResponse);
269
270 [expectation fulfill];
271 }];
272
Muxi Yanb1341a32016-12-05 16:38:02 -0800273 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700274}
275
276- (void)testServerStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700277 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700278 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"];
279
280 NSArray *expectedSizes = @[@31415, @9, @2653, @58979];
281
282 RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message];
283 for (NSNumber *size in expectedSizes) {
284 RMTResponseParameters *parameters = [RMTResponseParameters message];
Yuchen Zengafb62f82016-06-24 19:11:08 -0700285 parameters.size = [size intValue];
Jorge Canizales73076842015-05-30 12:04:43 -0700286 [request.responseParametersArray addObject:parameters];
287 }
288
289 __block int index = 0;
290 [_service streamingOutputCallWithRequest:request
murgatroid9925a26612015-06-25 11:22:23 -0700291 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700292 RMTStreamingOutputCallResponse *response,
293 NSError *error){
294 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
295 XCTAssertTrue(done || response, @"Event handler called without an event.");
296
297 if (response) {
298 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
299 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]];
300 XCTAssertEqualObjects(response, expected);
301 index += 1;
302 }
303
304 if (done) {
305 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
306 [expectation fulfill];
307 }
308 }];
309
Muxi Yanb1341a32016-12-05 16:38:02 -0800310 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700311}
312
313- (void)testPingPongRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700314 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700315 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"];
316
317 NSArray *requests = @[@27182, @8, @1828, @45904];
318 NSArray *responses = @[@31415, @9, @2653, @58979];
319
320 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
321
322 __block int index = 0;
323
324 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
325 requestedResponseSize:responses[index]];
326 [requestsBuffer writeValue:request];
327
328 [_service fullDuplexCallWithRequestsWriter:requestsBuffer
murgatroid9925a26612015-06-25 11:22:23 -0700329 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700330 RMTStreamingOutputCallResponse *response,
331 NSError *error) {
332 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
333 XCTAssertTrue(done || response, @"Event handler called without an event.");
334
335 if (response) {
336 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
337 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]];
338 XCTAssertEqualObjects(response, expected);
339 index += 1;
340 if (index < 4) {
341 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
342 requestedResponseSize:responses[index]];
343 [requestsBuffer writeValue:request];
344 } else {
345 [requestsBuffer writesFinishedWithError:nil];
346 }
347 }
348
349 if (done) {
350 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
351 [expectation fulfill];
352 }
353 }];
Muxi Yanb1341a32016-12-05 16:38:02 -0800354 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700355}
356
357- (void)testEmptyStreamRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700358 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700359 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
360 [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter]
murgatroid9925a26612015-06-25 11:22:23 -0700361 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700362 RMTStreamingOutputCallResponse *response,
363 NSError *error) {
364 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
365 XCTAssert(done, @"Unexpected response: %@", response);
366 [expectation fulfill];
367 }];
Muxi Yanb1341a32016-12-05 16:38:02 -0800368 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700369}
370
371- (void)testCancelAfterBeginRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700372 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700373 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"];
374
375 // A buffered pipe to which we never write any value acts as a writer that just hangs.
376 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
377
Yuchen Zeng3d399cb2016-06-21 11:57:46 -0700378 GRPCProtoCall *call =
379 [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
380 handler:^(RMTStreamingInputCallResponse *response,
381 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700382 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
383 [expectation fulfill];
384 }];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700385 XCTAssertEqual(call.state, GRXWriterStateNotStarted);
386
Jorge Canizales73076842015-05-30 12:04:43 -0700387 [call start];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700388 XCTAssertEqual(call.state, GRXWriterStateStarted);
389
Jorge Canizales73076842015-05-30 12:04:43 -0700390 [call cancel];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700391 XCTAssertEqual(call.state, GRXWriterStateFinished);
392
Muxi Yanb1341a32016-12-05 16:38:02 -0800393 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700394}
395
396- (void)testCancelAfterFirstResponseRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700397 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700398 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"];
Nate Kibler2d327712015-09-25 11:56:05 -0700399
Jorge Canizales73076842015-05-30 12:04:43 -0700400 // A buffered pipe to which we write a single value but never close
401 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
Nate Kibler2d327712015-09-25 11:56:05 -0700402
Jorge Canizales73076842015-05-30 12:04:43 -0700403 __block BOOL receivedResponse = NO;
Nate Kibler2d327712015-09-25 11:56:05 -0700404
Jorge Canizales73076842015-05-30 12:04:43 -0700405 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782
406 requestedResponseSize:@31415];
Nate Kibler2d327712015-09-25 11:56:05 -0700407
Jorge Canizales73076842015-05-30 12:04:43 -0700408 [requestsBuffer writeValue:request];
Nate Kibler2d327712015-09-25 11:56:05 -0700409
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -0700410 __block GRPCProtoCall *call =
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700411 [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
412 eventHandler:^(BOOL done,
413 RMTStreamingOutputCallResponse *response,
414 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700415 if (receivedResponse) {
416 XCTAssert(done, @"Unexpected extra response %@", response);
417 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
418 [expectation fulfill];
419 } else {
420 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
421 XCTAssertFalse(done, @"Finished without response");
422 XCTAssertNotNil(response);
423 receivedResponse = YES;
424 [call cancel];
425 }
426 }];
427 [call start];
Muxi Yanb1341a32016-12-05 16:38:02 -0800428 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700429}
430
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700431- (void)testRPCAfterClosingOpenConnections {
432 XCTAssertNotNil(self.class.host);
433 __weak XCTestExpectation *expectation =
434 [self expectationWithDescription:@"RPC after closing connection"];
435
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700436 GPBEmpty *request = [GPBEmpty message];
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700437
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700438 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700439 XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error);
440
Jorge Canizales00ca8ea2016-06-24 16:02:56 -0700441#pragma clang diagnostic push
442#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700443 [GRPCCall closeOpenConnections];
Jorge Canizales00ca8ea2016-06-24 16:02:56 -0700444#pragma clang diagnostic pop
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700445
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -0700446 [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700447 XCTAssertNil(error, @"Second RPC finished with unexpected error: %@", error);
448 [expectation fulfill];
449 }];
450 }];
451
Muxi Yanb1341a32016-12-05 16:38:02 -0800452 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
Jorge Canizalesfa70dac2016-04-29 19:58:52 -0700453}
454
Jorge Canizales73076842015-05-30 12:04:43 -0700455@end