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