Index: third_party/grpc/src/objective-c/tests/InteropTests.m |
diff --git a/third_party/grpc/src/objective-c/tests/InteropTests.m b/third_party/grpc/src/objective-c/tests/InteropTests.m |
new file mode 100644 |
index 0000000000000000000000000000000000000000..26877b1ae845238a78e5d2a11995f188272bc2a9 |
--- /dev/null |
+++ b/third_party/grpc/src/objective-c/tests/InteropTests.m |
@@ -0,0 +1,315 @@ |
+/* |
+ * |
+ * Copyright 2015, Google Inc. |
+ * All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#import "InteropTests.h" |
+ |
+#include <grpc/status.h> |
+ |
+#import <GRPCClient/GRPCCall+Tests.h> |
+#import <ProtoRPC/ProtoRPC.h> |
+#import <RemoteTest/Empty.pbobjc.h> |
+#import <RemoteTest/Messages.pbobjc.h> |
+#import <RemoteTest/Test.pbobjc.h> |
+#import <RemoteTest/Test.pbrpc.h> |
+#import <RxLibrary/GRXBufferedPipe.h> |
+#import <RxLibrary/GRXWriter+Immediate.h> |
+ |
+// Convenience constructors for the generated proto messages: |
+ |
+@interface RMTStreamingOutputCallRequest (Constructors) |
++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize |
+ requestedResponseSize:(NSNumber *)responseSize; |
+@end |
+ |
+@implementation RMTStreamingOutputCallRequest (Constructors) |
++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize |
+ requestedResponseSize:(NSNumber *)responseSize { |
+ RMTStreamingOutputCallRequest *request = [self message]; |
+ RMTResponseParameters *parameters = [RMTResponseParameters message]; |
+ parameters.size = responseSize.integerValue; |
+ [request.responseParametersArray addObject:parameters]; |
+ request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; |
+ return request; |
+} |
+@end |
+ |
+@interface RMTStreamingOutputCallResponse (Constructors) |
++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; |
+@end |
+ |
+@implementation RMTStreamingOutputCallResponse (Constructors) |
++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { |
+ RMTStreamingOutputCallResponse * response = [self message]; |
+ response.payload.type = RMTPayloadType_Compressable; |
+ response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; |
+ return response; |
+} |
+@end |
+ |
+#pragma mark Tests |
+ |
+@implementation InteropTests { |
+ RMTTestService *_service; |
+} |
+ |
++ (NSString *)host { |
+ return nil; |
+} |
+ |
+- (void)setUp { |
+ _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil; |
+} |
+ |
+- (void)testEmptyUnaryRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; |
+ |
+ RMTEmpty *request = [RMTEmpty message]; |
+ |
+ [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ |
+ id expectedResponse = [RMTEmpty message]; |
+ XCTAssertEqualObjects(response, expectedResponse); |
+ |
+ [expectation fulfill]; |
+ }]; |
+ |
+ [self waitForExpectationsWithTimeout:4 handler:nil]; |
+} |
+ |
+- (void)testLargeUnaryRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; |
+ |
+ RMTSimpleRequest *request = [RMTSimpleRequest message]; |
+ request.responseType = RMTPayloadType_Compressable; |
+ request.responseSize = 314159; |
+ request.payload.body = [NSMutableData dataWithLength:271828]; |
+ |
+ [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ |
+ RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; |
+ expectedResponse.payload.type = RMTPayloadType_Compressable; |
+ expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; |
+ XCTAssertEqualObjects(response, expectedResponse); |
+ |
+ [expectation fulfill]; |
+ }]; |
+ |
+ [self waitForExpectationsWithTimeout:16 handler:nil]; |
+} |
+ |
+- (void)testClientStreamingRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; |
+ |
+ RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; |
+ request1.payload.body = [NSMutableData dataWithLength:27182]; |
+ |
+ RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; |
+ request2.payload.body = [NSMutableData dataWithLength:8]; |
+ |
+ RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message]; |
+ request3.payload.body = [NSMutableData dataWithLength:1828]; |
+ |
+ RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; |
+ request4.payload.body = [NSMutableData dataWithLength:45904]; |
+ |
+ GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]]; |
+ |
+ [_service streamingInputCallWithRequestsWriter:writer |
+ handler:^(RMTStreamingInputCallResponse *response, |
+ NSError *error) { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ |
+ RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message]; |
+ expectedResponse.aggregatedPayloadSize = 74922; |
+ XCTAssertEqualObjects(response, expectedResponse); |
+ |
+ [expectation fulfill]; |
+ }]; |
+ |
+ [self waitForExpectationsWithTimeout:8 handler:nil]; |
+} |
+ |
+- (void)testServerStreamingRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; |
+ |
+ NSArray *expectedSizes = @[@31415, @9, @2653, @58979]; |
+ |
+ RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; |
+ for (NSNumber *size in expectedSizes) { |
+ RMTResponseParameters *parameters = [RMTResponseParameters message]; |
+ parameters.size = [size integerValue]; |
+ [request.responseParametersArray addObject:parameters]; |
+ } |
+ |
+ __block int index = 0; |
+ [_service streamingOutputCallWithRequest:request |
+ eventHandler:^(BOOL done, |
+ RMTStreamingOutputCallResponse *response, |
+ NSError *error){ |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ XCTAssertTrue(done || response, @"Event handler called without an event."); |
+ |
+ if (response) { |
+ XCTAssertLessThan(index, 4, @"More than 4 responses received."); |
+ id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]]; |
+ XCTAssertEqualObjects(response, expected); |
+ index += 1; |
+ } |
+ |
+ if (done) { |
+ XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); |
+ [expectation fulfill]; |
+ } |
+ }]; |
+ |
+ [self waitForExpectationsWithTimeout:8 handler:nil]; |
+} |
+ |
+- (void)testPingPongRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; |
+ |
+ NSArray *requests = @[@27182, @8, @1828, @45904]; |
+ NSArray *responses = @[@31415, @9, @2653, @58979]; |
+ |
+ GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
+ |
+ __block int index = 0; |
+ |
+ id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] |
+ requestedResponseSize:responses[index]]; |
+ [requestsBuffer writeValue:request]; |
+ |
+ [_service fullDuplexCallWithRequestsWriter:requestsBuffer |
+ eventHandler:^(BOOL done, |
+ RMTStreamingOutputCallResponse *response, |
+ NSError *error) { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ XCTAssertTrue(done || response, @"Event handler called without an event."); |
+ |
+ if (response) { |
+ XCTAssertLessThan(index, 4, @"More than 4 responses received."); |
+ id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; |
+ XCTAssertEqualObjects(response, expected); |
+ index += 1; |
+ if (index < 4) { |
+ id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] |
+ requestedResponseSize:responses[index]]; |
+ [requestsBuffer writeValue:request]; |
+ } else { |
+ [requestsBuffer writesFinishedWithError:nil]; |
+ } |
+ } |
+ |
+ if (done) { |
+ XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); |
+ [expectation fulfill]; |
+ } |
+ }]; |
+ [self waitForExpectationsWithTimeout:4 handler:nil]; |
+} |
+ |
+- (void)testEmptyStreamRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; |
+ [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] |
+ eventHandler:^(BOOL done, |
+ RMTStreamingOutputCallResponse *response, |
+ NSError *error) { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ XCTAssert(done, @"Unexpected response: %@", response); |
+ [expectation fulfill]; |
+ }]; |
+ [self waitForExpectationsWithTimeout:2 handler:nil]; |
+} |
+ |
+- (void)testCancelAfterBeginRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; |
+ |
+ // A buffered pipe to which we never write any value acts as a writer that just hangs. |
+ GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
+ |
+ ProtoRPC *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer |
+ handler:^(RMTStreamingInputCallResponse *response, |
+ NSError *error) { |
+ XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); |
+ [expectation fulfill]; |
+ }]; |
+ [call start]; |
+ [call cancel]; |
+ [self waitForExpectationsWithTimeout:1 handler:nil]; |
+} |
+ |
+- (void)testCancelAfterFirstResponseRPC { |
+ XCTAssertNotNil(self.class.host); |
+ __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"]; |
+ |
+ // A buffered pipe to which we write a single value but never close |
+ GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; |
+ |
+ __block BOOL receivedResponse = NO; |
+ |
+ id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 |
+ requestedResponseSize:@31415]; |
+ |
+ [requestsBuffer writeValue:request]; |
+ |
+ __block ProtoRPC *call = |
+ [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer |
+ eventHandler:^(BOOL done, |
+ RMTStreamingOutputCallResponse *response, |
+ NSError *error) { |
+ if (receivedResponse) { |
+ XCTAssert(done, @"Unexpected extra response %@", response); |
+ XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); |
+ [expectation fulfill]; |
+ } else { |
+ XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
+ XCTAssertFalse(done, @"Finished without response"); |
+ XCTAssertNotNil(response); |
+ receivedResponse = YES; |
+ [call cancel]; |
+ } |
+ }]; |
+ [call start]; |
+ [self waitForExpectationsWithTimeout:8 handler:nil]; |
+} |
+ |
+@end |