mirror of https://github.com/grpc/grpc.git
parent
72a2b65d67
commit
89f0323744
8 changed files with 534 additions and 1 deletions
@ -0,0 +1,56 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2019 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> |
||||||
|
|
||||||
|
@interface StressTests : XCTestCase |
||||||
|
/**
|
||||||
|
* Host to send the RPCs to. The base implementation returns nil, which would make all tests to |
||||||
|
* fail. |
||||||
|
* Override in a subclass to perform these tests against a specific address. |
||||||
|
*/ |
||||||
|
+ (NSString *)host; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes of overhead of test proto responses due to encoding. This is used to excercise the behavior |
||||||
|
* when responses are just above or below the max response size. For some reason, the local and |
||||||
|
* remote servers enconde responses with different overhead (?), so this is defined per-subclass. |
||||||
|
*/ |
||||||
|
- (int32_t)encodingOverhead; |
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of transport to be used. The base implementation returns default. Subclasses should |
||||||
|
* override to appropriate settings. |
||||||
|
*/ |
||||||
|
+ (GRPCTransportType)transportType; |
||||||
|
|
||||||
|
/**
|
||||||
|
* The root certificates to be used. The base implementation returns nil. Subclasses should override |
||||||
|
* to appropriate settings. |
||||||
|
*/ |
||||||
|
+ (NSString *)PEMRootCertificates; |
||||||
|
|
||||||
|
/**
|
||||||
|
* The root certificates to be used. The base implementation returns nil. Subclasses should override |
||||||
|
* to appropriate settings. |
||||||
|
*/ |
||||||
|
+ (NSString *)hostNameOverride; |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,237 @@ |
|||||||
|
/* |
||||||
|
* |
||||||
|
* Copyright 2019 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
#include "StressTests.h" |
||||||
|
|
||||||
|
#import <GRPCClient/GRPCCall+ChannelArg.h> |
||||||
|
#import <GRPCClient/GRPCCall+Tests.h> |
||||||
|
#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h> |
||||||
|
#import <ProtoRPC/ProtoRPC.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> |
||||||
|
#import <grpc/support/log.h> |
||||||
|
|
||||||
|
#define TEST_TIMEOUT 32 |
||||||
|
|
||||||
|
extern const char *kCFStreamVarName; |
||||||
|
|
||||||
|
// Convenience class to use blocks as callbacks |
||||||
|
@interface MacTestsBlockCallbacks : NSObject<GRPCProtoResponseHandler> |
||||||
|
|
||||||
|
- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback |
||||||
|
messageCallback:(void (^)(id))messageCallback |
||||||
|
closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback; |
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
@implementation MacTestsBlockCallbacks { |
||||||
|
void (^_initialMetadataCallback)(NSDictionary *); |
||||||
|
void (^_messageCallback)(id); |
||||||
|
void (^_closeCallback)(NSDictionary *, NSError *); |
||||||
|
dispatch_queue_t _dispatchQueue; |
||||||
|
} |
||||||
|
|
||||||
|
- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback |
||||||
|
messageCallback:(void (^)(id))messageCallback |
||||||
|
closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback { |
||||||
|
if ((self = [super init])) { |
||||||
|
_initialMetadataCallback = initialMetadataCallback; |
||||||
|
_messageCallback = messageCallback; |
||||||
|
_closeCallback = closeCallback; |
||||||
|
_dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); |
||||||
|
} |
||||||
|
return self; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { |
||||||
|
if (_initialMetadataCallback) { |
||||||
|
_initialMetadataCallback(initialMetadata); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (void)didReceiveProtoMessage:(GPBMessage *)message { |
||||||
|
if (_messageCallback) { |
||||||
|
_messageCallback(message); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { |
||||||
|
if (_closeCallback) { |
||||||
|
_closeCallback(trailingMetadata, error); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
- (dispatch_queue_t)dispatchQueue { |
||||||
|
return _dispatchQueue; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
||||||
|
|
||||||
|
@implementation StressTests { |
||||||
|
RMTTestService *_service; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)host { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostAddress { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)PEMRootCertificates { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostNameOverride { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
- (int32_t)encodingOverhead { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
+ (void)setUp { |
||||||
|
setenv(kCFStreamVarName, "1", 1); |
||||||
|
} |
||||||
|
|
||||||
|
- (void)setUp { |
||||||
|
self.continueAfterFailure = NO; |
||||||
|
|
||||||
|
[GRPCCall resetHostSettings]; |
||||||
|
|
||||||
|
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; |
||||||
|
options.transportType = [[self class] transportType]; |
||||||
|
options.PEMRootCertificates = [[self class] PEMRootCertificates]; |
||||||
|
options.hostNameOverride = [[self class] hostNameOverride]; |
||||||
|
_service = [RMTTestService serviceWithHost:[[self class] host] callOptions:options]; |
||||||
|
system([[NSString stringWithFormat:@"sudo ifconfig lo0 alias %@", [[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
} |
||||||
|
|
||||||
|
- (void)tearDown { |
||||||
|
system([[NSString stringWithFormat:@"sudo ifconfig lo0 -alias %@", [[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
} |
||||||
|
|
||||||
|
+ (GRPCTransportType)transportType { |
||||||
|
return GRPCTransportTypeChttp2BoringSSL; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)testNetworkFlapWithV2API { |
||||||
|
NSMutableArray *completeExpectations = [NSMutableArray array]; |
||||||
|
NSMutableArray *calls = [NSMutableArray array]; |
||||||
|
int num_rpcs = 100; |
||||||
|
__block BOOL address_removed = FALSE; |
||||||
|
__block BOOL address_readded = FALSE; |
||||||
|
for (int i = 0; i < num_rpcs; ++i) { |
||||||
|
[completeExpectations |
||||||
|
addObject:[self expectationWithDescription: |
||||||
|
[NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; |
||||||
|
|
||||||
|
RMTSimpleRequest *request = [RMTSimpleRequest message]; |
||||||
|
request.responseType = RMTPayloadType_Compressable; |
||||||
|
request.responseSize = 314159; |
||||||
|
request.payload.body = [NSMutableData dataWithLength:271828]; |
||||||
|
|
||||||
|
GRPCUnaryProtoCall *call = [_service |
||||||
|
unaryCallWithMessage:request |
||||||
|
responseHandler:[[MacTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil |
||||||
|
messageCallback:^(id message) { |
||||||
|
if (message) { |
||||||
|
RMTSimpleResponse *expectedResponse = |
||||||
|
[RMTSimpleResponse message]; |
||||||
|
expectedResponse.payload.type = RMTPayloadType_Compressable; |
||||||
|
expectedResponse.payload.body = |
||||||
|
[NSMutableData dataWithLength:314159]; |
||||||
|
XCTAssertEqualObjects(message, expectedResponse); |
||||||
|
} |
||||||
|
} |
||||||
|
closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { |
||||||
|
|
||||||
|
@synchronized(self) { |
||||||
|
if (error == nil && !address_removed) { |
||||||
|
system([[NSString |
||||||
|
stringWithFormat:@"sudo ifconfig lo0 -alias %@", |
||||||
|
[[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
address_removed = YES; |
||||||
|
} else if (error != nil && !address_readded) { |
||||||
|
system([ |
||||||
|
[NSString stringWithFormat:@"sudo ifconfig lo0 alias %@", |
||||||
|
[[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
address_readded = YES; |
||||||
|
} |
||||||
|
} |
||||||
|
[completeExpectations[i] fulfill]; |
||||||
|
}] |
||||||
|
callOptions:nil]; |
||||||
|
[calls addObject:call]; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < num_rpcs; ++i) { |
||||||
|
GRPCUnaryProtoCall *call = calls[i]; |
||||||
|
[call start]; |
||||||
|
[NSThread sleepForTimeInterval:0.1f]; |
||||||
|
} |
||||||
|
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)testNetworkFlapWithV1API { |
||||||
|
NSMutableArray *completeExpectations = [NSMutableArray array]; |
||||||
|
int num_rpcs = 100; |
||||||
|
__block BOOL address_removed = FALSE; |
||||||
|
__block BOOL address_readded = FALSE; |
||||||
|
for (int i = 0; i < num_rpcs; ++i) { |
||||||
|
[completeExpectations |
||||||
|
addObject:[self expectationWithDescription: |
||||||
|
[NSString stringWithFormat:@"Received response for RPC %d", i]]]; |
||||||
|
|
||||||
|
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) { |
||||||
|
@synchronized(self) { |
||||||
|
if (error == nil && !address_removed) { |
||||||
|
system([[NSString stringWithFormat:@"sudo ifconfig lo0 -alias %@", |
||||||
|
[[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
address_removed = YES; |
||||||
|
} else if (error != nil && !address_readded) { |
||||||
|
system([[NSString stringWithFormat:@"sudo ifconfig lo0 alias %@", |
||||||
|
[[self class] hostAddress]] |
||||||
|
UTF8String]); |
||||||
|
address_readded = YES; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[completeExpectations[i] fulfill]; |
||||||
|
}]; |
||||||
|
|
||||||
|
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,68 @@ |
|||||||
|
|
||||||
|
/* |
||||||
|
* |
||||||
|
* Copyright 2019 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 <GRPCClient/GRPCCall+Tests.h> |
||||||
|
#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h> |
||||||
|
|
||||||
|
#import "StressTests.h" |
||||||
|
|
||||||
|
static NSString *const kHostAddress = @"10.0.0.1"; |
||||||
|
|
||||||
|
// The Protocol Buffers encoding overhead of local interop server. Acquired |
||||||
|
// by experiment. Adjust this when server's proto file changes. |
||||||
|
static int32_t kLocalInteropServerOverhead = 10; |
||||||
|
|
||||||
|
/** Tests in InteropTests.m, sending the RPCs to a local cleartext server. */ |
||||||
|
@interface StressTestsCleartext : StressTests |
||||||
|
@end |
||||||
|
|
||||||
|
@implementation StressTestsCleartext |
||||||
|
|
||||||
|
+ (NSString *)host { |
||||||
|
return [NSString stringWithFormat:@"%@:5050", kHostAddress]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostAddress { |
||||||
|
return kHostAddress; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)PEMRootCertificates { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostNameOverride { |
||||||
|
return nil; |
||||||
|
} |
||||||
|
|
||||||
|
- (int32_t)encodingOverhead { |
||||||
|
return kLocalInteropServerOverhead; // bytes |
||||||
|
} |
||||||
|
|
||||||
|
- (void)setUp { |
||||||
|
[super setUp]; |
||||||
|
|
||||||
|
// Register test server as non-SSL. |
||||||
|
[GRPCCall useInsecureConnectionsForHost:[[self class] host]]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (GRPCTransportType)transportType { |
||||||
|
return GRPCTransportTypeInsecure; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* |
||||||
|
* Copyright 2019 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 <GRPCClient/GRPCCall+Tests.h> |
||||||
|
#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h> |
||||||
|
|
||||||
|
#include "StressTests.h" |
||||||
|
|
||||||
|
static NSString *const kHostAddress = @"10.0.0.1"; |
||||||
|
// The Protocol Buffers encoding overhead of local interop server. Acquired |
||||||
|
// by experiment. Adjust this when server's proto file changes. |
||||||
|
static int32_t kLocalInteropServerOverhead = 10; |
||||||
|
|
||||||
|
@interface StressTestsSSL : StressTests |
||||||
|
@end |
||||||
|
|
||||||
|
@implementation StressTestsSSL |
||||||
|
|
||||||
|
+ (NSString *)host { |
||||||
|
return [NSString stringWithFormat:@"%@:5051", kHostAddress]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostAddress { |
||||||
|
return kHostAddress; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)PEMRootCertificates { |
||||||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; |
||||||
|
NSString *certsPath = |
||||||
|
[bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; |
||||||
|
NSError *error; |
||||||
|
return [NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (NSString *)hostNameOverride { |
||||||
|
return @"foo.test.google.fr"; |
||||||
|
} |
||||||
|
|
||||||
|
- (int32_t)encodingOverhead { |
||||||
|
return kLocalInteropServerOverhead; // bytes |
||||||
|
} |
||||||
|
|
||||||
|
+ (GRPCTransportType)transportType { |
||||||
|
return GRPCTransportTypeChttp2BoringSSL; |
||||||
|
} |
||||||
|
|
||||||
|
- (void)setUp { |
||||||
|
[super setUp]; |
||||||
|
|
||||||
|
// Register test server certificates and name. |
||||||
|
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; |
||||||
|
NSString *certsPath = |
||||||
|
[bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; |
||||||
|
[GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:[[self class] host]]; |
||||||
|
} |
||||||
|
@end |
Loading…
Reference in new issue