parent
af1b4d6b48
commit
9fbc9105a6
21 changed files with 2305 additions and 18 deletions
@ -0,0 +1,164 @@ |
||||
/* |
||||
* |
||||
* 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 "../../GRPCClient/private/GRPCChannel.h" |
||||
#import "../../GRPCClient/private/GRPCChannelPool.h" |
||||
|
||||
#define TEST_TIMEOUT 32 |
||||
|
||||
NSString *kDummyHost = @"dummy.host"; |
||||
|
||||
@interface ChannelPoolTest : XCTestCase |
||||
|
||||
@end |
||||
|
||||
@implementation ChannelPoolTest |
||||
|
||||
+ (void)setUp { |
||||
grpc_init(); |
||||
} |
||||
|
||||
- (void)testCreateChannel { |
||||
NSString *kDummyHost = @"dummy.host"; |
||||
GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; |
||||
options1.transportType = GRPCTransportTypeInsecure; |
||||
GRPCCallOptions *options2 = [options1 copy]; |
||||
GRPCChannelConfiguration *config1 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; |
||||
GRPCChannelConfiguration *config2 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; |
||||
GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; |
||||
|
||||
__weak XCTestExpectation *expectCreateChannel = |
||||
[self expectationWithDescription:@"Create first channel"]; |
||||
GRPCChannel *channel1 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
[expectCreateChannel fulfill]; |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
GRPCChannel *channel2 = [pool channelWithConfiguration:config2 |
||||
createChannel:^{ |
||||
XCTFail(@"Should not create a second channel."); |
||||
return (GRPCChannel *)nil; |
||||
}]; |
||||
XCTAssertEqual(channel1, channel2); |
||||
} |
||||
|
||||
- (void)testChannelTimeout { |
||||
NSTimeInterval kChannelDestroyDelay = 1.0; |
||||
GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; |
||||
options1.transportType = GRPCTransportTypeInsecure; |
||||
GRPCChannelConfiguration *config1 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; |
||||
GRPCChannelPool *pool = |
||||
[[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; |
||||
GRPCChannel *channel1 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
[pool unrefChannelWithConfiguration:config1]; |
||||
__weak XCTestExpectation *expectTimerDone = [self expectationWithDescription:@"Timer elapse."]; |
||||
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:kChannelDestroyDelay + 1 |
||||
repeats:NO |
||||
block:^(NSTimer *_Nonnull timer) { |
||||
[expectTimerDone fulfill]; |
||||
}]; |
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
timer = nil; |
||||
GRPCChannel *channel2 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
XCTAssertNotEqual(channel1, channel2); |
||||
} |
||||
|
||||
- (void)testChannelTimeoutCancel { |
||||
NSTimeInterval kChannelDestroyDelay = 3.0; |
||||
GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; |
||||
options1.transportType = GRPCTransportTypeInsecure; |
||||
GRPCChannelConfiguration *config1 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; |
||||
GRPCChannelPool *pool = |
||||
[[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; |
||||
GRPCChannel *channel1 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
[channel1 unmanagedCallUnref]; |
||||
sleep(1); |
||||
GRPCChannel *channel2 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
XCTAssertEqual(channel1, channel2); |
||||
sleep((int)kChannelDestroyDelay + 2); |
||||
GRPCChannel *channel3 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
XCTAssertEqual(channel1, channel3); |
||||
} |
||||
|
||||
- (void)testClearChannels { |
||||
GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; |
||||
options1.transportType = GRPCTransportTypeInsecure; |
||||
GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; |
||||
options2.transportType = GRPCTransportTypeDefault; |
||||
GRPCChannelConfiguration *config1 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; |
||||
GRPCChannelConfiguration *config2 = |
||||
[[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; |
||||
GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; |
||||
|
||||
GRPCChannel *channel1 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
GRPCChannel *channel2 = |
||||
[pool channelWithConfiguration:config2 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config2]; |
||||
}]; |
||||
XCTAssertNotEqual(channel1, channel2); |
||||
|
||||
[pool clear]; |
||||
GRPCChannel *channel3 = |
||||
[pool channelWithConfiguration:config1 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config1]; |
||||
}]; |
||||
GRPCChannel *channel4 = |
||||
[pool channelWithConfiguration:config2 |
||||
createChannel:^{ |
||||
return [GRPCChannel createChannelWithConfiguration:config2]; |
||||
}]; |
||||
XCTAssertNotEqual(channel1, channel3); |
||||
XCTAssertNotEqual(channel2, channel4); |
||||
} |
||||
|
||||
@end |
@ -0,0 +1,93 @@ |
||||
/* |
||||
* |
||||
* 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 "../../GRPCClient/GRPCCallOptions.h" |
||||
#import "../../GRPCClient/private/GRPCChannel.h" |
||||
|
||||
@interface ChannelTests : XCTestCase |
||||
|
||||
@end |
||||
|
||||
@implementation ChannelTests |
||||
|
||||
+ (void)setUp { |
||||
grpc_init(); |
||||
} |
||||
|
||||
- (void)testSameConfiguration { |
||||
NSString *host = @"grpc-test.sandbox.googleapis.com"; |
||||
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; |
||||
options.userAgentPrefix = @"TestUAPrefix"; |
||||
NSMutableDictionary *args = [NSMutableDictionary new]; |
||||
args[@"abc"] = @"xyz"; |
||||
options.additionalChannelArgs = [args copy]; |
||||
GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options]; |
||||
GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options]; |
||||
XCTAssertEqual(channel1, channel2); |
||||
GRPCMutableCallOptions *options2 = [options mutableCopy]; |
||||
options2.additionalChannelArgs = [args copy]; |
||||
GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options2]; |
||||
XCTAssertEqual(channel1, channel3); |
||||
} |
||||
|
||||
- (void)testDifferentHost { |
||||
NSString *host1 = @"grpc-test.sandbox.googleapis.com"; |
||||
NSString *host2 = @"grpc-test2.sandbox.googleapis.com"; |
||||
NSString *host3 = @"http://grpc-test.sandbox.googleapis.com"; |
||||
NSString *host4 = @"dns://grpc-test.sandbox.googleapis.com"; |
||||
NSString *host5 = @"grpc-test.sandbox.googleapis.com:80"; |
||||
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; |
||||
options.userAgentPrefix = @"TestUAPrefix"; |
||||
NSMutableDictionary *args = [NSMutableDictionary new]; |
||||
args[@"abc"] = @"xyz"; |
||||
options.additionalChannelArgs = [args copy]; |
||||
GRPCChannel *channel1 = [GRPCChannel channelWithHost:host1 callOptions:options]; |
||||
GRPCChannel *channel2 = [GRPCChannel channelWithHost:host2 callOptions:options]; |
||||
GRPCChannel *channel3 = [GRPCChannel channelWithHost:host3 callOptions:options]; |
||||
GRPCChannel *channel4 = [GRPCChannel channelWithHost:host4 callOptions:options]; |
||||
GRPCChannel *channel5 = [GRPCChannel channelWithHost:host5 callOptions:options]; |
||||
XCTAssertNotEqual(channel1, channel2); |
||||
XCTAssertNotEqual(channel1, channel3); |
||||
XCTAssertNotEqual(channel1, channel4); |
||||
XCTAssertNotEqual(channel1, channel5); |
||||
} |
||||
|
||||
- (void)testDifferentChannelParameters { |
||||
NSString *host = @"grpc-test.sandbox.googleapis.com"; |
||||
GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; |
||||
options1.transportType = GRPCTransportTypeDefault; |
||||
NSMutableDictionary *args = [NSMutableDictionary new]; |
||||
args[@"abc"] = @"xyz"; |
||||
options1.additionalChannelArgs = [args copy]; |
||||
GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; |
||||
options2.transportType = GRPCTransportTypeInsecure; |
||||
options2.additionalChannelArgs = [args copy]; |
||||
GRPCMutableCallOptions *options3 = [[GRPCMutableCallOptions alloc] init]; |
||||
options3.transportType = GRPCTransportTypeDefault; |
||||
args[@"def"] = @"uvw"; |
||||
options3.additionalChannelArgs = [args copy]; |
||||
GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options1]; |
||||
GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options2]; |
||||
GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options3]; |
||||
XCTAssertNotEqual(channel1, channel2); |
||||
XCTAssertNotEqual(channel1, channel3); |
||||
} |
||||
|
||||
@end |
@ -0,0 +1,22 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>$(PRODUCT_NAME)</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>BNDL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>1.0</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>1</string> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,22 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>$(PRODUCT_NAME)</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>BNDL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>1.0</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>1</string> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,116 @@ |
||||
/* |
||||
* |
||||
* 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 <RemoteTest/Messages.pbobjc.h> |
||||
#import <RemoteTest/Test.pbobjc.h> |
||||
#import <RemoteTest/Test.pbrpc.h> |
||||
#import <RxLibrary/GRXBufferedPipe.h> |
||||
#import <RxLibrary/GRXWriter+Immediate.h> |
||||
#import <grpc/grpc.h> |
||||
|
||||
#define NSStringize_helper(x) #x |
||||
#define NSStringize(x) @NSStringize_helper(x) |
||||
static NSString *kRemoteHost = NSStringize(HOST_PORT_REMOTE); |
||||
const int32_t kRemoteInteropServerOverhead = 12; |
||||
|
||||
static const NSTimeInterval TEST_TIMEOUT = 16000; |
||||
|
||||
@interface InteropTestsCallOptions : XCTestCase |
||||
|
||||
@end |
||||
|
||||
@implementation InteropTestsCallOptions { |
||||
RMTTestService *_service; |
||||
} |
||||
|
||||
- (void)setUp { |
||||
self.continueAfterFailure = NO; |
||||
_service = [RMTTestService serviceWithHost:kRemoteHost]; |
||||
_service.options = [[GRPCCallOptions alloc] init]; |
||||
} |
||||
|
||||
- (void)test4MBResponsesAreAccepted { |
||||
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; |
||||
|
||||
RMTSimpleRequest *request = [RMTSimpleRequest message]; |
||||
const int32_t kPayloadSize = |
||||
4 * 1024 * 1024 - kRemoteInteropServerOverhead; // 4MB - encoding overhead |
||||
request.responseSize = kPayloadSize; |
||||
|
||||
[_service unaryCallWithRequest:request |
||||
handler:^(RMTSimpleResponse *response, NSError *error) { |
||||
XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
||||
XCTAssertEqual(response.payload.body.length, kPayloadSize); |
||||
[expectation fulfill]; |
||||
}]; |
||||
|
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
} |
||||
|
||||
- (void)testResponsesOverMaxSizeFailWithActionableMessage { |
||||
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; |
||||
|
||||
RMTSimpleRequest *request = [RMTSimpleRequest message]; |
||||
const int32_t kPayloadSize = |
||||
4 * 1024 * 1024 - kRemoteInteropServerOverhead + 1; // 1B over max size |
||||
request.responseSize = kPayloadSize; |
||||
|
||||
[_service unaryCallWithRequest:request |
||||
handler:^(RMTSimpleResponse *response, NSError *error) { |
||||
XCTAssertEqualObjects( |
||||
error.localizedDescription, |
||||
@"Received message larger than max (4194305 vs. 4194304)"); |
||||
[expectation fulfill]; |
||||
}]; |
||||
|
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
} |
||||
|
||||
- (void)testResponsesOver4MBAreAcceptedIfOptedIn { |
||||
__weak XCTestExpectation *expectation = |
||||
[self expectationWithDescription:@"HigherResponseSizeLimit"]; |
||||
|
||||
RMTSimpleRequest *request = [RMTSimpleRequest message]; |
||||
const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB |
||||
request.responseSize = kPayloadSize; |
||||
|
||||
GRPCProtoCall *rpc = [_service |
||||
RPCToUnaryCallWithRequest:request |
||||
handler:^(RMTSimpleResponse *response, NSError *error) { |
||||
XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
||||
XCTAssertEqual(response.payload.body.length, kPayloadSize); |
||||
[expectation fulfill]; |
||||
}]; |
||||
GRPCCallOptions *options = rpc.options; |
||||
options.responseSizeLimit = 6 * 1024 * 1024; |
||||
|
||||
[rpc start]; |
||||
|
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
} |
||||
|
||||
- (void)testPerformanceExample { |
||||
// This is an example of a performance test case. |
||||
[self measureBlock:^{ |
||||
// Put the code you want to measure the time of here. |
||||
}]; |
||||
} |
||||
|
||||
@end |
@ -0,0 +1,22 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>$(PRODUCT_NAME)</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>BNDL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>1.0</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>1</string> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,259 @@ |
||||
/* |
||||
* |
||||
* 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 <RemoteTest/Messages.pbobjc.h> |
||||
#import <RemoteTest/Test.pbobjc.h> |
||||
#import <RemoteTest/Test.pbrpc.h> |
||||
#import <RxLibrary/GRXBufferedPipe.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; |
||||
|
||||
// Default stack with remote host |
||||
_remoteService = [RMTTestService serviceWithHost:kRemoteSSLHost]; |
||||
|
||||
// Cronet stack with remote host |
||||
_remoteCronetService = [RMTTestService serviceWithHost:kRemoteSSLHost]; |
||||
|
||||
dispatch_once(&initCronet, ^{ |
||||
[Cronet setHttp2Enabled:YES]; |
||||
[Cronet start]; |
||||
}); |
||||
|
||||
GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; |
||||
options.transportType = GRPCTransportTypeCronet; |
||||
options.cronetEngine = [Cronet getGlobalEngine]; |
||||
_remoteCronetService.options = options; |
||||
|
||||
// Local stack with no SSL |
||||
_localCleartextService = [RMTTestService serviceWithHost:kLocalCleartextHost]; |
||||
options = [[GRPCCallOptions alloc] init]; |
||||
options.transportType = GRPCTransportTypeInsecure; |
||||
_localCleartextService.options = options; |
||||
|
||||
// Local stack with SSL |
||||
_localSSLService = [RMTTestService serviceWithHost:kLocalSSLHost]; |
||||
|
||||
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 = [[GRPCCallOptions alloc] init]; |
||||
options.transportType = GRPCTransportTypeDefault; |
||||
options.pemRootCert = certs; |
||||
options.hostNameOverride = @"foo.test.google.fr"; |
||||
_localSSLService.options = 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 (^handler)(GPBEmpty *response, NSError *error) = ^(GPBEmpty *response, NSError *error) { |
||||
XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
||||
|
||||
id expectedResponse = [GPBEmpty message]; |
||||
XCTAssertEqualObjects(response, expectedResponse); |
||||
}; |
||||
|
||||
[_remoteService emptyCallWithRequest:request |
||||
handler:^(GPBEmpty *response, NSError *error) { |
||||
handler(response, error); |
||||
[expectRemote fulfill]; |
||||
}]; |
||||
[_remoteCronetService emptyCallWithRequest:request |
||||
handler:^(GPBEmpty *response, NSError *error) { |
||||
handler(response, error); |
||||
[expectCronetRemote fulfill]; |
||||
}]; |
||||
[_localCleartextService emptyCallWithRequest:request |
||||
handler:^(GPBEmpty *response, NSError *error) { |
||||
handler(response, error); |
||||
[expectCleartext fulfill]; |
||||
}]; |
||||
[_localSSLService emptyCallWithRequest:request |
||||
handler:^(GPBEmpty *response, NSError *error) { |
||||
handler(response, error); |
||||
[expectSSL fulfill]; |
||||
}]; |
||||
|
||||
[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 *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]]; |
||||
} |
||||
|
||||
BOOL (^handler)(int, BOOL, RMTStreamingOutputCallResponse *, NSError *) = |
||||
^(int index, BOOL done, RMTStreamingOutputCallResponse *response, NSError *error) { |
||||
XCTAssertNil(error, @"Finished with unexpected error: %@", error); |
||||
XCTAssertTrue(done || response, @"Event handler called without an event."); |
||||
if (response) { |
||||
NSUInteger step = [steps[index] unsignedIntegerValue]; |
||||
XCTAssertLessThan(step, kRounds, @"More than %lu responses received.", |
||||
(unsigned long)kRounds); |
||||
XCTAssertEqualObjects(response, responses[step]); |
||||
step++; |
||||
steps[index] = [NSNumber numberWithUnsignedInteger:step]; |
||||
GRXBufferedPipe *pipe = requestsBuffers[index]; |
||||
if (step < kRounds) { |
||||
[pipe writeValue:requests[step]]; |
||||
} else { |
||||
[pipe writesFinishedWithError:nil]; |
||||
} |
||||
} |
||||
if (done) { |
||||
NSUInteger step = [steps[index] unsignedIntegerValue]; |
||||
XCTAssertEqual(step, kRounds, @"Received %lu responses instead of %lu.", step, kRounds); |
||||
return YES; |
||||
} |
||||
return NO; |
||||
}; |
||||
|
||||
[_remoteService |
||||
fullDuplexCallWithRequestsWriter:requestsBuffers[0] |
||||
eventHandler:^(BOOL done, |
||||
RMTStreamingOutputCallResponse *_Nullable response, |
||||
NSError *_Nullable error) { |
||||
if (handler(0, done, response, error)) { |
||||
[expectRemote fulfill]; |
||||
} |
||||
}]; |
||||
[_remoteCronetService |
||||
fullDuplexCallWithRequestsWriter:requestsBuffers[1] |
||||
eventHandler:^(BOOL done, |
||||
RMTStreamingOutputCallResponse *_Nullable response, |
||||
NSError *_Nullable error) { |
||||
if (handler(1, done, response, error)) { |
||||
[expectCronetRemote fulfill]; |
||||
} |
||||
}]; |
||||
[_localCleartextService |
||||
fullDuplexCallWithRequestsWriter:requestsBuffers[2] |
||||
eventHandler:^(BOOL done, |
||||
RMTStreamingOutputCallResponse *_Nullable response, |
||||
NSError *_Nullable error) { |
||||
if (handler(2, done, response, error)) { |
||||
[expectCleartext fulfill]; |
||||
} |
||||
}]; |
||||
[_localSSLService |
||||
fullDuplexCallWithRequestsWriter:requestsBuffers[3] |
||||
eventHandler:^(BOOL done, |
||||
RMTStreamingOutputCallResponse *_Nullable response, |
||||
NSError *_Nullable error) { |
||||
if (handler(3, done, response, error)) { |
||||
[expectSSL fulfill]; |
||||
} |
||||
}]; |
||||
|
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
} |
||||
|
||||
@end |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,92 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0930" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
<BuildActionEntries> |
||||
<BuildActionEntry |
||||
buildForTesting = "YES" |
||||
buildForRunning = "YES" |
||||
buildForProfiling = "NO" |
||||
buildForArchiving = "NO" |
||||
buildForAnalyzing = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EB2A2E32107DED300EB4B69" |
||||
BuildableName = "ChannelTests.xctest" |
||||
BlueprintName = "ChannelTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</BuildActionEntry> |
||||
</BuildActionEntries> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EB2A2E32107DED300EB4B69" |
||||
BuildableName = "ChannelTests.xctest" |
||||
BlueprintName = "ChannelTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<MacroExpansion> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EB2A2E32107DED300EB4B69" |
||||
BuildableName = "ChannelTests.xctest" |
||||
BlueprintName = "ChannelTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</MacroExpansion> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
<MacroExpansion> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EB2A2E32107DED300EB4B69" |
||||
BuildableName = "ChannelTests.xctest" |
||||
BlueprintName = "ChannelTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</MacroExpansion> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -0,0 +1,56 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0930" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Test" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E7D71B1210B9EC8001EA6BA" |
||||
BuildableName = "InteropTestsCallOptions.xctest" |
||||
BlueprintName = "InteropTestsCallOptions" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Test" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -0,0 +1,56 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0930" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Cronet" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EB2A2F42109284500EB4B69" |
||||
BuildableName = "InteropTestsMultipleChannels.xctest" |
||||
BlueprintName = "InteropTestsMultipleChannels" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Cronet" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
Loading…
Reference in new issue