blob: 15ce120c55118cfa882a1ab1741f29b86262cbb1 [file] [log] [blame]
Jorge Canizales73076842015-05-30 12:04:43 -07001/*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Jorge Canizales91952332015-07-31 17:50:49 -070034#import "InteropTests.h"
Jorge Canizales73076842015-05-30 12:04:43 -070035
Jorge Canizales91952332015-07-31 17:50:49 -070036#include <grpc/status.h>
Jorge Canizales73076842015-05-30 12:04:43 -070037
Makarand Dharmapurikarde733bd2016-05-25 10:38:56 -070038#import <Cronet/Cronet.h>
Jorge Canizalesb2bd0672015-08-01 23:19:11 -070039#import <GRPCClient/GRPCCall+Tests.h>
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -070040#import <GRPCClient/GRPCCall+Cronet.h>
Jorge Canizalesc42a38e2015-06-21 14:44:25 -070041#import <ProtoRPC/ProtoRPC.h>
Jorge Canizales73076842015-05-30 12:04:43 -070042#import <RemoteTest/Empty.pbobjc.h>
43#import <RemoteTest/Messages.pbobjc.h>
44#import <RemoteTest/Test.pbobjc.h>
45#import <RemoteTest/Test.pbrpc.h>
Jorge Canizalesc42a38e2015-06-21 14:44:25 -070046#import <RxLibrary/GRXBufferedPipe.h>
47#import <RxLibrary/GRXWriter+Immediate.h>
Jorge Canizales73076842015-05-30 12:04:43 -070048
49// Convenience constructors for the generated proto messages:
50
51@interface RMTStreamingOutputCallRequest (Constructors)
52+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize
53 requestedResponseSize:(NSNumber *)responseSize;
54@end
55
56@implementation RMTStreamingOutputCallRequest (Constructors)
57+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize
58 requestedResponseSize:(NSNumber *)responseSize {
59 RMTStreamingOutputCallRequest *request = [self message];
60 RMTResponseParameters *parameters = [RMTResponseParameters message];
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -070061 parameters.size = (int)responseSize.integerValue;
Jorge Canizales73076842015-05-30 12:04:43 -070062 [request.responseParametersArray addObject:parameters];
63 request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
64 return request;
65}
66@end
67
68@interface RMTStreamingOutputCallResponse (Constructors)
69+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize;
70@end
71
72@implementation RMTStreamingOutputCallResponse (Constructors)
73+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize {
74 RMTStreamingOutputCallResponse * response = [self message];
75 response.payload.type = RMTPayloadType_Compressable;
76 response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
77 return response;
78}
79@end
80
Jorge Canizalesb2bd0672015-08-01 23:19:11 -070081#pragma mark Tests
82
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -070083#ifdef GRPC_COMPILE_WITH_CRONET
Makarand Dharmapurikaraed1de92016-05-26 09:39:26 -070084static cronet_engine *cronetEngine = NULL;
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -070085#endif
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -070086
Jorge Canizales73076842015-05-30 12:04:43 -070087@implementation InteropTests {
88 RMTTestService *_service;
89}
90
Jorge Canizales945f72c2015-07-31 17:40:59 -070091+ (NSString *)host {
Jorge Canizales91db5ac2015-10-28 14:53:38 -070092 return nil;
Jorge Canizales945f72c2015-07-31 17:40:59 -070093}
Jorge Canizalesce8ee612015-07-24 20:52:49 -070094
Jorge Canizales73076842015-05-30 12:04:43 -070095- (void)setUp {
Jorge Canizales91db5ac2015-10-28 14:53:38 -070096 _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -070097#ifdef GRPC_COMPILE_WITH_CRONET
Makarand Dharmapurikaraed1de92016-05-26 09:39:26 -070098 if (cronetEngine == NULL) {
99 // Cronet setup
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -0700100 [Cronet setHttp2Enabled:YES];
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -0700101 [Cronet start];
Makarand Dharmapurikaraed1de92016-05-26 09:39:26 -0700102 cronetEngine = [Cronet getGlobalEngine];
103 [GRPCCall useCronetWithEngine:cronetEngine];
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -0700104 }
105#endif
Jorge Canizales73076842015-05-30 12:04:43 -0700106}
107
Jorge Canizales73076842015-05-30 12:04:43 -0700108- (void)testEmptyUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700109 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700110 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
111
112 RMTEmpty *request = [RMTEmpty message];
113
114 [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) {
115 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
116
117 id expectedResponse = [RMTEmpty message];
118 XCTAssertEqualObjects(response, expectedResponse);
119
120 [expectation fulfill];
121 }];
122
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700123 [self waitForExpectationsWithTimeout:4 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700124}
125
126- (void)testLargeUnaryRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700127 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700128 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"];
129
130 RMTSimpleRequest *request = [RMTSimpleRequest message];
131 request.responseType = RMTPayloadType_Compressable;
132 request.responseSize = 314159;
133 request.payload.body = [NSMutableData dataWithLength:271828];
134
135 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
136 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
137
138 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
139 expectedResponse.payload.type = RMTPayloadType_Compressable;
140 expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
141 XCTAssertEqualObjects(response, expectedResponse);
142
143 [expectation fulfill];
144 }];
145
Jorge Canizales83c57cb2015-08-09 16:36:49 -0700146 [self waitForExpectationsWithTimeout:16 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700147}
148
149- (void)testClientStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700150 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700151 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"];
152
153 RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message];
154 request1.payload.body = [NSMutableData dataWithLength:27182];
155
156 RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message];
157 request2.payload.body = [NSMutableData dataWithLength:8];
158
159 RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message];
160 request3.payload.body = [NSMutableData dataWithLength:1828];
161
162 RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
163 request4.payload.body = [NSMutableData dataWithLength:45904];
164
Jorge Canizalesa8c5d962015-07-16 18:55:31 -0700165 GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
Jorge Canizales73076842015-05-30 12:04:43 -0700166
167 [_service streamingInputCallWithRequestsWriter:writer
168 handler:^(RMTStreamingInputCallResponse *response,
169 NSError *error) {
170 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
171
172 RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message];
173 expectedResponse.aggregatedPayloadSize = 74922;
174 XCTAssertEqualObjects(response, expectedResponse);
175
176 [expectation fulfill];
177 }];
178
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700179 [self waitForExpectationsWithTimeout:8 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700180}
181
182- (void)testServerStreamingRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700183 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700184 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"];
185
186 NSArray *expectedSizes = @[@31415, @9, @2653, @58979];
187
188 RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message];
189 for (NSNumber *size in expectedSizes) {
190 RMTResponseParameters *parameters = [RMTResponseParameters message];
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -0700191 parameters.size = (int)[size integerValue];
Jorge Canizales73076842015-05-30 12:04:43 -0700192 [request.responseParametersArray addObject:parameters];
193 }
194
195 __block int index = 0;
196 [_service streamingOutputCallWithRequest:request
murgatroid9925a26612015-06-25 11:22:23 -0700197 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700198 RMTStreamingOutputCallResponse *response,
199 NSError *error){
200 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
201 XCTAssertTrue(done || response, @"Event handler called without an event.");
202
203 if (response) {
204 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
205 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]];
206 XCTAssertEqualObjects(response, expected);
207 index += 1;
208 }
209
210 if (done) {
211 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
212 [expectation fulfill];
213 }
214 }];
215
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700216 [self waitForExpectationsWithTimeout:8 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700217}
218
219- (void)testPingPongRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700220 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700221 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"];
222
223 NSArray *requests = @[@27182, @8, @1828, @45904];
224 NSArray *responses = @[@31415, @9, @2653, @58979];
225
226 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
227
228 __block int index = 0;
229
230 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
231 requestedResponseSize:responses[index]];
232 [requestsBuffer writeValue:request];
233
234 [_service fullDuplexCallWithRequestsWriter:requestsBuffer
murgatroid9925a26612015-06-25 11:22:23 -0700235 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700236 RMTStreamingOutputCallResponse *response,
237 NSError *error) {
238 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
239 XCTAssertTrue(done || response, @"Event handler called without an event.");
240
241 if (response) {
242 XCTAssertLessThan(index, 4, @"More than 4 responses received.");
243 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]];
244 XCTAssertEqualObjects(response, expected);
245 index += 1;
246 if (index < 4) {
247 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
248 requestedResponseSize:responses[index]];
249 [requestsBuffer writeValue:request];
250 } else {
251 [requestsBuffer writesFinishedWithError:nil];
252 }
253 }
254
255 if (done) {
256 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
257 [expectation fulfill];
258 }
259 }];
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700260 [self waitForExpectationsWithTimeout:4 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700261}
262
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -0700263#ifndef GRPC_COMPILE_WITH_CRONET
264// TODO(makdharma@): Fix this test
Jorge Canizales73076842015-05-30 12:04:43 -0700265- (void)testEmptyStreamRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700266 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700267 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
268 [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter]
murgatroid9925a26612015-06-25 11:22:23 -0700269 eventHandler:^(BOOL done,
Jorge Canizales73076842015-05-30 12:04:43 -0700270 RMTStreamingOutputCallResponse *response,
271 NSError *error) {
272 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
273 XCTAssert(done, @"Unexpected response: %@", response);
274 [expectation fulfill];
275 }];
276 [self waitForExpectationsWithTimeout:2 handler:nil];
277}
Makarand Dharmapurikar9b5f6402016-05-20 15:57:34 -0700278#endif
Jorge Canizales73076842015-05-30 12:04:43 -0700279
280- (void)testCancelAfterBeginRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700281 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700282 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"];
283
284 // A buffered pipe to which we never write any value acts as a writer that just hangs.
285 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
286
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -0700287 GRPCProtoCall *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
Yuchen Zeng8d9e8382016-06-21 11:21:48 -0700288 handler:^(RMTStreamingInputCallResponse *response,
289 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700290 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
291 [expectation fulfill];
292 }];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700293 XCTAssertEqual(call.state, GRXWriterStateNotStarted);
294
Jorge Canizales73076842015-05-30 12:04:43 -0700295 [call start];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700296 XCTAssertEqual(call.state, GRXWriterStateStarted);
297
Jorge Canizales73076842015-05-30 12:04:43 -0700298 [call cancel];
Jorge Canizales47b80bc2016-04-30 10:32:49 -0700299 XCTAssertEqual(call.state, GRXWriterStateFinished);
300
Jorge Canizales73076842015-05-30 12:04:43 -0700301 [self waitForExpectationsWithTimeout:1 handler:nil];
302}
303
304- (void)testCancelAfterFirstResponseRPC {
Jorge Canizales91db5ac2015-10-28 14:53:38 -0700305 XCTAssertNotNil(self.class.host);
Jorge Canizales73076842015-05-30 12:04:43 -0700306 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"];
Nate Kibler2d327712015-09-25 11:56:05 -0700307
Jorge Canizales73076842015-05-30 12:04:43 -0700308 // A buffered pipe to which we write a single value but never close
309 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
Nate Kibler2d327712015-09-25 11:56:05 -0700310
Jorge Canizales73076842015-05-30 12:04:43 -0700311 __block BOOL receivedResponse = NO;
Nate Kibler2d327712015-09-25 11:56:05 -0700312
Jorge Canizales73076842015-05-30 12:04:43 -0700313 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782
314 requestedResponseSize:@31415];
Nate Kibler2d327712015-09-25 11:56:05 -0700315
Jorge Canizales73076842015-05-30 12:04:43 -0700316 [requestsBuffer writeValue:request];
Nate Kibler2d327712015-09-25 11:56:05 -0700317
Yuchen Zengdbe2b9e2016-06-15 20:23:04 -0700318 __block GRPCProtoCall *call =
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700319 [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
320 eventHandler:^(BOOL done,
321 RMTStreamingOutputCallResponse *response,
322 NSError *error) {
Jorge Canizales73076842015-05-30 12:04:43 -0700323 if (receivedResponse) {
324 XCTAssert(done, @"Unexpected extra response %@", response);
325 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
326 [expectation fulfill];
327 } else {
328 XCTAssertNil(error, @"Finished with unexpected error: %@", error);
329 XCTAssertFalse(done, @"Finished without response");
330 XCTAssertNotNil(response);
331 receivedResponse = YES;
332 [call cancel];
333 }
334 }];
335 [call start];
Jorge Canizales5580e5d2015-07-15 23:35:48 -0700336 [self waitForExpectationsWithTimeout:8 handler:nil];
Jorge Canizales73076842015-05-30 12:04:43 -0700337}
338
339@end