OLD | NEW |
(Empty) | |
| 1 /* |
| 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 |
| 34 #import "InteropTests.h" |
| 35 |
| 36 #include <grpc/status.h> |
| 37 |
| 38 #import <GRPCClient/GRPCCall+Tests.h> |
| 39 #import <ProtoRPC/ProtoRPC.h> |
| 40 #import <RemoteTest/Empty.pbobjc.h> |
| 41 #import <RemoteTest/Messages.pbobjc.h> |
| 42 #import <RemoteTest/Test.pbobjc.h> |
| 43 #import <RemoteTest/Test.pbrpc.h> |
| 44 #import <RxLibrary/GRXBufferedPipe.h> |
| 45 #import <RxLibrary/GRXWriter+Immediate.h> |
| 46 |
| 47 // Convenience constructors for the generated proto messages: |
| 48 |
| 49 @interface RMTStreamingOutputCallRequest (Constructors) |
| 50 + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize |
| 51 requestedResponseSize:(NSNumber *)responseSize; |
| 52 @end |
| 53 |
| 54 @implementation RMTStreamingOutputCallRequest (Constructors) |
| 55 + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize |
| 56 requestedResponseSize:(NSNumber *)responseSize { |
| 57 RMTStreamingOutputCallRequest *request = [self message]; |
| 58 RMTResponseParameters *parameters = [RMTResponseParameters message]; |
| 59 parameters.size = responseSize.integerValue; |
| 60 [request.responseParametersArray addObject:parameters]; |
| 61 request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedInteg
erValue]; |
| 62 return request; |
| 63 } |
| 64 @end |
| 65 |
| 66 @interface RMTStreamingOutputCallResponse (Constructors) |
| 67 + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; |
| 68 @end |
| 69 |
| 70 @implementation RMTStreamingOutputCallResponse (Constructors) |
| 71 + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { |
| 72 RMTStreamingOutputCallResponse * response = [self message]; |
| 73 response.payload.type = RMTPayloadType_Compressable; |
| 74 response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedInte
gerValue]; |
| 75 return response; |
| 76 } |
| 77 @end |
| 78 |
| 79 #pragma mark Tests |
| 80 |
| 81 @implementation InteropTests { |
| 82 RMTTestService *_service; |
| 83 } |
| 84 |
| 85 + (NSString *)host { |
| 86 return nil; |
| 87 } |
| 88 |
| 89 - (void)setUp { |
| 90 _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host]
: nil; |
| 91 } |
| 92 |
| 93 - (void)testEmptyUnaryRPC { |
| 94 XCTAssertNotNil(self.class.host); |
| 95 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Emp
tyUnary"]; |
| 96 |
| 97 RMTEmpty *request = [RMTEmpty message]; |
| 98 |
| 99 [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *
error) { |
| 100 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 101 |
| 102 id expectedResponse = [RMTEmpty message]; |
| 103 XCTAssertEqualObjects(response, expectedResponse); |
| 104 |
| 105 [expectation fulfill]; |
| 106 }]; |
| 107 |
| 108 [self waitForExpectationsWithTimeout:4 handler:nil]; |
| 109 } |
| 110 |
| 111 - (void)testLargeUnaryRPC { |
| 112 XCTAssertNotNil(self.class.host); |
| 113 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Lar
geUnary"]; |
| 114 |
| 115 RMTSimpleRequest *request = [RMTSimpleRequest message]; |
| 116 request.responseType = RMTPayloadType_Compressable; |
| 117 request.responseSize = 314159; |
| 118 request.payload.body = [NSMutableData dataWithLength:271828]; |
| 119 |
| 120 [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response,
NSError *error) { |
| 121 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 122 |
| 123 RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; |
| 124 expectedResponse.payload.type = RMTPayloadType_Compressable; |
| 125 expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; |
| 126 XCTAssertEqualObjects(response, expectedResponse); |
| 127 |
| 128 [expectation fulfill]; |
| 129 }]; |
| 130 |
| 131 [self waitForExpectationsWithTimeout:16 handler:nil]; |
| 132 } |
| 133 |
| 134 - (void)testClientStreamingRPC { |
| 135 XCTAssertNotNil(self.class.host); |
| 136 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Cli
entStreaming"]; |
| 137 |
| 138 RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message
]; |
| 139 request1.payload.body = [NSMutableData dataWithLength:27182]; |
| 140 |
| 141 RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message
]; |
| 142 request2.payload.body = [NSMutableData dataWithLength:8]; |
| 143 |
| 144 RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message
]; |
| 145 request3.payload.body = [NSMutableData dataWithLength:1828]; |
| 146 |
| 147 RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message
]; |
| 148 request4.payload.body = [NSMutableData dataWithLength:45904]; |
| 149 |
| 150 GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, reque
st3, request4]]; |
| 151 |
| 152 [_service streamingInputCallWithRequestsWriter:writer |
| 153 handler:^(RMTStreamingInputCallResponse
*response, |
| 154 NSError *error) { |
| 155 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 156 |
| 157 RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResp
onse message]; |
| 158 expectedResponse.aggregatedPayloadSize = 74922; |
| 159 XCTAssertEqualObjects(response, expectedResponse); |
| 160 |
| 161 [expectation fulfill]; |
| 162 }]; |
| 163 |
| 164 [self waitForExpectationsWithTimeout:8 handler:nil]; |
| 165 } |
| 166 |
| 167 - (void)testServerStreamingRPC { |
| 168 XCTAssertNotNil(self.class.host); |
| 169 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Ser
verStreaming"]; |
| 170 |
| 171 NSArray *expectedSizes = @[@31415, @9, @2653, @58979]; |
| 172 |
| 173 RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest messag
e]; |
| 174 for (NSNumber *size in expectedSizes) { |
| 175 RMTResponseParameters *parameters = [RMTResponseParameters message]; |
| 176 parameters.size = [size integerValue]; |
| 177 [request.responseParametersArray addObject:parameters]; |
| 178 } |
| 179 |
| 180 __block int index = 0; |
| 181 [_service streamingOutputCallWithRequest:request |
| 182 eventHandler:^(BOOL done, |
| 183 RMTStreamingOutputCallResponse *res
ponse, |
| 184 NSError *error){ |
| 185 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 186 XCTAssertTrue(done || response, @"Event handler called without an event."); |
| 187 |
| 188 if (response) { |
| 189 XCTAssertLessThan(index, 4, @"More than 4 responses received."); |
| 190 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expec
tedSizes[index]]; |
| 191 XCTAssertEqualObjects(response, expected); |
| 192 index += 1; |
| 193 } |
| 194 |
| 195 if (done) { |
| 196 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); |
| 197 [expectation fulfill]; |
| 198 } |
| 199 }]; |
| 200 |
| 201 [self waitForExpectationsWithTimeout:8 handler:nil]; |
| 202 } |
| 203 |
| 204 - (void)testPingPongRPC { |
| 205 XCTAssertNotNil(self.class.host); |
| 206 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Pin
gPong"]; |
| 207 |
| 208 NSArray *requests = @[@27182, @8, @1828, @45904]; |
| 209 NSArray *responses = @[@31415, @9, @2653, @58979]; |
| 210 |
| 211 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
| 212 |
| 213 __block int index = 0; |
| 214 |
| 215 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[in
dex] |
| 216 requestedResponseSize:responses[i
ndex]]; |
| 217 [requestsBuffer writeValue:request]; |
| 218 |
| 219 [_service fullDuplexCallWithRequestsWriter:requestsBuffer |
| 220 eventHandler:^(BOOL done, |
| 221 RMTStreamingOutputCallResponse *r
esponse, |
| 222 NSError *error) { |
| 223 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 224 XCTAssertTrue(done || response, @"Event handler called without an event."); |
| 225 |
| 226 if (response) { |
| 227 XCTAssertLessThan(index, 4, @"More than 4 responses received."); |
| 228 id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:respo
nses[index]]; |
| 229 XCTAssertEqualObjects(response, expected); |
| 230 index += 1; |
| 231 if (index < 4) { |
| 232 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:reque
sts[index] |
| 233 requestedResponseSize:respo
nses[index]]; |
| 234 [requestsBuffer writeValue:request]; |
| 235 } else { |
| 236 [requestsBuffer writesFinishedWithError:nil]; |
| 237 } |
| 238 } |
| 239 |
| 240 if (done) { |
| 241 XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); |
| 242 [expectation fulfill]; |
| 243 } |
| 244 }]; |
| 245 [self waitForExpectationsWithTimeout:4 handler:nil]; |
| 246 } |
| 247 |
| 248 - (void)testEmptyStreamRPC { |
| 249 XCTAssertNotNil(self.class.host); |
| 250 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Emp
tyStream"]; |
| 251 [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] |
| 252 eventHandler:^(BOOL done, |
| 253 RMTStreamingOutputCallResponse *r
esponse, |
| 254 NSError *error) { |
| 255 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 256 XCTAssert(done, @"Unexpected response: %@", response); |
| 257 [expectation fulfill]; |
| 258 }]; |
| 259 [self waitForExpectationsWithTimeout:2 handler:nil]; |
| 260 } |
| 261 |
| 262 - (void)testCancelAfterBeginRPC { |
| 263 XCTAssertNotNil(self.class.host); |
| 264 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Can
celAfterBegin"]; |
| 265 |
| 266 // A buffered pipe to which we never write any value acts as a writer that jus
t hangs. |
| 267 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
| 268 |
| 269 ProtoRPC *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsB
uffer |
| 270 handler:^(RMTStre
amingInputCallResponse *response, |
| 271 NSError
*error) { |
| 272 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); |
| 273 [expectation fulfill]; |
| 274 }]; |
| 275 [call start]; |
| 276 [call cancel]; |
| 277 [self waitForExpectationsWithTimeout:1 handler:nil]; |
| 278 } |
| 279 |
| 280 - (void)testCancelAfterFirstResponseRPC { |
| 281 XCTAssertNotNil(self.class.host); |
| 282 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Can
celAfterFirstResponse"]; |
| 283 |
| 284 // A buffered pipe to which we write a single value but never close |
| 285 GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
| 286 |
| 287 __block BOOL receivedResponse = NO; |
| 288 |
| 289 id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 |
| 290 requestedResponseSize:@31415]; |
| 291 |
| 292 [requestsBuffer writeValue:request]; |
| 293 |
| 294 __block ProtoRPC *call = |
| 295 [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer |
| 296 eventHandler:^(BOOL done, |
| 297 RMTStreamingOutputCallRe
sponse *response, |
| 298 NSError *error) { |
| 299 if (receivedResponse) { |
| 300 XCTAssert(done, @"Unexpected extra response %@", response); |
| 301 XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); |
| 302 [expectation fulfill]; |
| 303 } else { |
| 304 XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
| 305 XCTAssertFalse(done, @"Finished without response"); |
| 306 XCTAssertNotNil(response); |
| 307 receivedResponse = YES; |
| 308 [call cancel]; |
| 309 } |
| 310 }]; |
| 311 [call start]; |
| 312 [self waitForExpectationsWithTimeout:8 handler:nil]; |
| 313 } |
| 314 |
| 315 @end |
OLD | NEW |