mirror of https://github.com/grpc/grpc.git
parent
1bfdbc1f6c
commit
35a1f0a963
6 changed files with 264 additions and 1 deletions
@ -0,0 +1,232 @@ |
||||
/* |
||||
* |
||||
* 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.h> |
||||
#import <GRPCClient/GRPCInterceptor.h> |
||||
#import <GRPCClient/GRPCTransport.h> |
||||
#import <XCTest/XCTest.h> |
||||
|
||||
#define TEST_TIMEOUT (8.0) |
||||
|
||||
static NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com:443"; |
||||
|
||||
static const GRPCTransportID kFakeTransportID = "io.grpc.transport.unittest.fake"; |
||||
|
||||
@class GRPCFakeTransportFactory; |
||||
dispatch_once_t initFakeTransportFactory; |
||||
static GRPCFakeTransportFactory *fakeTransportFactory; |
||||
|
||||
@interface GRPCFakeTransportFactory : NSObject<GRPCTransportFactory> |
||||
|
||||
@property(atomic) GRPCTransport *nextTransportInstance; |
||||
- (void)setTransportInterceptorFactories:(NSArray<id<GRPCInterceptorFactory>> *)factories; |
||||
|
||||
@end |
||||
|
||||
@implementation GRPCFakeTransportFactory { |
||||
NSArray<id<GRPCInterceptorFactory>> *_interceptorFactories; |
||||
} |
||||
|
||||
+ (instancetype)sharedInstance { |
||||
dispatch_once(&initFakeTransportFactory, ^{ |
||||
fakeTransportFactory = [[GRPCFakeTransportFactory alloc] init]; |
||||
}); |
||||
return fakeTransportFactory; |
||||
} |
||||
|
||||
+ (void)load { |
||||
[[GRPCTransportRegistry sharedInstance] registerTransportWithID:kFakeTransportID |
||||
factory:[self sharedInstance]]; |
||||
} |
||||
|
||||
- (GRPCTransport *)createTransportWithManager:(GRPCTransportManager *)transportManager { |
||||
return _nextTransportInstance; |
||||
} |
||||
|
||||
- (void)setTransportInterceptorFactories:(NSArray<id<GRPCInterceptorFactory>> *)factories { |
||||
_interceptorFactories = [NSArray arrayWithArray:factories]; |
||||
} |
||||
|
||||
- (NSArray<id<GRPCInterceptorFactory>> *)transportInterceptorFactories { |
||||
return _interceptorFactories; |
||||
} |
||||
|
||||
@end |
||||
|
||||
@interface DummyInterceptor : GRPCInterceptor |
||||
|
||||
@property(atomic) BOOL hit; |
||||
|
||||
@end |
||||
|
||||
@implementation DummyInterceptor { |
||||
GRPCInterceptorManager *_manager; |
||||
} |
||||
|
||||
- (instancetype)initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager |
||||
dispatchQueue:(dispatch_queue_t)dispatchQueue { |
||||
if (dispatchQueue == nil) { |
||||
dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); |
||||
} |
||||
if ((self = [super initWithInterceptorManager:interceptorManager dispatchQueue:dispatchQueue])) { |
||||
_manager = interceptorManager; |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions |
||||
callOptions:(GRPCCallOptions *)callOptions { |
||||
self.hit = YES; |
||||
[_manager |
||||
forwardPreviousInterceptorCloseWithTrailingMetadata:nil |
||||
error:[NSError |
||||
errorWithDomain:kGRPCErrorDomain |
||||
code:GRPCErrorCodeCancelled |
||||
userInfo:@{ |
||||
NSLocalizedDescriptionKey : |
||||
@"Canceled." |
||||
}]]; |
||||
[_manager shutDown]; |
||||
} |
||||
|
||||
@end |
||||
|
||||
@interface DummyInterceptorFactory : NSObject<GRPCInterceptorFactory> |
||||
|
||||
+ (instancetype)sharedInstance; |
||||
|
||||
@end |
||||
|
||||
static DummyInterceptorFactory *dummyInterceptorFactory; |
||||
static dispatch_once_t initDummyInterceptorFactory; |
||||
|
||||
@implementation DummyInterceptorFactory |
||||
|
||||
+ (instancetype)sharedInstance { |
||||
dispatch_once(&initDummyInterceptorFactory, ^{ |
||||
dummyInterceptorFactory = [[DummyInterceptorFactory alloc] init]; |
||||
}); |
||||
return dummyInterceptorFactory; |
||||
} |
||||
|
||||
- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager { |
||||
return [[DummyInterceptor alloc] |
||||
initWithInterceptorManager:interceptorManager |
||||
dispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL)]; |
||||
} |
||||
|
||||
@end |
||||
|
||||
@interface TestsBlockCallbacks : NSObject<GRPCResponseHandler> |
||||
|
||||
- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback |
||||
dataCallback:(void (^)(id))dataCallback |
||||
closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback |
||||
writeMessageCallback:(void (^)(void))writeMessageCallback; |
||||
|
||||
@end |
||||
|
||||
@implementation TestsBlockCallbacks { |
||||
void (^_initialMetadataCallback)(NSDictionary *); |
||||
void (^_dataCallback)(id); |
||||
void (^_closeCallback)(NSDictionary *, NSError *); |
||||
void (^_writeMessageCallback)(void); |
||||
dispatch_queue_t _dispatchQueue; |
||||
} |
||||
|
||||
- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback |
||||
dataCallback:(void (^)(id))dataCallback |
||||
closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback |
||||
writeMessageCallback:(void (^)(void))writeMessageCallback { |
||||
if ((self = [super init])) { |
||||
_initialMetadataCallback = initialMetadataCallback; |
||||
_dataCallback = dataCallback; |
||||
_closeCallback = closeCallback; |
||||
_writeMessageCallback = writeMessageCallback; |
||||
_dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { |
||||
if (_initialMetadataCallback) { |
||||
_initialMetadataCallback(initialMetadata); |
||||
} |
||||
} |
||||
|
||||
- (void)didReceiveProtoMessage:(id)message { |
||||
if (_dataCallback) { |
||||
_dataCallback(message); |
||||
} |
||||
} |
||||
|
||||
- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { |
||||
if (_closeCallback) { |
||||
_closeCallback(trailingMetadata, error); |
||||
} |
||||
} |
||||
|
||||
- (void)didWriteMessage { |
||||
if (_writeMessageCallback) { |
||||
_writeMessageCallback(); |
||||
} |
||||
} |
||||
|
||||
- (dispatch_queue_t)dispatchQueue { |
||||
return _dispatchQueue; |
||||
} |
||||
@end |
||||
|
||||
@interface TransportTests : XCTestCase |
||||
|
||||
@end |
||||
|
||||
@implementation TransportTests |
||||
|
||||
- (void)testTransportInterceptors { |
||||
__weak XCTestExpectation *expectComplete = |
||||
[self expectationWithDescription:@"Expect call complete"]; |
||||
[GRPCFakeTransportFactory sharedInstance].nextTransportInstance = nil; |
||||
|
||||
[[GRPCFakeTransportFactory sharedInstance] |
||||
setTransportInterceptorFactories:@[ [DummyInterceptorFactory sharedInstance] ]]; |
||||
GRPCRequestOptions *requestOptions = |
||||
[[GRPCRequestOptions alloc] initWithHost:kRemoteHost |
||||
path:@"/UnaryCall" |
||||
safety:GRPCCallSafetyDefault]; |
||||
GRPCMutableCallOptions *callOptions = [[GRPCMutableCallOptions alloc] init]; |
||||
callOptions.transport = kFakeTransportID; |
||||
GRPCCall2 *call = [[GRPCCall2 alloc] |
||||
initWithRequestOptions:requestOptions |
||||
responseHandler:[[TestsBlockCallbacks alloc] |
||||
initWithInitialMetadataCallback:nil |
||||
dataCallback:nil |
||||
closeCallback:^(NSDictionary *trailingMetadata, |
||||
NSError *error) { |
||||
XCTAssertNotNil(error); |
||||
XCTAssertEqual(error.code, |
||||
GRPCErrorCodeCancelled); |
||||
[expectComplete fulfill]; |
||||
} |
||||
writeMessageCallback:nil] |
||||
callOptions:callOptions]; |
||||
[call start]; |
||||
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; |
||||
} |
||||
|
||||
@end |
Loading…
Reference in new issue