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