blob: 8a158b5eab9d64e9bd4befaaca9f26536cc39f1d [file] [log] [blame]
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <XCTest/XCTest.h>
#import <Cronet/Cronet.h>
#import <GRPCClient/GRPCCallOptions.h>
#import <RxLibrary/GRXBufferedPipe.h>
#import "src/objective-c/tests/RemoteTestClient/Messages.pbobjc.h"
#import "src/objective-c/tests/RemoteTestClient/Test.pbobjc.h"
#import "src/objective-c/tests/RemoteTestClient/Test.pbrpc.h"
#import "../ConfigureCronet.h"
#import "InteropTestsBlockCallbacks.h"
#define NSStringize_helper(x) #x
#define NSStringize(x) @NSStringize_helper(x)
static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
static NSString *const kLocalSSLHost = NSStringize(HOST_PORT_LOCALSSL);
static NSString *const kLocalCleartextHost = NSStringize(HOST_PORT_LOCAL);
static const NSTimeInterval TEST_TIMEOUT = 8000;
@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.intValue;
[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
@interface InteropTestsMultipleChannels : XCTestCase
@end
dispatch_once_t initCronet;
@implementation InteropTestsMultipleChannels {
RMTTestService *_remoteService;
RMTTestService *_remoteCronetService;
RMTTestService *_localCleartextService;
RMTTestService *_localSSLService;
}
- (void)setUp {
[super setUp];
self.continueAfterFailure = NO;
_remoteService = [RMTTestService serviceWithHost:kRemoteSSLHost callOptions:nil];
configureCronet(/*enable_netlog=*/false);
// Default stack with remote host
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
options.transportType = GRPCTransportTypeCronet;
// Cronet stack with remote host
_remoteCronetService = [RMTTestService serviceWithHost:kRemoteSSLHost callOptions:options];
// Local stack with no SSL
options = [[GRPCMutableCallOptions alloc] init];
options.transportType = GRPCTransportTypeInsecure;
_localCleartextService = [RMTTestService serviceWithHost:kLocalCleartextHost callOptions:options];
// Local stack with SSL
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *certsPath =
[bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"];
NSError *error = nil;
NSString *certs =
[NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error];
XCTAssertNil(error);
options = [[GRPCMutableCallOptions alloc] init];
options.transportType = GRPCTransportTypeChttp2BoringSSL;
options.PEMRootCertificates = certs;
options.hostNameOverride = @"foo.test.google.fr";
_localSSLService = [RMTTestService serviceWithHost:kLocalSSLHost callOptions:options];
}
- (void)testEmptyUnaryRPC {
__weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectCronetRemote =
[self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectCleartext =
[self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"];
GPBEmpty *request = [GPBEmpty message];
void (^messageHandler)(id message) = ^(id message) {
id expectedResponse = [GPBEmpty message];
XCTAssertEqualObjects(message, expectedResponse);
};
GRPCUnaryProtoCall *callRemote = [_remoteService
emptyCallWithMessage:request
responseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:messageHandler
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectRemote fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
GRPCUnaryProtoCall *callCronet = [_remoteCronetService
emptyCallWithMessage:request
responseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:messageHandler
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectCronetRemote fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
GRPCUnaryProtoCall *callCleartext = [_localCleartextService
emptyCallWithMessage:request
responseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:messageHandler
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectCleartext fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
GRPCUnaryProtoCall *callSSL = [_localSSLService
emptyCallWithMessage:request
responseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:messageHandler
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectSSL fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
[callRemote start];
[callCronet start];
[callCleartext start];
[callSSL start];
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
- (void)testFullDuplexRPC {
__weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectCronetRemote =
[self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectCleartext =
[self expectationWithDescription:@"Remote RPC finish"];
__weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"];
NSArray *requestSizes = @[ @100, @101, @102, @103 ];
NSArray *responseSizes = @[ @104, @105, @106, @107 ];
XCTAssertEqual([requestSizes count], [responseSizes count]);
NSUInteger kRounds = [requestSizes count];
NSMutableArray<GRPCStreamingProtoCall *> *calls = [NSMutableArray arrayWithCapacity:4];
NSMutableArray *requests = [NSMutableArray arrayWithCapacity:kRounds];
NSMutableArray *responses = [NSMutableArray arrayWithCapacity:kRounds];
for (int i = 0; i < kRounds; i++) {
requests[i] = [RMTStreamingOutputCallRequest messageWithPayloadSize:requestSizes[i]
requestedResponseSize:responseSizes[i]];
responses[i] = [RMTStreamingOutputCallResponse messageWithPayloadSize:responseSizes[i]];
}
__block NSMutableArray *steps = [NSMutableArray arrayWithCapacity:4];
__block NSMutableArray *requestsBuffers = [NSMutableArray arrayWithCapacity:4];
for (int i = 0; i < 4; i++) {
steps[i] = [NSNumber numberWithUnsignedInteger:0];
requestsBuffers[i] = [[GRXBufferedPipe alloc] init];
[requestsBuffers[i] writeValue:requests[0]];
}
void (^handler)(NSUInteger index, id message) = ^(NSUInteger index, id message) {
NSUInteger step = [steps[index] unsignedIntegerValue];
step++;
steps[index] = [NSNumber numberWithUnsignedInteger:step];
if (step < kRounds) {
[calls[index] writeMessage:requests[step]];
} else {
[calls[index] finish];
}
};
calls[0] = [_remoteService
fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:^(id message) {
handler(0, message);
}
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectRemote fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
calls[1] = [_remoteCronetService
fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:^(id message) {
handler(1, message);
}
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectCronetRemote fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
calls[2] = [_localCleartextService
fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:^(id message) {
handler(2, message);
}
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectCleartext fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
calls[3] = [_localSSLService
fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:^(id message) {
handler(3, message);
}
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
XCTAssertNil(error);
[expectSSL fulfill];
}
writeMessageCallback:nil]
callOptions:nil];
for (int i = 0; i < 4; i++) {
[calls[i] start];
[calls[i] writeMessage:requests[0]];
}
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
@end