1*cc02d7e2SAndroid Build Coastguard Worker/* 2*cc02d7e2SAndroid Build Coastguard Worker * 3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2015 gRPC authors. 4*cc02d7e2SAndroid Build Coastguard Worker * 5*cc02d7e2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker * You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker * 9*cc02d7e2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker * 11*cc02d7e2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker * limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker * 17*cc02d7e2SAndroid Build Coastguard Worker */ 18*cc02d7e2SAndroid Build Coastguard Worker 19*cc02d7e2SAndroid Build Coastguard Worker#import "InteropTests.h" 20*cc02d7e2SAndroid Build Coastguard Worker 21*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/status.h> 22*cc02d7e2SAndroid Build Coastguard Worker 23*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCCall+ChannelArg.h> 24*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCCall+Cronet.h> 25*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCCall+Interceptor.h> 26*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCCall+Tests.h> 27*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/GRPCInterceptor.h> 28*cc02d7e2SAndroid Build Coastguard Worker#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h> 29*cc02d7e2SAndroid Build Coastguard Worker#import <ProtoRPC/ProtoRPC.h> 30*cc02d7e2SAndroid Build Coastguard Worker#import <RxLibrary/GRXBufferedPipe.h> 31*cc02d7e2SAndroid Build Coastguard Worker#import <RxLibrary/GRXWriter+Immediate.h> 32*cc02d7e2SAndroid Build Coastguard Worker#import <grpc/grpc.h> 33*cc02d7e2SAndroid Build Coastguard Worker#import <grpc/support/log.h> 34*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Messages.pbobjc.h" 35*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Test.pbobjc.h" 36*cc02d7e2SAndroid Build Coastguard Worker#import "src/objective-c/tests/RemoteTestClient/Test.pbrpc.h" 37*cc02d7e2SAndroid Build Coastguard Worker 38*cc02d7e2SAndroid Build Coastguard Worker#import "../Common/TestUtils.h" 39*cc02d7e2SAndroid Build Coastguard Worker#import "InteropTestsBlockCallbacks.h" 40*cc02d7e2SAndroid Build Coastguard Worker 41*cc02d7e2SAndroid Build Coastguard Worker#define SMALL_PAYLOAD_SIZE 10 42*cc02d7e2SAndroid Build Coastguard Worker#define LARGE_REQUEST_PAYLOAD_SIZE 271828 43*cc02d7e2SAndroid Build Coastguard Worker#define LARGE_RESPONSE_PAYLOAD_SIZE 314159 44*cc02d7e2SAndroid Build Coastguard Worker 45*cc02d7e2SAndroid Build Coastguard Workerstatic const int kTestRetries = 3; 46*cc02d7e2SAndroid Build Coastguard Workerextern const char *kCFStreamVarName; 47*cc02d7e2SAndroid Build Coastguard Worker 48*cc02d7e2SAndroid Build Coastguard Worker@interface RMTStreamingOutputCallRequest (Constructors) 49*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize 50*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:(NSNumber *)responseSize; 51*cc02d7e2SAndroid Build Coastguard Worker@end 52*cc02d7e2SAndroid Build Coastguard Worker 53*cc02d7e2SAndroid Build Coastguard Worker@implementation RMTStreamingOutputCallRequest (Constructors) 54*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize 55*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:(NSNumber *)responseSize { 56*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingOutputCallRequest *request = [self message]; 57*cc02d7e2SAndroid Build Coastguard Worker RMTResponseParameters *parameters = [RMTResponseParameters message]; 58*cc02d7e2SAndroid Build Coastguard Worker parameters.size = responseSize.intValue; 59*cc02d7e2SAndroid Build Coastguard Worker [request.responseParametersArray addObject:parameters]; 60*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; 61*cc02d7e2SAndroid Build Coastguard Worker return request; 62*cc02d7e2SAndroid Build Coastguard Worker} 63*cc02d7e2SAndroid Build Coastguard Worker@end 64*cc02d7e2SAndroid Build Coastguard Worker 65*cc02d7e2SAndroid Build Coastguard Worker@interface RMTStreamingOutputCallResponse (Constructors) 66*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; 67*cc02d7e2SAndroid Build Coastguard Worker@end 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Worker@implementation RMTStreamingOutputCallResponse (Constructors) 70*cc02d7e2SAndroid Build Coastguard Worker+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { 71*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingOutputCallResponse *response = [self message]; 72*cc02d7e2SAndroid Build Coastguard Worker response.payload.type = RMTPayloadType_Compressable; 73*cc02d7e2SAndroid Build Coastguard Worker response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; 74*cc02d7e2SAndroid Build Coastguard Worker return response; 75*cc02d7e2SAndroid Build Coastguard Worker} 76*cc02d7e2SAndroid Build Coastguard Worker@end 77*cc02d7e2SAndroid Build Coastguard Worker 78*cc02d7e2SAndroid Build Coastguard WorkerBOOL isRemoteInteropTest(NSString *host) { 79*cc02d7e2SAndroid Build Coastguard Worker return [host isEqualToString:@"grpc-test.sandbox.googleapis.com"]; 80*cc02d7e2SAndroid Build Coastguard Worker} 81*cc02d7e2SAndroid Build Coastguard Worker 82*cc02d7e2SAndroid Build Coastguard Worker@interface DefaultInterceptorFactory : NSObject <GRPCInterceptorFactory> 83*cc02d7e2SAndroid Build Coastguard Worker 84*cc02d7e2SAndroid Build Coastguard Worker- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager; 85*cc02d7e2SAndroid Build Coastguard Worker 86*cc02d7e2SAndroid Build Coastguard Worker@end 87*cc02d7e2SAndroid Build Coastguard Worker 88*cc02d7e2SAndroid Build Coastguard Worker@implementation DefaultInterceptorFactory 89*cc02d7e2SAndroid Build Coastguard Worker 90*cc02d7e2SAndroid Build Coastguard Worker- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager { 91*cc02d7e2SAndroid Build Coastguard Worker dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); 92*cc02d7e2SAndroid Build Coastguard Worker return [[GRPCInterceptor alloc] initWithInterceptorManager:interceptorManager 93*cc02d7e2SAndroid Build Coastguard Worker dispatchQueue:queue]; 94*cc02d7e2SAndroid Build Coastguard Worker} 95*cc02d7e2SAndroid Build Coastguard Worker 96*cc02d7e2SAndroid Build Coastguard Worker@end 97*cc02d7e2SAndroid Build Coastguard Worker 98*cc02d7e2SAndroid Build Coastguard Worker@interface HookInterceptorFactory : NSObject <GRPCInterceptorFactory> 99*cc02d7e2SAndroid Build Coastguard Worker 100*cc02d7e2SAndroid Build Coastguard Worker- (instancetype) 101*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:(dispatch_queue_t)dispatchQueue 102*cc02d7e2SAndroid Build Coastguard Worker startHook:(void (^)(GRPCRequestOptions *requestOptions, 103*cc02d7e2SAndroid Build Coastguard Worker GRPCCallOptions *callOptions, 104*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 105*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 106*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 107*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 108*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 109*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 110*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 111*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 112*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 113*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 114*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook; 115*cc02d7e2SAndroid Build Coastguard Worker 116*cc02d7e2SAndroid Build Coastguard Worker- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager; 117*cc02d7e2SAndroid Build Coastguard Worker 118*cc02d7e2SAndroid Build Coastguard Worker@end 119*cc02d7e2SAndroid Build Coastguard Worker 120*cc02d7e2SAndroid Build Coastguard Worker@interface HookInterceptor : GRPCInterceptor 121*cc02d7e2SAndroid Build Coastguard Worker 122*cc02d7e2SAndroid Build Coastguard Worker- (instancetype) 123*cc02d7e2SAndroid Build Coastguard Worker initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager 124*cc02d7e2SAndroid Build Coastguard Worker dispatchQueue:(dispatch_queue_t)dispatchQueue 125*cc02d7e2SAndroid Build Coastguard Worker startHook:(void (^)(GRPCRequestOptions *requestOptions, 126*cc02d7e2SAndroid Build Coastguard Worker GRPCCallOptions *callOptions, 127*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 128*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 129*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 130*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 131*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 132*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 133*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 134*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 135*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 136*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 137*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook; 138*cc02d7e2SAndroid Build Coastguard Worker 139*cc02d7e2SAndroid Build Coastguard Worker@end 140*cc02d7e2SAndroid Build Coastguard Worker 141*cc02d7e2SAndroid Build Coastguard Worker@implementation HookInterceptorFactory { 142*cc02d7e2SAndroid Build Coastguard Worker @protected 143*cc02d7e2SAndroid Build Coastguard Worker void (^_startHook)(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 144*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager); 145*cc02d7e2SAndroid Build Coastguard Worker void (^_writeDataHook)(id data, GRPCInterceptorManager *manager); 146*cc02d7e2SAndroid Build Coastguard Worker void (^_finishHook)(GRPCInterceptorManager *manager); 147*cc02d7e2SAndroid Build Coastguard Worker void (^_receiveNextMessagesHook)(NSUInteger numberOfMessages, GRPCInterceptorManager *manager); 148*cc02d7e2SAndroid Build Coastguard Worker void (^_responseHeaderHook)(NSDictionary *initialMetadata, GRPCInterceptorManager *manager); 149*cc02d7e2SAndroid Build Coastguard Worker void (^_responseDataHook)(id data, GRPCInterceptorManager *manager); 150*cc02d7e2SAndroid Build Coastguard Worker void (^_responseCloseHook)(NSDictionary *trailingMetadata, NSError *error, 151*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager); 152*cc02d7e2SAndroid Build Coastguard Worker void (^_didWriteDataHook)(GRPCInterceptorManager *manager); 153*cc02d7e2SAndroid Build Coastguard Worker dispatch_queue_t _dispatchQueue; 154*cc02d7e2SAndroid Build Coastguard Worker} 155*cc02d7e2SAndroid Build Coastguard Worker 156*cc02d7e2SAndroid Build Coastguard Worker- (instancetype) 157*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:(dispatch_queue_t)dispatchQueue 158*cc02d7e2SAndroid Build Coastguard Worker startHook:(void (^)(GRPCRequestOptions *requestOptions, 159*cc02d7e2SAndroid Build Coastguard Worker GRPCCallOptions *callOptions, 160*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 161*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 162*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 163*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 164*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 165*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 166*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 167*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 168*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 169*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 170*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook { 171*cc02d7e2SAndroid Build Coastguard Worker if ((self = [super init])) { 172*cc02d7e2SAndroid Build Coastguard Worker _dispatchQueue = dispatchQueue; 173*cc02d7e2SAndroid Build Coastguard Worker _startHook = startHook; 174*cc02d7e2SAndroid Build Coastguard Worker _writeDataHook = writeDataHook; 175*cc02d7e2SAndroid Build Coastguard Worker _finishHook = finishHook; 176*cc02d7e2SAndroid Build Coastguard Worker _receiveNextMessagesHook = receiveNextMessagesHook; 177*cc02d7e2SAndroid Build Coastguard Worker _responseHeaderHook = responseHeaderHook; 178*cc02d7e2SAndroid Build Coastguard Worker _responseDataHook = responseDataHook; 179*cc02d7e2SAndroid Build Coastguard Worker _responseCloseHook = responseCloseHook; 180*cc02d7e2SAndroid Build Coastguard Worker _didWriteDataHook = didWriteDataHook; 181*cc02d7e2SAndroid Build Coastguard Worker } 182*cc02d7e2SAndroid Build Coastguard Worker return self; 183*cc02d7e2SAndroid Build Coastguard Worker} 184*cc02d7e2SAndroid Build Coastguard Worker 185*cc02d7e2SAndroid Build Coastguard Worker- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager { 186*cc02d7e2SAndroid Build Coastguard Worker return [[HookInterceptor alloc] initWithInterceptorManager:interceptorManager 187*cc02d7e2SAndroid Build Coastguard Worker dispatchQueue:_dispatchQueue 188*cc02d7e2SAndroid Build Coastguard Worker startHook:_startHook 189*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:_writeDataHook 190*cc02d7e2SAndroid Build Coastguard Worker finishHook:_finishHook 191*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:_receiveNextMessagesHook 192*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:_responseHeaderHook 193*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:_responseDataHook 194*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:_responseCloseHook 195*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:_didWriteDataHook]; 196*cc02d7e2SAndroid Build Coastguard Worker} 197*cc02d7e2SAndroid Build Coastguard Worker 198*cc02d7e2SAndroid Build Coastguard Worker@end 199*cc02d7e2SAndroid Build Coastguard Worker 200*cc02d7e2SAndroid Build Coastguard Worker@implementation HookInterceptor { 201*cc02d7e2SAndroid Build Coastguard Worker void (^_startHook)(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 202*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager); 203*cc02d7e2SAndroid Build Coastguard Worker void (^_writeDataHook)(id data, GRPCInterceptorManager *manager); 204*cc02d7e2SAndroid Build Coastguard Worker void (^_finishHook)(GRPCInterceptorManager *manager); 205*cc02d7e2SAndroid Build Coastguard Worker void (^_receiveNextMessagesHook)(NSUInteger numberOfMessages, GRPCInterceptorManager *manager); 206*cc02d7e2SAndroid Build Coastguard Worker void (^_responseHeaderHook)(NSDictionary *initialMetadata, GRPCInterceptorManager *manager); 207*cc02d7e2SAndroid Build Coastguard Worker void (^_responseDataHook)(id data, GRPCInterceptorManager *manager); 208*cc02d7e2SAndroid Build Coastguard Worker void (^_responseCloseHook)(NSDictionary *trailingMetadata, NSError *error, 209*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager); 210*cc02d7e2SAndroid Build Coastguard Worker void (^_didWriteDataHook)(GRPCInterceptorManager *manager); 211*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *_manager; 212*cc02d7e2SAndroid Build Coastguard Worker dispatch_queue_t _dispatchQueue; 213*cc02d7e2SAndroid Build Coastguard Worker} 214*cc02d7e2SAndroid Build Coastguard Worker 215*cc02d7e2SAndroid Build Coastguard Worker- (dispatch_queue_t)dispatchQueue { 216*cc02d7e2SAndroid Build Coastguard Worker return _dispatchQueue; 217*cc02d7e2SAndroid Build Coastguard Worker} 218*cc02d7e2SAndroid Build Coastguard Worker 219*cc02d7e2SAndroid Build Coastguard Worker- (instancetype) 220*cc02d7e2SAndroid Build Coastguard Worker initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager 221*cc02d7e2SAndroid Build Coastguard Worker dispatchQueue:(dispatch_queue_t)dispatchQueue 222*cc02d7e2SAndroid Build Coastguard Worker startHook:(void (^)(GRPCRequestOptions *requestOptions, 223*cc02d7e2SAndroid Build Coastguard Worker GRPCCallOptions *callOptions, 224*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 225*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 226*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 227*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 228*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 229*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 230*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 231*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 232*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 233*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 234*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook { 235*cc02d7e2SAndroid Build Coastguard Worker if ((self = [super initWithInterceptorManager:interceptorManager dispatchQueue:dispatchQueue])) { 236*cc02d7e2SAndroid Build Coastguard Worker _startHook = startHook; 237*cc02d7e2SAndroid Build Coastguard Worker _writeDataHook = writeDataHook; 238*cc02d7e2SAndroid Build Coastguard Worker _finishHook = finishHook; 239*cc02d7e2SAndroid Build Coastguard Worker _receiveNextMessagesHook = receiveNextMessagesHook; 240*cc02d7e2SAndroid Build Coastguard Worker _responseHeaderHook = responseHeaderHook; 241*cc02d7e2SAndroid Build Coastguard Worker _responseDataHook = responseDataHook; 242*cc02d7e2SAndroid Build Coastguard Worker _responseCloseHook = responseCloseHook; 243*cc02d7e2SAndroid Build Coastguard Worker _didWriteDataHook = didWriteDataHook; 244*cc02d7e2SAndroid Build Coastguard Worker _dispatchQueue = dispatchQueue; 245*cc02d7e2SAndroid Build Coastguard Worker _manager = interceptorManager; 246*cc02d7e2SAndroid Build Coastguard Worker } 247*cc02d7e2SAndroid Build Coastguard Worker return self; 248*cc02d7e2SAndroid Build Coastguard Worker} 249*cc02d7e2SAndroid Build Coastguard Worker 250*cc02d7e2SAndroid Build Coastguard Worker- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions 251*cc02d7e2SAndroid Build Coastguard Worker callOptions:(GRPCCallOptions *)callOptions { 252*cc02d7e2SAndroid Build Coastguard Worker if (_startHook) { 253*cc02d7e2SAndroid Build Coastguard Worker _startHook(requestOptions, callOptions, _manager); 254*cc02d7e2SAndroid Build Coastguard Worker } 255*cc02d7e2SAndroid Build Coastguard Worker} 256*cc02d7e2SAndroid Build Coastguard Worker 257*cc02d7e2SAndroid Build Coastguard Worker- (void)writeData:(id)data { 258*cc02d7e2SAndroid Build Coastguard Worker if (_writeDataHook) { 259*cc02d7e2SAndroid Build Coastguard Worker _writeDataHook(data, _manager); 260*cc02d7e2SAndroid Build Coastguard Worker } 261*cc02d7e2SAndroid Build Coastguard Worker} 262*cc02d7e2SAndroid Build Coastguard Worker 263*cc02d7e2SAndroid Build Coastguard Worker- (void)finish { 264*cc02d7e2SAndroid Build Coastguard Worker if (_finishHook) { 265*cc02d7e2SAndroid Build Coastguard Worker _finishHook(_manager); 266*cc02d7e2SAndroid Build Coastguard Worker } 267*cc02d7e2SAndroid Build Coastguard Worker} 268*cc02d7e2SAndroid Build Coastguard Worker 269*cc02d7e2SAndroid Build Coastguard Worker- (void)receiveNextMessages:(NSUInteger)numberOfMessages { 270*cc02d7e2SAndroid Build Coastguard Worker if (_receiveNextMessagesHook) { 271*cc02d7e2SAndroid Build Coastguard Worker _receiveNextMessagesHook(numberOfMessages, _manager); 272*cc02d7e2SAndroid Build Coastguard Worker } 273*cc02d7e2SAndroid Build Coastguard Worker} 274*cc02d7e2SAndroid Build Coastguard Worker 275*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { 276*cc02d7e2SAndroid Build Coastguard Worker if (_responseHeaderHook) { 277*cc02d7e2SAndroid Build Coastguard Worker _responseHeaderHook(initialMetadata, _manager); 278*cc02d7e2SAndroid Build Coastguard Worker } 279*cc02d7e2SAndroid Build Coastguard Worker} 280*cc02d7e2SAndroid Build Coastguard Worker 281*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveData:(id)data { 282*cc02d7e2SAndroid Build Coastguard Worker if (_responseDataHook) { 283*cc02d7e2SAndroid Build Coastguard Worker _responseDataHook(data, _manager); 284*cc02d7e2SAndroid Build Coastguard Worker } 285*cc02d7e2SAndroid Build Coastguard Worker} 286*cc02d7e2SAndroid Build Coastguard Worker 287*cc02d7e2SAndroid Build Coastguard Worker- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { 288*cc02d7e2SAndroid Build Coastguard Worker if (_responseCloseHook) { 289*cc02d7e2SAndroid Build Coastguard Worker _responseCloseHook(trailingMetadata, error, _manager); 290*cc02d7e2SAndroid Build Coastguard Worker } 291*cc02d7e2SAndroid Build Coastguard Worker} 292*cc02d7e2SAndroid Build Coastguard Worker 293*cc02d7e2SAndroid Build Coastguard Worker- (void)didWriteData { 294*cc02d7e2SAndroid Build Coastguard Worker if (_didWriteDataHook) { 295*cc02d7e2SAndroid Build Coastguard Worker _didWriteDataHook(_manager); 296*cc02d7e2SAndroid Build Coastguard Worker } 297*cc02d7e2SAndroid Build Coastguard Worker} 298*cc02d7e2SAndroid Build Coastguard Worker 299*cc02d7e2SAndroid Build Coastguard Worker@end 300*cc02d7e2SAndroid Build Coastguard Worker 301*cc02d7e2SAndroid Build Coastguard Worker@interface GlobalInterceptorFactory : HookInterceptorFactory 302*cc02d7e2SAndroid Build Coastguard Worker 303*cc02d7e2SAndroid Build Coastguard Worker@property BOOL enabled; 304*cc02d7e2SAndroid Build Coastguard Worker 305*cc02d7e2SAndroid Build Coastguard Worker- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue; 306*cc02d7e2SAndroid Build Coastguard Worker 307*cc02d7e2SAndroid Build Coastguard Worker- (void)setStartHook:(void (^)(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 308*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 309*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 310*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 311*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 312*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 313*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 314*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 315*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 316*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 317*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 318*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook; 319*cc02d7e2SAndroid Build Coastguard Worker 320*cc02d7e2SAndroid Build Coastguard Worker@end 321*cc02d7e2SAndroid Build Coastguard Worker 322*cc02d7e2SAndroid Build Coastguard Worker@implementation GlobalInterceptorFactory 323*cc02d7e2SAndroid Build Coastguard Worker 324*cc02d7e2SAndroid Build Coastguard Worker- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue { 325*cc02d7e2SAndroid Build Coastguard Worker _enabled = NO; 326*cc02d7e2SAndroid Build Coastguard Worker return [super initWithDispatchQueue:dispatchQueue 327*cc02d7e2SAndroid Build Coastguard Worker startHook:nil 328*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:nil 329*cc02d7e2SAndroid Build Coastguard Worker finishHook:nil 330*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:nil 331*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:nil 332*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:nil 333*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:nil 334*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:nil]; 335*cc02d7e2SAndroid Build Coastguard Worker} 336*cc02d7e2SAndroid Build Coastguard Worker 337*cc02d7e2SAndroid Build Coastguard Worker- (GRPCInterceptor *)createInterceptorWithManager:(GRPCInterceptorManager *)interceptorManager { 338*cc02d7e2SAndroid Build Coastguard Worker if (_enabled) { 339*cc02d7e2SAndroid Build Coastguard Worker return [[HookInterceptor alloc] initWithInterceptorManager:interceptorManager 340*cc02d7e2SAndroid Build Coastguard Worker dispatchQueue:_dispatchQueue 341*cc02d7e2SAndroid Build Coastguard Worker startHook:_startHook 342*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:_writeDataHook 343*cc02d7e2SAndroid Build Coastguard Worker finishHook:_finishHook 344*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:_receiveNextMessagesHook 345*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:_responseHeaderHook 346*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:_responseDataHook 347*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:_responseCloseHook 348*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:_didWriteDataHook]; 349*cc02d7e2SAndroid Build Coastguard Worker } else { 350*cc02d7e2SAndroid Build Coastguard Worker return nil; 351*cc02d7e2SAndroid Build Coastguard Worker } 352*cc02d7e2SAndroid Build Coastguard Worker} 353*cc02d7e2SAndroid Build Coastguard Worker 354*cc02d7e2SAndroid Build Coastguard Worker- (void)setStartHook:(void (^)(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 355*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))startHook 356*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:(void (^)(id data, GRPCInterceptorManager *manager))writeDataHook 357*cc02d7e2SAndroid Build Coastguard Worker finishHook:(void (^)(GRPCInterceptorManager *manager))finishHook 358*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:(void (^)(NSUInteger numberOfMessages, 359*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))receiveNextMessagesHook 360*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:(void (^)(NSDictionary *initialMetadata, 361*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseHeaderHook 362*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:(void (^)(id data, GRPCInterceptorManager *manager))responseDataHook 363*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:(void (^)(NSDictionary *trailingMetadata, NSError *error, 364*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager))responseCloseHook 365*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:(void (^)(GRPCInterceptorManager *manager))didWriteDataHook { 366*cc02d7e2SAndroid Build Coastguard Worker _startHook = startHook; 367*cc02d7e2SAndroid Build Coastguard Worker _writeDataHook = writeDataHook; 368*cc02d7e2SAndroid Build Coastguard Worker _finishHook = finishHook; 369*cc02d7e2SAndroid Build Coastguard Worker _receiveNextMessagesHook = receiveNextMessagesHook; 370*cc02d7e2SAndroid Build Coastguard Worker _responseHeaderHook = responseHeaderHook; 371*cc02d7e2SAndroid Build Coastguard Worker _responseDataHook = responseDataHook; 372*cc02d7e2SAndroid Build Coastguard Worker _responseCloseHook = responseCloseHook; 373*cc02d7e2SAndroid Build Coastguard Worker _didWriteDataHook = didWriteDataHook; 374*cc02d7e2SAndroid Build Coastguard Worker} 375*cc02d7e2SAndroid Build Coastguard Worker 376*cc02d7e2SAndroid Build Coastguard Worker@end 377*cc02d7e2SAndroid Build Coastguard Worker 378*cc02d7e2SAndroid Build Coastguard Workerstatic GlobalInterceptorFactory *globalInterceptorFactory = nil; 379*cc02d7e2SAndroid Build Coastguard Workerstatic dispatch_once_t initGlobalInterceptorFactory; 380*cc02d7e2SAndroid Build Coastguard Worker 381*cc02d7e2SAndroid Build Coastguard Worker#pragma mark Tests 382*cc02d7e2SAndroid Build Coastguard Worker 383*cc02d7e2SAndroid Build Coastguard Worker@implementation InteropTests 384*cc02d7e2SAndroid Build Coastguard Worker 385*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic push 386*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 387*cc02d7e2SAndroid Build Coastguard Worker- (void)retriableTest:(SEL)selector retries:(int)retries timeout:(NSTimeInterval)timeout { 388*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < retries; i++) { 389*cc02d7e2SAndroid Build Coastguard Worker NSDate *waitUntil = [[NSDate date] dateByAddingTimeInterval:timeout]; 390*cc02d7e2SAndroid Build Coastguard Worker NSCondition *cv = [[NSCondition alloc] init]; 391*cc02d7e2SAndroid Build Coastguard Worker __block BOOL done = NO; 392*cc02d7e2SAndroid Build Coastguard Worker [cv lock]; 393*cc02d7e2SAndroid Build Coastguard Worker dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ 394*cc02d7e2SAndroid Build Coastguard Worker [self performSelector:selector]; 395*cc02d7e2SAndroid Build Coastguard Worker [cv lock]; 396*cc02d7e2SAndroid Build Coastguard Worker done = YES; 397*cc02d7e2SAndroid Build Coastguard Worker [cv signal]; 398*cc02d7e2SAndroid Build Coastguard Worker [cv unlock]; 399*cc02d7e2SAndroid Build Coastguard Worker }); 400*cc02d7e2SAndroid Build Coastguard Worker while (!done && [waitUntil timeIntervalSinceNow] > 0) { 401*cc02d7e2SAndroid Build Coastguard Worker [cv waitUntilDate:waitUntil]; 402*cc02d7e2SAndroid Build Coastguard Worker } 403*cc02d7e2SAndroid Build Coastguard Worker if (done) { 404*cc02d7e2SAndroid Build Coastguard Worker [cv unlock]; 405*cc02d7e2SAndroid Build Coastguard Worker break; 406*cc02d7e2SAndroid Build Coastguard Worker } else { 407*cc02d7e2SAndroid Build Coastguard Worker [cv unlock]; 408*cc02d7e2SAndroid Build Coastguard Worker [self tearDown]; 409*cc02d7e2SAndroid Build Coastguard Worker [self setUp]; 410*cc02d7e2SAndroid Build Coastguard Worker } 411*cc02d7e2SAndroid Build Coastguard Worker } 412*cc02d7e2SAndroid Build Coastguard Worker} 413*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic pop 414*cc02d7e2SAndroid Build Coastguard Worker 415*cc02d7e2SAndroid Build Coastguard Worker+ (XCTestSuite *)defaultTestSuite { 416*cc02d7e2SAndroid Build Coastguard Worker if (self == [InteropTests class]) { 417*cc02d7e2SAndroid Build Coastguard Worker return [XCTestSuite testSuiteWithName:@"InteropTestsEmptySuite"]; 418*cc02d7e2SAndroid Build Coastguard Worker } 419*cc02d7e2SAndroid Build Coastguard Worker return super.defaultTestSuite; 420*cc02d7e2SAndroid Build Coastguard Worker} 421*cc02d7e2SAndroid Build Coastguard Worker 422*cc02d7e2SAndroid Build Coastguard Worker+ (NSString *)host { 423*cc02d7e2SAndroid Build Coastguard Worker return nil; 424*cc02d7e2SAndroid Build Coastguard Worker} 425*cc02d7e2SAndroid Build Coastguard Worker 426*cc02d7e2SAndroid Build Coastguard Worker// This number indicates how many bytes of overhead does Protocol Buffers encoding add onto the 427*cc02d7e2SAndroid Build Coastguard Worker// message. The number varies as different message.proto is used on different servers. The actual 428*cc02d7e2SAndroid Build Coastguard Worker// number for each interop server is overridden in corresponding derived test classes. 429*cc02d7e2SAndroid Build Coastguard Worker- (int32_t)encodingOverhead { 430*cc02d7e2SAndroid Build Coastguard Worker return 0; 431*cc02d7e2SAndroid Build Coastguard Worker} 432*cc02d7e2SAndroid Build Coastguard Worker 433*cc02d7e2SAndroid Build Coastguard Worker// For backwards compatibility 434*cc02d7e2SAndroid Build Coastguard Worker+ (GRPCTransportType)transportType { 435*cc02d7e2SAndroid Build Coastguard Worker return GRPCTransportTypeChttp2BoringSSL; 436*cc02d7e2SAndroid Build Coastguard Worker} 437*cc02d7e2SAndroid Build Coastguard Worker 438*cc02d7e2SAndroid Build Coastguard Worker+ (GRPCTransportID)transport { 439*cc02d7e2SAndroid Build Coastguard Worker return NULL; 440*cc02d7e2SAndroid Build Coastguard Worker} 441*cc02d7e2SAndroid Build Coastguard Worker 442*cc02d7e2SAndroid Build Coastguard Worker+ (NSString *)PEMRootCertificates { 443*cc02d7e2SAndroid Build Coastguard Worker return nil; 444*cc02d7e2SAndroid Build Coastguard Worker} 445*cc02d7e2SAndroid Build Coastguard Worker 446*cc02d7e2SAndroid Build Coastguard Worker+ (NSString *)hostNameOverride { 447*cc02d7e2SAndroid Build Coastguard Worker return nil; 448*cc02d7e2SAndroid Build Coastguard Worker} 449*cc02d7e2SAndroid Build Coastguard Worker 450*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp { 451*cc02d7e2SAndroid Build Coastguard Worker dispatch_once(&initGlobalInterceptorFactory, ^{ 452*cc02d7e2SAndroid Build Coastguard Worker dispatch_queue_t globalInterceptorQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); 453*cc02d7e2SAndroid Build Coastguard Worker globalInterceptorFactory = 454*cc02d7e2SAndroid Build Coastguard Worker [[GlobalInterceptorFactory alloc] initWithDispatchQueue:globalInterceptorQueue]; 455*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall2 registerGlobalInterceptor:globalInterceptorFactory]; 456*cc02d7e2SAndroid Build Coastguard Worker }); 457*cc02d7e2SAndroid Build Coastguard Worker} 458*cc02d7e2SAndroid Build Coastguard Worker 459*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 460*cc02d7e2SAndroid Build Coastguard Worker self.continueAfterFailure = YES; 461*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall resetHostSettings]; 462*cc02d7e2SAndroid Build Coastguard Worker GRPCResetCallConnections(); 463*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotNil([[self class] host]); 464*cc02d7e2SAndroid Build Coastguard Worker} 465*cc02d7e2SAndroid Build Coastguard Worker 466*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyUnaryRPC { 467*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiter, GRPCTestAssert assertBlock) { 468*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 469*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; 470*cc02d7e2SAndroid Build Coastguard Worker 471*cc02d7e2SAndroid Build Coastguard Worker GPBEmpty *request = [GPBEmpty message]; 472*cc02d7e2SAndroid Build Coastguard Worker 473*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 474*cc02d7e2SAndroid Build Coastguard Worker [service emptyCallWithRequest:request 475*cc02d7e2SAndroid Build Coastguard Worker handler:^(GPBEmpty *response, NSError *error) { 476*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 477*cc02d7e2SAndroid Build Coastguard Worker return; 478*cc02d7e2SAndroid Build Coastguard Worker } 479*cc02d7e2SAndroid Build Coastguard Worker 480*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 481*cc02d7e2SAndroid Build Coastguard Worker 482*cc02d7e2SAndroid Build Coastguard Worker id expectedResponse = [GPBEmpty message]; 483*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 484*cc02d7e2SAndroid Build Coastguard Worker 485*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 486*cc02d7e2SAndroid Build Coastguard Worker }]; 487*cc02d7e2SAndroid Build Coastguard Worker waiter(@[ expectation ], GRPCInteropTestTimeoutDefault); 488*cc02d7e2SAndroid Build Coastguard Worker }); 489*cc02d7e2SAndroid Build Coastguard Worker} 490*cc02d7e2SAndroid Build Coastguard Worker 491*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyUnaryRPCWithV2API { 492*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 493*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 494*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectReceive = 495*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"EmptyUnaryWithV2API received message"]; 496*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectComplete = 497*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"EmptyUnaryWithV2API completed"]; 498*cc02d7e2SAndroid Build Coastguard Worker 499*cc02d7e2SAndroid Build Coastguard Worker GPBEmpty *request = [GPBEmpty message]; 500*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 501*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 502*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 503*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 504*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 505*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 506*cc02d7e2SAndroid Build Coastguard Worker 507*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 508*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *call = [service 509*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 510*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 511*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 512*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 513*cc02d7e2SAndroid Build Coastguard Worker return; 514*cc02d7e2SAndroid Build Coastguard Worker } 515*cc02d7e2SAndroid Build Coastguard Worker if (message) { 516*cc02d7e2SAndroid Build Coastguard Worker id expectedResponse = [GPBEmpty message]; 517*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(message, expectedResponse); 518*cc02d7e2SAndroid Build Coastguard Worker [expectReceive fulfill]; 519*cc02d7e2SAndroid Build Coastguard Worker } 520*cc02d7e2SAndroid Build Coastguard Worker } 521*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 522*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 523*cc02d7e2SAndroid Build Coastguard Worker return; 524*cc02d7e2SAndroid Build Coastguard Worker } 525*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Unexpected error: %@", error); 526*cc02d7e2SAndroid Build Coastguard Worker [expectComplete fulfill]; 527*cc02d7e2SAndroid Build Coastguard Worker }] 528*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 529*cc02d7e2SAndroid Build Coastguard Worker [call start]; 530*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectReceive, expectComplete ], GRPCInteropTestTimeoutDefault); 531*cc02d7e2SAndroid Build Coastguard Worker }); 532*cc02d7e2SAndroid Build Coastguard Worker} 533*cc02d7e2SAndroid Build Coastguard Worker 534*cc02d7e2SAndroid Build Coastguard Worker// Test that responses can be dispatched even if we do not run main run-loop 535*cc02d7e2SAndroid Build Coastguard Worker- (void)testAsyncDispatchWithV2API { 536*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 537*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 538*cc02d7e2SAndroid Build Coastguard Worker 539*cc02d7e2SAndroid Build Coastguard Worker XCTestExpectation *receiveExpect = [self expectationWithDescription:@"receiveExpect"]; 540*cc02d7e2SAndroid Build Coastguard Worker XCTestExpectation *closeExpect = [self expectationWithDescription:@"closeExpect"]; 541*cc02d7e2SAndroid Build Coastguard Worker 542*cc02d7e2SAndroid Build Coastguard Worker GPBEmpty *request = [GPBEmpty message]; 543*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 544*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 545*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 546*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 547*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 548*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 549*cc02d7e2SAndroid Build Coastguard Worker 550*cc02d7e2SAndroid Build Coastguard Worker __block BOOL messageReceived = NO; 551*cc02d7e2SAndroid Build Coastguard Worker __block BOOL done = NO; 552*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 553*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *call = [service 554*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithMessage:request 555*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 556*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 557*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 558*cc02d7e2SAndroid Build Coastguard Worker return; 559*cc02d7e2SAndroid Build Coastguard Worker } 560*cc02d7e2SAndroid Build Coastguard Worker if (message) { 561*cc02d7e2SAndroid Build Coastguard Worker id expectedResponse = [GPBEmpty message]; 562*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(message, expectedResponse); 563*cc02d7e2SAndroid Build Coastguard Worker messageReceived = YES; 564*cc02d7e2SAndroid Build Coastguard Worker } 565*cc02d7e2SAndroid Build Coastguard Worker [receiveExpect fulfill]; 566*cc02d7e2SAndroid Build Coastguard Worker } 567*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 568*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 569*cc02d7e2SAndroid Build Coastguard Worker return; 570*cc02d7e2SAndroid Build Coastguard Worker } 571*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Unexpected error: %@", error); 572*cc02d7e2SAndroid Build Coastguard Worker done = YES; 573*cc02d7e2SAndroid Build Coastguard Worker [closeExpect fulfill]; 574*cc02d7e2SAndroid Build Coastguard Worker }] 575*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 576*cc02d7e2SAndroid Build Coastguard Worker 577*cc02d7e2SAndroid Build Coastguard Worker [call start]; 578*cc02d7e2SAndroid Build Coastguard Worker 579*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ receiveExpect, closeExpect ], GRPCInteropTestTimeoutDefault); 580*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(messageReceived); 581*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(done); 582*cc02d7e2SAndroid Build Coastguard Worker }); 583*cc02d7e2SAndroid Build Coastguard Worker} 584*cc02d7e2SAndroid Build Coastguard Worker 585*cc02d7e2SAndroid Build Coastguard Worker- (void)testLargeUnaryRPC { 586*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 587*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 588*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; 589*cc02d7e2SAndroid Build Coastguard Worker 590*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 591*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 592*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = LARGE_RESPONSE_PAYLOAD_SIZE; 593*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:LARGE_REQUEST_PAYLOAD_SIZE]; 594*cc02d7e2SAndroid Build Coastguard Worker 595*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 596*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 597*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 598*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 599*cc02d7e2SAndroid Build Coastguard Worker return; 600*cc02d7e2SAndroid Build Coastguard Worker } 601*cc02d7e2SAndroid Build Coastguard Worker 602*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 603*cc02d7e2SAndroid Build Coastguard Worker 604*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 605*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 606*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 607*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:LARGE_RESPONSE_PAYLOAD_SIZE]; 608*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 609*cc02d7e2SAndroid Build Coastguard Worker 610*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 611*cc02d7e2SAndroid Build Coastguard Worker }]; 612*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 613*cc02d7e2SAndroid Build Coastguard Worker }); 614*cc02d7e2SAndroid Build Coastguard Worker} 615*cc02d7e2SAndroid Build Coastguard Worker 616*cc02d7e2SAndroid Build Coastguard Worker- (void)testUnaryResponseHandler { 617*cc02d7e2SAndroid Build Coastguard Worker // The test does not work on a remote server since it does not echo a trailer 618*cc02d7e2SAndroid Build Coastguard Worker if ([[self class] isRemoteTest]) { 619*cc02d7e2SAndroid Build Coastguard Worker return; 620*cc02d7e2SAndroid Build Coastguard Worker } 621*cc02d7e2SAndroid Build Coastguard Worker 622*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 623*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 624*cc02d7e2SAndroid Build Coastguard Worker 625*cc02d7e2SAndroid Build Coastguard Worker XCTestExpectation *expectComplete = [self expectationWithDescription:@"call complete"]; 626*cc02d7e2SAndroid Build Coastguard Worker XCTestExpectation *expectCompleteMainQueue = 627*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"main queue call complete"]; 628*cc02d7e2SAndroid Build Coastguard Worker 629*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 630*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 631*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = LARGE_RESPONSE_PAYLOAD_SIZE; 632*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:LARGE_REQUEST_PAYLOAD_SIZE]; 633*cc02d7e2SAndroid Build Coastguard Worker 634*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 635*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 636*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 637*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 638*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 639*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 640*cc02d7e2SAndroid Build Coastguard Worker const unsigned char raw_bytes[] = {1, 2, 3, 4}; 641*cc02d7e2SAndroid Build Coastguard Worker NSData *trailer_data = [NSData dataWithBytes:raw_bytes length:sizeof(raw_bytes)]; 642*cc02d7e2SAndroid Build Coastguard Worker options.initialMetadata = @{ 643*cc02d7e2SAndroid Build Coastguard Worker @"x-grpc-test-echo-trailing-bin" : trailer_data, 644*cc02d7e2SAndroid Build Coastguard Worker @"x-grpc-test-echo-initial" : @"test-header" 645*cc02d7e2SAndroid Build Coastguard Worker }; 646*cc02d7e2SAndroid Build Coastguard Worker 647*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 648*cc02d7e2SAndroid Build Coastguard Worker 649*cc02d7e2SAndroid Build Coastguard Worker __block GRPCUnaryResponseHandler *handler = [[GRPCUnaryResponseHandler alloc] 650*cc02d7e2SAndroid Build Coastguard Worker initWithResponseHandler:^(GPBMessage *response, NSError *error) { 651*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 652*cc02d7e2SAndroid Build Coastguard Worker return; 653*cc02d7e2SAndroid Build Coastguard Worker } 654*cc02d7e2SAndroid Build Coastguard Worker 655*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Unexpected error: %@", error); 656*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 657*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 658*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 659*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:LARGE_RESPONSE_PAYLOAD_SIZE]; 660*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 661*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(handler.responseHeaders[@"x-grpc-test-echo-initial"], 662*cc02d7e2SAndroid Build Coastguard Worker @"test-header"); 663*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(handler.responseTrailers[@"x-grpc-test-echo-trailing-bin"], 664*cc02d7e2SAndroid Build Coastguard Worker trailer_data); 665*cc02d7e2SAndroid Build Coastguard Worker [expectComplete fulfill]; 666*cc02d7e2SAndroid Build Coastguard Worker } 667*cc02d7e2SAndroid Build Coastguard Worker responseDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL)]; 668*cc02d7e2SAndroid Build Coastguard Worker __block GRPCUnaryResponseHandler *handlerMainQueue = [[GRPCUnaryResponseHandler alloc] 669*cc02d7e2SAndroid Build Coastguard Worker initWithResponseHandler:^(GPBMessage *response, NSError *error) { 670*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 671*cc02d7e2SAndroid Build Coastguard Worker return; 672*cc02d7e2SAndroid Build Coastguard Worker } 673*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Unexpected error: %@", error); 674*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 675*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 676*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 677*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:LARGE_RESPONSE_PAYLOAD_SIZE]; 678*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 679*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(handlerMainQueue.responseHeaders[@"x-grpc-test-echo-initial"], 680*cc02d7e2SAndroid Build Coastguard Worker @"test-header"); 681*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(handlerMainQueue.responseTrailers[@"x-grpc-test-echo-trailing-bin"], 682*cc02d7e2SAndroid Build Coastguard Worker trailer_data); 683*cc02d7e2SAndroid Build Coastguard Worker [expectCompleteMainQueue fulfill]; 684*cc02d7e2SAndroid Build Coastguard Worker } 685*cc02d7e2SAndroid Build Coastguard Worker responseDispatchQueue:nil]; 686*cc02d7e2SAndroid Build Coastguard Worker 687*cc02d7e2SAndroid Build Coastguard Worker [[service unaryCallWithMessage:request responseHandler:handler callOptions:options] start]; 688*cc02d7e2SAndroid Build Coastguard Worker [[service unaryCallWithMessage:request responseHandler:handlerMainQueue 689*cc02d7e2SAndroid Build Coastguard Worker callOptions:options] start]; 690*cc02d7e2SAndroid Build Coastguard Worker 691*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectComplete, expectCompleteMainQueue ], GRPCInteropTestTimeoutDefault); 692*cc02d7e2SAndroid Build Coastguard Worker }); 693*cc02d7e2SAndroid Build Coastguard Worker} 694*cc02d7e2SAndroid Build Coastguard Worker 695*cc02d7e2SAndroid Build Coastguard Worker- (void)testLargeUnaryRPCWithV2API { 696*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 697*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 698*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectReceive = 699*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"LargeUnaryWithV2API received message"]; 700*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectComplete = 701*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"LargeUnaryWithV2API received complete"]; 702*cc02d7e2SAndroid Build Coastguard Worker 703*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 704*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 705*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = LARGE_RESPONSE_PAYLOAD_SIZE; 706*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:LARGE_REQUEST_PAYLOAD_SIZE]; 707*cc02d7e2SAndroid Build Coastguard Worker 708*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 709*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 710*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 711*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 712*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 713*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 714*cc02d7e2SAndroid Build Coastguard Worker 715*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 716*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *call = [service 717*cc02d7e2SAndroid Build Coastguard Worker unaryCallWithMessage:request 718*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 719*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 720*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 721*cc02d7e2SAndroid Build Coastguard Worker return; 722*cc02d7e2SAndroid Build Coastguard Worker } 723*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotNil(message); 724*cc02d7e2SAndroid Build Coastguard Worker if (message) { 725*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = 726*cc02d7e2SAndroid Build Coastguard Worker [RMTSimpleResponse message]; 727*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 728*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 729*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:LARGE_RESPONSE_PAYLOAD_SIZE]; 730*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(message, expectedResponse); 731*cc02d7e2SAndroid Build Coastguard Worker 732*cc02d7e2SAndroid Build Coastguard Worker [expectReceive fulfill]; 733*cc02d7e2SAndroid Build Coastguard Worker } 734*cc02d7e2SAndroid Build Coastguard Worker } 735*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 736*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 737*cc02d7e2SAndroid Build Coastguard Worker return; 738*cc02d7e2SAndroid Build Coastguard Worker } 739*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Unexpected error: %@", error); 740*cc02d7e2SAndroid Build Coastguard Worker [expectComplete fulfill]; 741*cc02d7e2SAndroid Build Coastguard Worker }] 742*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 743*cc02d7e2SAndroid Build Coastguard Worker [call start]; 744*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectReceive, expectComplete ], GRPCInteropTestTimeoutDefault); 745*cc02d7e2SAndroid Build Coastguard Worker }); 746*cc02d7e2SAndroid Build Coastguard Worker} 747*cc02d7e2SAndroid Build Coastguard Worker 748*cc02d7e2SAndroid Build Coastguard Worker- (void)testConcurrentRPCsWithErrorsWithV2API { 749*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 750*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 751*cc02d7e2SAndroid Build Coastguard Worker NSMutableArray *completeExpectations = [NSMutableArray array]; 752*cc02d7e2SAndroid Build Coastguard Worker NSMutableArray *calls = [NSMutableArray array]; 753*cc02d7e2SAndroid Build Coastguard Worker int num_rpcs = 10; 754*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < num_rpcs; ++i) { 755*cc02d7e2SAndroid Build Coastguard Worker [completeExpectations 756*cc02d7e2SAndroid Build Coastguard Worker addObject:[self expectationWithDescription: 757*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received trailer for RPC %d", i]]]; 758*cc02d7e2SAndroid Build Coastguard Worker 759*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 760*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 761*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = SMALL_PAYLOAD_SIZE; 762*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:SMALL_PAYLOAD_SIZE]; 763*cc02d7e2SAndroid Build Coastguard Worker if (i % 3 == 0) { 764*cc02d7e2SAndroid Build Coastguard Worker request.responseStatus.code = GRPC_STATUS_UNAVAILABLE; 765*cc02d7e2SAndroid Build Coastguard Worker } else if (i % 7 == 0) { 766*cc02d7e2SAndroid Build Coastguard Worker request.responseStatus.code = GRPC_STATUS_CANCELLED; 767*cc02d7e2SAndroid Build Coastguard Worker } 768*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 769*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 770*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 771*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 772*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 773*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 774*cc02d7e2SAndroid Build Coastguard Worker 775*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 776*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *call = [service 777*cc02d7e2SAndroid Build Coastguard Worker unaryCallWithMessage:request 778*cc02d7e2SAndroid Build Coastguard Worker responseHandler:[[InteropTestsBlockCallbacks alloc] 779*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 780*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 781*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 782*cc02d7e2SAndroid Build Coastguard Worker return; 783*cc02d7e2SAndroid Build Coastguard Worker } 784*cc02d7e2SAndroid Build Coastguard Worker if (message) { 785*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = 786*cc02d7e2SAndroid Build Coastguard Worker [RMTSimpleResponse message]; 787*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 788*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 789*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:SMALL_PAYLOAD_SIZE]; 790*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(message, expectedResponse); 791*cc02d7e2SAndroid Build Coastguard Worker } 792*cc02d7e2SAndroid Build Coastguard Worker } 793*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 794*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 795*cc02d7e2SAndroid Build Coastguard Worker return; 796*cc02d7e2SAndroid Build Coastguard Worker } 797*cc02d7e2SAndroid Build Coastguard Worker [completeExpectations[i] fulfill]; 798*cc02d7e2SAndroid Build Coastguard Worker }] 799*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 800*cc02d7e2SAndroid Build Coastguard Worker [calls addObject:call]; 801*cc02d7e2SAndroid Build Coastguard Worker } 802*cc02d7e2SAndroid Build Coastguard Worker 803*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < num_rpcs; ++i) { 804*cc02d7e2SAndroid Build Coastguard Worker GRPCUnaryProtoCall *call = calls[i]; 805*cc02d7e2SAndroid Build Coastguard Worker [call start]; 806*cc02d7e2SAndroid Build Coastguard Worker } 807*cc02d7e2SAndroid Build Coastguard Worker 808*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(completeExpectations, GRPCInteropTestTimeoutDefault); 809*cc02d7e2SAndroid Build Coastguard Worker }); 810*cc02d7e2SAndroid Build Coastguard Worker} 811*cc02d7e2SAndroid Build Coastguard Worker 812*cc02d7e2SAndroid Build Coastguard Worker- (void)concurrentRPCsWithErrors { 813*cc02d7e2SAndroid Build Coastguard Worker const int kNumRpcs = 10; 814*cc02d7e2SAndroid Build Coastguard Worker __block int completedCallCount = 0; 815*cc02d7e2SAndroid Build Coastguard Worker NSCondition *cv = [[NSCondition alloc] init]; 816*cc02d7e2SAndroid Build Coastguard Worker NSDate *waitUntil = [[NSDate date] dateByAddingTimeInterval:GRPCInteropTestTimeoutDefault]; 817*cc02d7e2SAndroid Build Coastguard Worker [cv lock]; 818*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumRpcs; ++i) { 819*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 820*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 821*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = SMALL_PAYLOAD_SIZE; 822*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:SMALL_PAYLOAD_SIZE]; 823*cc02d7e2SAndroid Build Coastguard Worker if (i % 3 == 0) { 824*cc02d7e2SAndroid Build Coastguard Worker request.responseStatus.code = GRPC_STATUS_UNAVAILABLE; 825*cc02d7e2SAndroid Build Coastguard Worker } else if (i % 7 == 0) { 826*cc02d7e2SAndroid Build Coastguard Worker request.responseStatus.code = GRPC_STATUS_CANCELLED; 827*cc02d7e2SAndroid Build Coastguard Worker } 828*cc02d7e2SAndroid Build Coastguard Worker 829*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 830*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 831*cc02d7e2SAndroid Build Coastguard Worker GRPCProtoCall *call = [service 832*cc02d7e2SAndroid Build Coastguard Worker RPCToUnaryCallWithRequest:request 833*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 834*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 835*cc02d7e2SAndroid Build Coastguard Worker return; 836*cc02d7e2SAndroid Build Coastguard Worker } 837*cc02d7e2SAndroid Build Coastguard Worker if (error == nil) { 838*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 839*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 840*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 841*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:SMALL_PAYLOAD_SIZE]; 842*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 843*cc02d7e2SAndroid Build Coastguard Worker } 844*cc02d7e2SAndroid Build Coastguard Worker // DEBUG 845*cc02d7e2SAndroid Build Coastguard Worker [cv lock]; 846*cc02d7e2SAndroid Build Coastguard Worker if (++completedCallCount == kNumRpcs) { 847*cc02d7e2SAndroid Build Coastguard Worker [cv signal]; 848*cc02d7e2SAndroid Build Coastguard Worker } 849*cc02d7e2SAndroid Build Coastguard Worker [cv unlock]; 850*cc02d7e2SAndroid Build Coastguard Worker }]; 851*cc02d7e2SAndroid Build Coastguard Worker [call setResponseDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL)]; 852*cc02d7e2SAndroid Build Coastguard Worker [call start]; 853*cc02d7e2SAndroid Build Coastguard Worker } 854*cc02d7e2SAndroid Build Coastguard Worker while (completedCallCount < kNumRpcs && [waitUntil timeIntervalSinceNow] > 0) { 855*cc02d7e2SAndroid Build Coastguard Worker [cv waitUntilDate:waitUntil]; 856*cc02d7e2SAndroid Build Coastguard Worker } 857*cc02d7e2SAndroid Build Coastguard Worker [cv unlock]; 858*cc02d7e2SAndroid Build Coastguard Worker} 859*cc02d7e2SAndroid Build Coastguard Worker 860*cc02d7e2SAndroid Build Coastguard Worker- (void)testConcurrentRPCsWithErrors { 861*cc02d7e2SAndroid Build Coastguard Worker [self retriableTest:@selector(concurrentRPCsWithErrors) retries:kTestRetries timeout:10]; 862*cc02d7e2SAndroid Build Coastguard Worker} 863*cc02d7e2SAndroid Build Coastguard Worker 864*cc02d7e2SAndroid Build Coastguard Worker- (void)testPacketCoalescing { 865*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 866*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 867*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; 868*cc02d7e2SAndroid Build Coastguard Worker 869*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 870*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 871*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = SMALL_PAYLOAD_SIZE; 872*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:SMALL_PAYLOAD_SIZE]; 873*cc02d7e2SAndroid Build Coastguard Worker 874*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall enableOpBatchLog:YES]; 875*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 876*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 877*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 878*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 879*cc02d7e2SAndroid Build Coastguard Worker return; 880*cc02d7e2SAndroid Build Coastguard Worker } 881*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 882*cc02d7e2SAndroid Build Coastguard Worker 883*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 884*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 885*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = [NSMutableData dataWithLength:10]; 886*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 887*cc02d7e2SAndroid Build Coastguard Worker 888*cc02d7e2SAndroid Build Coastguard Worker // The test is a success if there is a batch of exactly 3 ops 889*cc02d7e2SAndroid Build Coastguard Worker // (SEND_INITIAL_METADATA, SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). 890*cc02d7e2SAndroid Build Coastguard Worker // Without packet coalescing each batch of ops contains only one op. 891*cc02d7e2SAndroid Build Coastguard Worker NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog]; 892*cc02d7e2SAndroid Build Coastguard Worker const NSInteger kExpectedOpBatchSize = 3; 893*cc02d7e2SAndroid Build Coastguard Worker for (NSObject *o in opBatches) { 894*cc02d7e2SAndroid Build Coastguard Worker if ([o isKindOfClass:[NSArray class]]) { 895*cc02d7e2SAndroid Build Coastguard Worker NSArray *batch = (NSArray *)o; 896*cc02d7e2SAndroid Build Coastguard Worker if ([batch count] == kExpectedOpBatchSize) { 897*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 898*cc02d7e2SAndroid Build Coastguard Worker break; 899*cc02d7e2SAndroid Build Coastguard Worker } 900*cc02d7e2SAndroid Build Coastguard Worker } 901*cc02d7e2SAndroid Build Coastguard Worker } 902*cc02d7e2SAndroid Build Coastguard Worker }]; 903*cc02d7e2SAndroid Build Coastguard Worker 904*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 905*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall enableOpBatchLog:NO]; 906*cc02d7e2SAndroid Build Coastguard Worker }); 907*cc02d7e2SAndroid Build Coastguard Worker} 908*cc02d7e2SAndroid Build Coastguard Worker 909*cc02d7e2SAndroid Build Coastguard Worker- (void)test4MBResponsesAreAccepted { 910*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 911*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 912*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; 913*cc02d7e2SAndroid Build Coastguard Worker 914*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 915*cc02d7e2SAndroid Build Coastguard Worker const int32_t kPayloadSize = 916*cc02d7e2SAndroid Build Coastguard Worker 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead 917*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = kPayloadSize; 918*cc02d7e2SAndroid Build Coastguard Worker 919*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 920*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 921*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 922*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 923*cc02d7e2SAndroid Build Coastguard Worker return; 924*cc02d7e2SAndroid Build Coastguard Worker } 925*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 926*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.payload.body.length, kPayloadSize); 927*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 928*cc02d7e2SAndroid Build Coastguard Worker }]; 929*cc02d7e2SAndroid Build Coastguard Worker 930*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 931*cc02d7e2SAndroid Build Coastguard Worker }); 932*cc02d7e2SAndroid Build Coastguard Worker} 933*cc02d7e2SAndroid Build Coastguard Worker 934*cc02d7e2SAndroid Build Coastguard Worker- (void)testResponsesOverMaxSizeFailWithActionableMessage { 935*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 936*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 937*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 938*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"ResponseOverMaxSize"]; 939*cc02d7e2SAndroid Build Coastguard Worker 940*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 941*cc02d7e2SAndroid Build Coastguard Worker const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size 942*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = kPayloadSize; 943*cc02d7e2SAndroid Build Coastguard Worker 944*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 945*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 946*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 947*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 948*cc02d7e2SAndroid Build Coastguard Worker return; 949*cc02d7e2SAndroid Build Coastguard Worker } 950*cc02d7e2SAndroid Build Coastguard Worker // TODO(jcanizales): Catch the error and rethrow it with an 951*cc02d7e2SAndroid Build Coastguard Worker // actionable message: 952*cc02d7e2SAndroid Build Coastguard Worker // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a 953*cc02d7e2SAndroid Build Coastguard Worker // higher limit. 954*cc02d7e2SAndroid Build Coastguard Worker // - If you're developing the server, consider using response 955*cc02d7e2SAndroid Build Coastguard Worker // streaming, or let clients filter 956*cc02d7e2SAndroid Build Coastguard Worker // responses by setting a google.protobuf.FieldMask in the 957*cc02d7e2SAndroid Build Coastguard Worker // request: 958*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/field_mask.proto 959*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects( 960*cc02d7e2SAndroid Build Coastguard Worker error.localizedDescription, 961*cc02d7e2SAndroid Build Coastguard Worker @"CLIENT: Received message larger than max (4194305 vs. 4194304)"); 962*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 963*cc02d7e2SAndroid Build Coastguard Worker }]; 964*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 965*cc02d7e2SAndroid Build Coastguard Worker }); 966*cc02d7e2SAndroid Build Coastguard Worker} 967*cc02d7e2SAndroid Build Coastguard Worker 968*cc02d7e2SAndroid Build Coastguard Worker- (void)testResponsesOver4MBAreAcceptedIfOptedIn { 969*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 970*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 971*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 972*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"HigherResponseSizeLimit"]; 973*cc02d7e2SAndroid Build Coastguard Worker __block NSError *callError = nil; 974*cc02d7e2SAndroid Build Coastguard Worker 975*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 976*cc02d7e2SAndroid Build Coastguard Worker const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB 977*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = kPayloadSize; 978*cc02d7e2SAndroid Build Coastguard Worker 979*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:[[self class] host]]; 980*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 981*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 982*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 983*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 984*cc02d7e2SAndroid Build Coastguard Worker return; 985*cc02d7e2SAndroid Build Coastguard Worker } 986*cc02d7e2SAndroid Build Coastguard Worker callError = error; 987*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 988*cc02d7e2SAndroid Build Coastguard Worker }]; 989*cc02d7e2SAndroid Build Coastguard Worker 990*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 991*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(callError, @"Finished with unexpected error: %@", callError); 992*cc02d7e2SAndroid Build Coastguard Worker }); 993*cc02d7e2SAndroid Build Coastguard Worker} 994*cc02d7e2SAndroid Build Coastguard Worker 995*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientStreamingRPC { 996*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 997*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 998*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; 999*cc02d7e2SAndroid Build Coastguard Worker 1000*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; 1001*cc02d7e2SAndroid Build Coastguard Worker request1.payload.body = [NSMutableData dataWithLength:27182]; 1002*cc02d7e2SAndroid Build Coastguard Worker 1003*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; 1004*cc02d7e2SAndroid Build Coastguard Worker request2.payload.body = [NSMutableData dataWithLength:8]; 1005*cc02d7e2SAndroid Build Coastguard Worker 1006*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message]; 1007*cc02d7e2SAndroid Build Coastguard Worker request3.payload.body = [NSMutableData dataWithLength:1828]; 1008*cc02d7e2SAndroid Build Coastguard Worker 1009*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; 1010*cc02d7e2SAndroid Build Coastguard Worker request4.payload.body = [NSMutableData dataWithLength:45904]; 1011*cc02d7e2SAndroid Build Coastguard Worker 1012*cc02d7e2SAndroid Build Coastguard Worker GRXWriter *writer = [GRXWriter writerWithContainer:@[ request1, request2, request3, request4 ]]; 1013*cc02d7e2SAndroid Build Coastguard Worker 1014*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1015*cc02d7e2SAndroid Build Coastguard Worker [service 1016*cc02d7e2SAndroid Build Coastguard Worker streamingInputCallWithRequestsWriter:writer 1017*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTStreamingInputCallResponse *response, 1018*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1019*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1020*cc02d7e2SAndroid Build Coastguard Worker return; 1021*cc02d7e2SAndroid Build Coastguard Worker } 1022*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", 1023*cc02d7e2SAndroid Build Coastguard Worker error); 1024*cc02d7e2SAndroid Build Coastguard Worker 1025*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingInputCallResponse *expectedResponse = 1026*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingInputCallResponse message]; 1027*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.aggregatedPayloadSize = 74922; 1028*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 1029*cc02d7e2SAndroid Build Coastguard Worker 1030*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1031*cc02d7e2SAndroid Build Coastguard Worker }]; 1032*cc02d7e2SAndroid Build Coastguard Worker 1033*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1034*cc02d7e2SAndroid Build Coastguard Worker }); 1035*cc02d7e2SAndroid Build Coastguard Worker} 1036*cc02d7e2SAndroid Build Coastguard Worker 1037*cc02d7e2SAndroid Build Coastguard Worker- (void)testServerStreamingRPC { 1038*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1039*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1040*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; 1041*cc02d7e2SAndroid Build Coastguard Worker 1042*cc02d7e2SAndroid Build Coastguard Worker NSArray *expectedSizes = @[ @31415, @9, @2653, @58979 ]; 1043*cc02d7e2SAndroid Build Coastguard Worker 1044*cc02d7e2SAndroid Build Coastguard Worker RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; 1045*cc02d7e2SAndroid Build Coastguard Worker for (NSNumber *size in expectedSizes) { 1046*cc02d7e2SAndroid Build Coastguard Worker RMTResponseParameters *parameters = [RMTResponseParameters message]; 1047*cc02d7e2SAndroid Build Coastguard Worker parameters.size = [size intValue]; 1048*cc02d7e2SAndroid Build Coastguard Worker [request.responseParametersArray addObject:parameters]; 1049*cc02d7e2SAndroid Build Coastguard Worker } 1050*cc02d7e2SAndroid Build Coastguard Worker 1051*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1052*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1053*cc02d7e2SAndroid Build Coastguard Worker [service 1054*cc02d7e2SAndroid Build Coastguard Worker streamingOutputCallWithRequest:request 1055*cc02d7e2SAndroid Build Coastguard Worker eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, 1056*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1057*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1058*cc02d7e2SAndroid Build Coastguard Worker return; 1059*cc02d7e2SAndroid Build Coastguard Worker } 1060*cc02d7e2SAndroid Build Coastguard Worker 1061*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1062*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1063*cc02d7e2SAndroid Build Coastguard Worker [NSString 1064*cc02d7e2SAndroid Build Coastguard Worker stringWithFormat:@"Finished with unexpected error: %@", error]); 1065*cc02d7e2SAndroid Build Coastguard Worker assertBlock(done || response, 1066*cc02d7e2SAndroid Build Coastguard Worker @"Event handler called without an event."); 1067*cc02d7e2SAndroid Build Coastguard Worker 1068*cc02d7e2SAndroid Build Coastguard Worker if (response) { 1069*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 1070*cc02d7e2SAndroid Build Coastguard Worker 1071*cc02d7e2SAndroid Build Coastguard Worker id expected = [RMTStreamingOutputCallResponse 1072*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:expectedSizes[index]]; 1073*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1074*cc02d7e2SAndroid Build Coastguard Worker [response isEqual:expected], 1075*cc02d7e2SAndroid Build Coastguard Worker [NSString 1076*cc02d7e2SAndroid Build Coastguard Worker stringWithFormat:@"response %@ not equal to expected %@", 1077*cc02d7e2SAndroid Build Coastguard Worker response, expected]); 1078*cc02d7e2SAndroid Build Coastguard Worker 1079*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1080*cc02d7e2SAndroid Build Coastguard Worker } 1081*cc02d7e2SAndroid Build Coastguard Worker 1082*cc02d7e2SAndroid Build Coastguard Worker if (done) { 1083*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1084*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1085*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %@ responses instead of 4.", 1086*cc02d7e2SAndroid Build Coastguard Worker @(index)]); 1087*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1088*cc02d7e2SAndroid Build Coastguard Worker } 1089*cc02d7e2SAndroid Build Coastguard Worker }]; 1090*cc02d7e2SAndroid Build Coastguard Worker 1091*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1092*cc02d7e2SAndroid Build Coastguard Worker }); 1093*cc02d7e2SAndroid Build Coastguard Worker} 1094*cc02d7e2SAndroid Build Coastguard Worker 1095*cc02d7e2SAndroid Build Coastguard Worker- (void)testPingPongRPC { 1096*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1097*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1098*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; 1099*cc02d7e2SAndroid Build Coastguard Worker 1100*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @27182, @8, @1828, @45904 ]; 1101*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @31415, @9, @2653, @58979 ]; 1102*cc02d7e2SAndroid Build Coastguard Worker 1103*cc02d7e2SAndroid Build Coastguard Worker GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; 1104*cc02d7e2SAndroid Build Coastguard Worker 1105*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1106*cc02d7e2SAndroid Build Coastguard Worker 1107*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1108*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1109*cc02d7e2SAndroid Build Coastguard Worker [requestsBuffer writeValue:request]; 1110*cc02d7e2SAndroid Build Coastguard Worker 1111*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1112*cc02d7e2SAndroid Build Coastguard Worker [service 1113*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithRequestsWriter:requestsBuffer 1114*cc02d7e2SAndroid Build Coastguard Worker eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, 1115*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1116*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1117*cc02d7e2SAndroid Build Coastguard Worker return; 1118*cc02d7e2SAndroid Build Coastguard Worker } 1119*cc02d7e2SAndroid Build Coastguard Worker 1120*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1121*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1122*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", 1123*cc02d7e2SAndroid Build Coastguard Worker error]); 1124*cc02d7e2SAndroid Build Coastguard Worker assertBlock(done || response, 1125*cc02d7e2SAndroid Build Coastguard Worker @"Event handler called without an event."); 1126*cc02d7e2SAndroid Build Coastguard Worker 1127*cc02d7e2SAndroid Build Coastguard Worker if (response) { 1128*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 1129*cc02d7e2SAndroid Build Coastguard Worker 1130*cc02d7e2SAndroid Build Coastguard Worker id expected = [RMTStreamingOutputCallResponse 1131*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:responses[index]]; 1132*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1133*cc02d7e2SAndroid Build Coastguard Worker [response isEqual:expected], 1134*cc02d7e2SAndroid Build Coastguard Worker [NSString 1135*cc02d7e2SAndroid Build Coastguard Worker stringWithFormat:@"response %@ not equal to expected %@", 1136*cc02d7e2SAndroid Build Coastguard Worker response, expected]); 1137*cc02d7e2SAndroid Build Coastguard Worker 1138*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1139*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 1140*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest 1141*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:requests[index] 1142*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1143*cc02d7e2SAndroid Build Coastguard Worker [requestsBuffer writeValue:request]; 1144*cc02d7e2SAndroid Build Coastguard Worker } else { 1145*cc02d7e2SAndroid Build Coastguard Worker [requestsBuffer writesFinishedWithError:nil]; 1146*cc02d7e2SAndroid Build Coastguard Worker } 1147*cc02d7e2SAndroid Build Coastguard Worker } 1148*cc02d7e2SAndroid Build Coastguard Worker 1149*cc02d7e2SAndroid Build Coastguard Worker if (done) { 1150*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1151*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1152*cc02d7e2SAndroid Build Coastguard Worker [NSString 1153*cc02d7e2SAndroid Build Coastguard Worker stringWithFormat:@"Received %@ responses instead of 4.", 1154*cc02d7e2SAndroid Build Coastguard Worker @(index)]); 1155*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1156*cc02d7e2SAndroid Build Coastguard Worker } 1157*cc02d7e2SAndroid Build Coastguard Worker }]; 1158*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1159*cc02d7e2SAndroid Build Coastguard Worker }); 1160*cc02d7e2SAndroid Build Coastguard Worker} 1161*cc02d7e2SAndroid Build Coastguard Worker 1162*cc02d7e2SAndroid Build Coastguard Worker- (void)testPingPongRPCWithV2API { 1163*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1164*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1165*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPongWithV2API"]; 1166*cc02d7e2SAndroid Build Coastguard Worker 1167*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @27182, @8, @1828, @45904 ]; 1168*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @31415, @9, @2653, @58979 ]; 1169*cc02d7e2SAndroid Build Coastguard Worker 1170*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1171*cc02d7e2SAndroid Build Coastguard Worker 1172*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1173*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1174*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1175*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1176*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1177*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1178*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1179*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1180*cc02d7e2SAndroid Build Coastguard Worker 1181*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 1182*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1183*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1184*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 1185*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1186*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1187*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1188*cc02d7e2SAndroid Build Coastguard Worker return; 1189*cc02d7e2SAndroid Build Coastguard Worker } 1190*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 1191*cc02d7e2SAndroid Build Coastguard Worker 1192*cc02d7e2SAndroid Build Coastguard Worker id expected = 1193*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; 1194*cc02d7e2SAndroid Build Coastguard Worker assertBlock([message isEqual:expected], 1195*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"message %@ not equal to expected %@", 1196*cc02d7e2SAndroid Build Coastguard Worker message, expected]); 1197*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1198*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 1199*cc02d7e2SAndroid Build Coastguard Worker id request = 1200*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1201*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1202*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 1203*cc02d7e2SAndroid Build Coastguard Worker } else { 1204*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 1205*cc02d7e2SAndroid Build Coastguard Worker } 1206*cc02d7e2SAndroid Build Coastguard Worker } 1207*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1208*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1209*cc02d7e2SAndroid Build Coastguard Worker return; 1210*cc02d7e2SAndroid Build Coastguard Worker } 1211*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1212*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1213*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 1214*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1215*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1216*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %@ responses instead of 4.", @(index)]); 1217*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1218*cc02d7e2SAndroid Build Coastguard Worker }] 1219*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1220*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1221*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1222*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1223*cc02d7e2SAndroid Build Coastguard Worker 1224*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1225*cc02d7e2SAndroid Build Coastguard Worker }); 1226*cc02d7e2SAndroid Build Coastguard Worker} 1227*cc02d7e2SAndroid Build Coastguard Worker 1228*cc02d7e2SAndroid Build Coastguard Worker- (void)testPingPongRPCWithFlowControl { 1229*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1230*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1231*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPongWithV2API"]; 1232*cc02d7e2SAndroid Build Coastguard Worker 1233*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @27182, @8, @1828, @45904 ]; 1234*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @31415, @9, @2653, @58979 ]; 1235*cc02d7e2SAndroid Build Coastguard Worker 1236*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1237*cc02d7e2SAndroid Build Coastguard Worker 1238*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1239*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1240*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1241*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1242*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1243*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1244*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1245*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1246*cc02d7e2SAndroid Build Coastguard Worker options.flowControlEnabled = YES; 1247*cc02d7e2SAndroid Build Coastguard Worker __block int writeMessageCount = 0; 1248*cc02d7e2SAndroid Build Coastguard Worker 1249*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 1250*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1251*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1252*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 1253*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1254*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1255*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1256*cc02d7e2SAndroid Build Coastguard Worker return; 1257*cc02d7e2SAndroid Build Coastguard Worker } 1258*cc02d7e2SAndroid Build Coastguard Worker 1259*cc02d7e2SAndroid Build Coastguard Worker assertBlock((index < 4), @"More than 4 responses received."); 1260*cc02d7e2SAndroid Build Coastguard Worker id expected = 1261*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; 1262*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1263*cc02d7e2SAndroid Build Coastguard Worker [message isEqual:expected], 1264*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"message %@ not equal to %@", message, expected]); 1265*cc02d7e2SAndroid Build Coastguard Worker 1266*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1267*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 1268*cc02d7e2SAndroid Build Coastguard Worker id request = 1269*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1270*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1271*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 1272*cc02d7e2SAndroid Build Coastguard Worker [localCall receiveNextMessage]; 1273*cc02d7e2SAndroid Build Coastguard Worker } else { 1274*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 1275*cc02d7e2SAndroid Build Coastguard Worker } 1276*cc02d7e2SAndroid Build Coastguard Worker } 1277*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1278*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1279*cc02d7e2SAndroid Build Coastguard Worker return; 1280*cc02d7e2SAndroid Build Coastguard Worker } 1281*cc02d7e2SAndroid Build Coastguard Worker 1282*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1283*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1284*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 1285*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1286*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1287*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %i responses instead of 4.", index]); 1288*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1289*cc02d7e2SAndroid Build Coastguard Worker } 1290*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:^{ 1291*cc02d7e2SAndroid Build Coastguard Worker writeMessageCount++; 1292*cc02d7e2SAndroid Build Coastguard Worker }] 1293*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1294*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1295*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1296*cc02d7e2SAndroid Build Coastguard Worker [call receiveNextMessage]; 1297*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1298*cc02d7e2SAndroid Build Coastguard Worker 1299*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1300*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1301*cc02d7e2SAndroid Build Coastguard Worker writeMessageCount == 4, 1302*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"writeMessageCount %@ not equal to 4", @(writeMessageCount)]); 1303*cc02d7e2SAndroid Build Coastguard Worker }); 1304*cc02d7e2SAndroid Build Coastguard Worker} 1305*cc02d7e2SAndroid Build Coastguard Worker 1306*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyStreamRPC { 1307*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1308*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1309*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; 1310*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1311*cc02d7e2SAndroid Build Coastguard Worker [service 1312*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] 1313*cc02d7e2SAndroid Build Coastguard Worker eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, 1314*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1315*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1316*cc02d7e2SAndroid Build Coastguard Worker return; 1317*cc02d7e2SAndroid Build Coastguard Worker } 1318*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 1319*cc02d7e2SAndroid Build Coastguard Worker XCTAssert(done, @"Unexpected response: %@", response); 1320*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1321*cc02d7e2SAndroid Build Coastguard Worker }]; 1322*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1323*cc02d7e2SAndroid Build Coastguard Worker }); 1324*cc02d7e2SAndroid Build Coastguard Worker} 1325*cc02d7e2SAndroid Build Coastguard Worker 1326*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelAfterBeginRPC { 1327*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1328*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1329*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; 1330*cc02d7e2SAndroid Build Coastguard Worker 1331*cc02d7e2SAndroid Build Coastguard Worker // A buffered pipe to which we never write any value acts as a writer that just hangs. 1332*cc02d7e2SAndroid Build Coastguard Worker GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; 1333*cc02d7e2SAndroid Build Coastguard Worker 1334*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1335*cc02d7e2SAndroid Build Coastguard Worker GRPCProtoCall *call = [service 1336*cc02d7e2SAndroid Build Coastguard Worker RPCToStreamingInputCallWithRequestsWriter:requestsBuffer 1337*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTStreamingInputCallResponse *response, 1338*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1339*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1340*cc02d7e2SAndroid Build Coastguard Worker return; 1341*cc02d7e2SAndroid Build Coastguard Worker } 1342*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); 1343*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1344*cc02d7e2SAndroid Build Coastguard Worker }]; 1345*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(call.state, GRXWriterStateNotStarted); 1346*cc02d7e2SAndroid Build Coastguard Worker 1347*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1348*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(call.state, GRXWriterStateStarted); 1349*cc02d7e2SAndroid Build Coastguard Worker 1350*cc02d7e2SAndroid Build Coastguard Worker [call cancel]; 1351*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(call.state, GRXWriterStateFinished); 1352*cc02d7e2SAndroid Build Coastguard Worker 1353*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1354*cc02d7e2SAndroid Build Coastguard Worker }); 1355*cc02d7e2SAndroid Build Coastguard Worker} 1356*cc02d7e2SAndroid Build Coastguard Worker 1357*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelAfterBeginRPCWithV2API { 1358*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1359*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1360*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 1361*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"CancelAfterBeginWithV2API"]; 1362*cc02d7e2SAndroid Build Coastguard Worker 1363*cc02d7e2SAndroid Build Coastguard Worker // A buffered pipe to which we never write any value acts as a writer that just hangs. 1364*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1365*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1366*cc02d7e2SAndroid Build Coastguard Worker streamingInputCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 1367*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 1368*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1369*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1370*cc02d7e2SAndroid Build Coastguard Worker return; 1371*cc02d7e2SAndroid Build Coastguard Worker } 1372*cc02d7e2SAndroid Build Coastguard Worker XCTFail(@"Not expected to receive message"); 1373*cc02d7e2SAndroid Build Coastguard Worker } 1374*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 1375*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1376*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1377*cc02d7e2SAndroid Build Coastguard Worker return; 1378*cc02d7e2SAndroid Build Coastguard Worker } 1379*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, 1380*cc02d7e2SAndroid Build Coastguard Worker GRPC_STATUS_CANCELLED); 1381*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1382*cc02d7e2SAndroid Build Coastguard Worker }] 1383*cc02d7e2SAndroid Build Coastguard Worker callOptions:nil]; 1384*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1385*cc02d7e2SAndroid Build Coastguard Worker [call cancel]; 1386*cc02d7e2SAndroid Build Coastguard Worker 1387*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1388*cc02d7e2SAndroid Build Coastguard Worker }); 1389*cc02d7e2SAndroid Build Coastguard Worker} 1390*cc02d7e2SAndroid Build Coastguard Worker 1391*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelAfterFirstResponseRPC { 1392*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1393*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1394*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 1395*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"CancelAfterFirstResponse"]; 1396*cc02d7e2SAndroid Build Coastguard Worker 1397*cc02d7e2SAndroid Build Coastguard Worker // A buffered pipe to which we write a single value but never close 1398*cc02d7e2SAndroid Build Coastguard Worker GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; 1399*cc02d7e2SAndroid Build Coastguard Worker 1400*cc02d7e2SAndroid Build Coastguard Worker __block BOOL receivedResponse = NO; 1401*cc02d7e2SAndroid Build Coastguard Worker 1402*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 1403*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:@31415]; 1404*cc02d7e2SAndroid Build Coastguard Worker 1405*cc02d7e2SAndroid Build Coastguard Worker [requestsBuffer writeValue:request]; 1406*cc02d7e2SAndroid Build Coastguard Worker 1407*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1408*cc02d7e2SAndroid Build Coastguard Worker __block GRPCProtoCall *call = [service 1409*cc02d7e2SAndroid Build Coastguard Worker RPCToFullDuplexCallWithRequestsWriter:requestsBuffer 1410*cc02d7e2SAndroid Build Coastguard Worker eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, 1411*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1412*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1413*cc02d7e2SAndroid Build Coastguard Worker return; 1414*cc02d7e2SAndroid Build Coastguard Worker } 1415*cc02d7e2SAndroid Build Coastguard Worker if (receivedResponse) { 1416*cc02d7e2SAndroid Build Coastguard Worker XCTAssert(done, @"Unexpected extra response %@", response); 1417*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); 1418*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1419*cc02d7e2SAndroid Build Coastguard Worker } else { 1420*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", 1421*cc02d7e2SAndroid Build Coastguard Worker error); 1422*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(done, @"Finished without response"); 1423*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotNil(response); 1424*cc02d7e2SAndroid Build Coastguard Worker receivedResponse = YES; 1425*cc02d7e2SAndroid Build Coastguard Worker [call cancel]; 1426*cc02d7e2SAndroid Build Coastguard Worker } 1427*cc02d7e2SAndroid Build Coastguard Worker }]; 1428*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1429*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1430*cc02d7e2SAndroid Build Coastguard Worker }); 1431*cc02d7e2SAndroid Build Coastguard Worker} 1432*cc02d7e2SAndroid Build Coastguard Worker 1433*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelAfterFirstResponseRPCWithV2API { 1434*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1435*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1436*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *completionExpectation = 1437*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Call completed."]; 1438*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *responseExpectation = 1439*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Received response."]; 1440*cc02d7e2SAndroid Build Coastguard Worker 1441*cc02d7e2SAndroid Build Coastguard Worker __block BOOL receivedResponse = NO; 1442*cc02d7e2SAndroid Build Coastguard Worker 1443*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1444*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1445*cc02d7e2SAndroid Build Coastguard Worker options.transportType = self.class.transportType; 1446*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1447*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = self.class.PEMRootCertificates; 1448*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1449*cc02d7e2SAndroid Build Coastguard Worker 1450*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 1451*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:@31415]; 1452*cc02d7e2SAndroid Build Coastguard Worker 1453*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 1454*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1455*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 1456*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 1457*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1458*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1459*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1460*cc02d7e2SAndroid Build Coastguard Worker return; 1461*cc02d7e2SAndroid Build Coastguard Worker } 1462*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(receivedResponse); 1463*cc02d7e2SAndroid Build Coastguard Worker receivedResponse = YES; 1464*cc02d7e2SAndroid Build Coastguard Worker [localCall cancel]; 1465*cc02d7e2SAndroid Build Coastguard Worker [responseExpectation fulfill]; 1466*cc02d7e2SAndroid Build Coastguard Worker } 1467*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 1468*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1469*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1470*cc02d7e2SAndroid Build Coastguard Worker return; 1471*cc02d7e2SAndroid Build Coastguard Worker } 1472*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); 1473*cc02d7e2SAndroid Build Coastguard Worker [completionExpectation fulfill]; 1474*cc02d7e2SAndroid Build Coastguard Worker }] 1475*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1476*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1477*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1478*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1479*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ completionExpectation, responseExpectation ], GRPCInteropTestTimeoutDefault); 1480*cc02d7e2SAndroid Build Coastguard Worker }); 1481*cc02d7e2SAndroid Build Coastguard Worker} 1482*cc02d7e2SAndroid Build Coastguard Worker 1483*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelAfterFirstRequestWithV2API { 1484*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1485*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1486*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *completionExpectation = 1487*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Call completed."]; 1488*cc02d7e2SAndroid Build Coastguard Worker 1489*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1490*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1491*cc02d7e2SAndroid Build Coastguard Worker options.transportType = self.class.transportType; 1492*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1493*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = self.class.PEMRootCertificates; 1494*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1495*cc02d7e2SAndroid Build Coastguard Worker 1496*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 1497*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:@31415]; 1498*cc02d7e2SAndroid Build Coastguard Worker 1499*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1500*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1501*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 1502*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 1503*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1504*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1505*cc02d7e2SAndroid Build Coastguard Worker return; 1506*cc02d7e2SAndroid Build Coastguard Worker } 1507*cc02d7e2SAndroid Build Coastguard Worker XCTFail(@"Received unexpected response."); 1508*cc02d7e2SAndroid Build Coastguard Worker } 1509*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 1510*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 1511*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1512*cc02d7e2SAndroid Build Coastguard Worker return; 1513*cc02d7e2SAndroid Build Coastguard Worker } 1514*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); 1515*cc02d7e2SAndroid Build Coastguard Worker [completionExpectation fulfill]; 1516*cc02d7e2SAndroid Build Coastguard Worker }] 1517*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1518*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1519*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1520*cc02d7e2SAndroid Build Coastguard Worker [call cancel]; 1521*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ completionExpectation ], GRPCInteropTestTimeoutDefault); 1522*cc02d7e2SAndroid Build Coastguard Worker }); 1523*cc02d7e2SAndroid Build Coastguard Worker} 1524*cc02d7e2SAndroid Build Coastguard Worker 1525*cc02d7e2SAndroid Build Coastguard Worker- (void)testRPCAfterClosingOpenConnections { 1526*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1527*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1528*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 1529*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"RPC after closing connection"]; 1530*cc02d7e2SAndroid Build Coastguard Worker 1531*cc02d7e2SAndroid Build Coastguard Worker GPBEmpty *request = [GPBEmpty message]; 1532*cc02d7e2SAndroid Build Coastguard Worker 1533*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1534*cc02d7e2SAndroid Build Coastguard Worker [service 1535*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithRequest:request 1536*cc02d7e2SAndroid Build Coastguard Worker handler:^(GPBEmpty *response, NSError *error) { 1537*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1538*cc02d7e2SAndroid Build Coastguard Worker return; 1539*cc02d7e2SAndroid Build Coastguard Worker } 1540*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error); 1541*cc02d7e2SAndroid Build Coastguard Worker 1542*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic push 1543*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdeprecated-declarations" 1544*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall closeOpenConnections]; 1545*cc02d7e2SAndroid Build Coastguard Worker#pragma clang diagnostic pop 1546*cc02d7e2SAndroid Build Coastguard Worker 1547*cc02d7e2SAndroid Build Coastguard Worker [weakService 1548*cc02d7e2SAndroid Build Coastguard Worker emptyCallWithRequest:request 1549*cc02d7e2SAndroid Build Coastguard Worker handler:^(GPBEmpty *response, NSError *error) { 1550*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil( 1551*cc02d7e2SAndroid Build Coastguard Worker error, 1552*cc02d7e2SAndroid Build Coastguard Worker @"Second RPC finished with unexpected error: %@", 1553*cc02d7e2SAndroid Build Coastguard Worker error); 1554*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1555*cc02d7e2SAndroid Build Coastguard Worker }]; 1556*cc02d7e2SAndroid Build Coastguard Worker }]; 1557*cc02d7e2SAndroid Build Coastguard Worker 1558*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1559*cc02d7e2SAndroid Build Coastguard Worker }); 1560*cc02d7e2SAndroid Build Coastguard Worker} 1561*cc02d7e2SAndroid Build Coastguard Worker 1562*cc02d7e2SAndroid Build Coastguard Worker- (void)testCompressedUnaryRPC { 1563*cc02d7e2SAndroid Build Coastguard Worker // This test needs to be disabled for remote test because interop server grpc-test 1564*cc02d7e2SAndroid Build Coastguard Worker // does not support compression. 1565*cc02d7e2SAndroid Build Coastguard Worker if (isRemoteInteropTest([[self class] host])) { 1566*cc02d7e2SAndroid Build Coastguard Worker return; 1567*cc02d7e2SAndroid Build Coastguard Worker } 1568*cc02d7e2SAndroid Build Coastguard Worker 1569*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1570*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1571*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; 1572*cc02d7e2SAndroid Build Coastguard Worker 1573*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleRequest *request = [RMTSimpleRequest message]; 1574*cc02d7e2SAndroid Build Coastguard Worker request.responseType = RMTPayloadType_Compressable; 1575*cc02d7e2SAndroid Build Coastguard Worker request.responseSize = LARGE_RESPONSE_PAYLOAD_SIZE; 1576*cc02d7e2SAndroid Build Coastguard Worker request.payload.body = [NSMutableData dataWithLength:LARGE_REQUEST_PAYLOAD_SIZE]; 1577*cc02d7e2SAndroid Build Coastguard Worker request.expectCompressed.value = YES; 1578*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall setDefaultCompressMethod:GRPCCompressGzip forhost:[[self class] host]]; 1579*cc02d7e2SAndroid Build Coastguard Worker 1580*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1581*cc02d7e2SAndroid Build Coastguard Worker [service unaryCallWithRequest:request 1582*cc02d7e2SAndroid Build Coastguard Worker handler:^(RMTSimpleResponse *response, NSError *error) { 1583*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1584*cc02d7e2SAndroid Build Coastguard Worker return; 1585*cc02d7e2SAndroid Build Coastguard Worker } 1586*cc02d7e2SAndroid Build Coastguard Worker 1587*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(error, @"Finished with unexpected error: %@", error); 1588*cc02d7e2SAndroid Build Coastguard Worker 1589*cc02d7e2SAndroid Build Coastguard Worker RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; 1590*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.type = RMTPayloadType_Compressable; 1591*cc02d7e2SAndroid Build Coastguard Worker expectedResponse.payload.body = 1592*cc02d7e2SAndroid Build Coastguard Worker [NSMutableData dataWithLength:LARGE_RESPONSE_PAYLOAD_SIZE]; 1593*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(response, expectedResponse); 1594*cc02d7e2SAndroid Build Coastguard Worker 1595*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1596*cc02d7e2SAndroid Build Coastguard Worker }]; 1597*cc02d7e2SAndroid Build Coastguard Worker 1598*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1599*cc02d7e2SAndroid Build Coastguard Worker }); 1600*cc02d7e2SAndroid Build Coastguard Worker} 1601*cc02d7e2SAndroid Build Coastguard Worker 1602*cc02d7e2SAndroid Build Coastguard Worker// TODO(b/268379869): This test has a race and is flaky in any configurations. One possible way to 1603*cc02d7e2SAndroid Build Coastguard Worker// deflake this test is to find a way to disable ping ack on the interop server for this test case. 1604*cc02d7e2SAndroid Build Coastguard Worker- (void)testKeepaliveWithV2API { 1605*cc02d7e2SAndroid Build Coastguard Worker return; 1606*cc02d7e2SAndroid Build Coastguard Worker 1607*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1608*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1609*cc02d7e2SAndroid Build Coastguard Worker if ([[self class] transport] == gGRPCCoreCronetID) { 1610*cc02d7e2SAndroid Build Coastguard Worker // Cronet does not support keepalive 1611*cc02d7e2SAndroid Build Coastguard Worker return; 1612*cc02d7e2SAndroid Build Coastguard Worker } 1613*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Keepalive"]; 1614*cc02d7e2SAndroid Build Coastguard Worker 1615*cc02d7e2SAndroid Build Coastguard Worker const NSTimeInterval kTestTimeout = 5; 1616*cc02d7e2SAndroid Build Coastguard Worker NSNumber *kRequestSize = @27182; 1617*cc02d7e2SAndroid Build Coastguard Worker NSNumber *kResponseSize = @31415; 1618*cc02d7e2SAndroid Build Coastguard Worker 1619*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:kRequestSize 1620*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:kResponseSize]; 1621*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1622*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1623*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1624*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1625*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1626*cc02d7e2SAndroid Build Coastguard Worker options.keepaliveInterval = 1.5; 1627*cc02d7e2SAndroid Build Coastguard Worker options.keepaliveTimeout = 0; 1628*cc02d7e2SAndroid Build Coastguard Worker 1629*cc02d7e2SAndroid Build Coastguard Worker __weak RMTTestService *weakService = service; 1630*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1631*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1632*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] 1633*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 1634*cc02d7e2SAndroid Build Coastguard Worker messageCallback:nil 1635*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1636*cc02d7e2SAndroid Build Coastguard Worker if (weakService == nil) { 1637*cc02d7e2SAndroid Build Coastguard Worker return; 1638*cc02d7e2SAndroid Build Coastguard Worker } 1639*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotNil(error); 1640*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual( 1641*cc02d7e2SAndroid Build Coastguard Worker error.code, GRPC_STATUS_UNAVAILABLE, 1642*cc02d7e2SAndroid Build Coastguard Worker @"Received status %@ instead of UNAVAILABLE (14).", 1643*cc02d7e2SAndroid Build Coastguard Worker @(error.code)); 1644*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1645*cc02d7e2SAndroid Build Coastguard Worker }] 1646*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1647*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1648*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1649*cc02d7e2SAndroid Build Coastguard Worker 1650*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], kTestTimeout); 1651*cc02d7e2SAndroid Build Coastguard Worker [call finish]; 1652*cc02d7e2SAndroid Build Coastguard Worker }); 1653*cc02d7e2SAndroid Build Coastguard Worker} 1654*cc02d7e2SAndroid Build Coastguard Worker 1655*cc02d7e2SAndroid Build Coastguard Worker- (void)testDefaultInterceptor { 1656*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1657*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1658*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 1659*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"testDefaultInterceptor"]; 1660*cc02d7e2SAndroid Build Coastguard Worker 1661*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @27182, @8, @1828, @45904 ]; 1662*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @31415, @9, @2653, @58979 ]; 1663*cc02d7e2SAndroid Build Coastguard Worker 1664*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1665*cc02d7e2SAndroid Build Coastguard Worker 1666*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1667*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1668*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1669*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1670*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1671*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1672*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1673*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1674*cc02d7e2SAndroid Build Coastguard Worker options.interceptorFactories = @[ [[DefaultInterceptorFactory alloc] init] ]; 1675*cc02d7e2SAndroid Build Coastguard Worker 1676*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 1677*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1678*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1679*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 1680*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1681*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1682*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1683*cc02d7e2SAndroid Build Coastguard Worker return; 1684*cc02d7e2SAndroid Build Coastguard Worker } 1685*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 1686*cc02d7e2SAndroid Build Coastguard Worker 1687*cc02d7e2SAndroid Build Coastguard Worker id expected = 1688*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; 1689*cc02d7e2SAndroid Build Coastguard Worker assertBlock([message isEqual:expected], 1690*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"message %@ not equal to expected %@", 1691*cc02d7e2SAndroid Build Coastguard Worker message, expected]); 1692*cc02d7e2SAndroid Build Coastguard Worker 1693*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1694*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 1695*cc02d7e2SAndroid Build Coastguard Worker id request = 1696*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1697*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1698*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 1699*cc02d7e2SAndroid Build Coastguard Worker } else { 1700*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 1701*cc02d7e2SAndroid Build Coastguard Worker } 1702*cc02d7e2SAndroid Build Coastguard Worker } 1703*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1704*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1705*cc02d7e2SAndroid Build Coastguard Worker return; 1706*cc02d7e2SAndroid Build Coastguard Worker } 1707*cc02d7e2SAndroid Build Coastguard Worker 1708*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1709*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1710*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %@ responses instead of 4.", @(index)]); 1711*cc02d7e2SAndroid Build Coastguard Worker 1712*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1713*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1714*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 1715*cc02d7e2SAndroid Build Coastguard Worker 1716*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1717*cc02d7e2SAndroid Build Coastguard Worker }] 1718*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1719*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1720*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1721*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1722*cc02d7e2SAndroid Build Coastguard Worker 1723*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1724*cc02d7e2SAndroid Build Coastguard Worker }); 1725*cc02d7e2SAndroid Build Coastguard Worker} 1726*cc02d7e2SAndroid Build Coastguard Worker 1727*cc02d7e2SAndroid Build Coastguard Worker- (void)testLoggingInterceptor { 1728*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1729*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1730*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 1731*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"testLoggingInterceptor"]; 1732*cc02d7e2SAndroid Build Coastguard Worker 1733*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger startCount = 0; 1734*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger writeDataCount = 0; 1735*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger finishCount = 0; 1736*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger receiveNextMessageCount = 0; 1737*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseHeaderCount = 0; 1738*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseDataCount = 0; 1739*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseCloseCount = 0; 1740*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger didWriteDataCount = 0; 1741*cc02d7e2SAndroid Build Coastguard Worker id<GRPCInterceptorFactory> factory = [[HookInterceptorFactory alloc] 1742*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) 1743*cc02d7e2SAndroid Build Coastguard Worker startHook:^(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 1744*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 1745*cc02d7e2SAndroid Build Coastguard Worker startCount++; 1746*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.host, [[self class] host]); 1747*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.path, @"/grpc.testing.TestService/FullDuplexCall"); 1748*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(requestOptions.safety, GRPCCallSafetyDefault); 1749*cc02d7e2SAndroid Build Coastguard Worker [manager startNextInterceptorWithRequest:[requestOptions copy] 1750*cc02d7e2SAndroid Build Coastguard Worker callOptions:[callOptions copy]]; 1751*cc02d7e2SAndroid Build Coastguard Worker } 1752*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:^(id data, GRPCInterceptorManager *manager) { 1753*cc02d7e2SAndroid Build Coastguard Worker writeDataCount++; 1754*cc02d7e2SAndroid Build Coastguard Worker [manager writeNextInterceptorWithData:data]; 1755*cc02d7e2SAndroid Build Coastguard Worker } 1756*cc02d7e2SAndroid Build Coastguard Worker finishHook:^(GRPCInterceptorManager *manager) { 1757*cc02d7e2SAndroid Build Coastguard Worker finishCount++; 1758*cc02d7e2SAndroid Build Coastguard Worker [manager finishNextInterceptor]; 1759*cc02d7e2SAndroid Build Coastguard Worker } 1760*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:^(NSUInteger numberOfMessages, GRPCInterceptorManager *manager) { 1761*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessageCount++; 1762*cc02d7e2SAndroid Build Coastguard Worker [manager receiveNextInterceptorMessages:numberOfMessages]; 1763*cc02d7e2SAndroid Build Coastguard Worker } 1764*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:^(NSDictionary *initialMetadata, GRPCInterceptorManager *manager) { 1765*cc02d7e2SAndroid Build Coastguard Worker responseHeaderCount++; 1766*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata]; 1767*cc02d7e2SAndroid Build Coastguard Worker } 1768*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:^(id data, GRPCInterceptorManager *manager) { 1769*cc02d7e2SAndroid Build Coastguard Worker responseDataCount++; 1770*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:data]; 1771*cc02d7e2SAndroid Build Coastguard Worker } 1772*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:^(NSDictionary *trailingMetadata, NSError *error, 1773*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 1774*cc02d7e2SAndroid Build Coastguard Worker responseCloseCount++; 1775*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata 1776*cc02d7e2SAndroid Build Coastguard Worker error:error]; 1777*cc02d7e2SAndroid Build Coastguard Worker } 1778*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:^(GRPCInterceptorManager *manager) { 1779*cc02d7e2SAndroid Build Coastguard Worker didWriteDataCount++; 1780*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorDidWriteData]; 1781*cc02d7e2SAndroid Build Coastguard Worker }]; 1782*cc02d7e2SAndroid Build Coastguard Worker 1783*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @1, @2, @3, @4 ]; 1784*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @1, @2, @3, @4 ]; 1785*cc02d7e2SAndroid Build Coastguard Worker 1786*cc02d7e2SAndroid Build Coastguard Worker __block int messageIndex = 0; 1787*cc02d7e2SAndroid Build Coastguard Worker 1788*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[messageIndex] 1789*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[messageIndex]]; 1790*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1791*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1792*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1793*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1794*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1795*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1796*cc02d7e2SAndroid Build Coastguard Worker options.flowControlEnabled = YES; 1797*cc02d7e2SAndroid Build Coastguard Worker options.interceptorFactories = @[ factory ]; 1798*cc02d7e2SAndroid Build Coastguard Worker 1799*cc02d7e2SAndroid Build Coastguard Worker __block int writeMessageCount = 0; 1800*cc02d7e2SAndroid Build Coastguard Worker __block __weak GRPCStreamingProtoCall *weakCall; 1801*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1802*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1803*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 1804*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1805*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1806*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1807*cc02d7e2SAndroid Build Coastguard Worker return; 1808*cc02d7e2SAndroid Build Coastguard Worker } 1809*cc02d7e2SAndroid Build Coastguard Worker assertBlock((messageIndex < 4), @"More than 4 responses received."); 1810*cc02d7e2SAndroid Build Coastguard Worker 1811*cc02d7e2SAndroid Build Coastguard Worker id expected = [RMTStreamingOutputCallResponse 1812*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:responses[messageIndex]]; 1813*cc02d7e2SAndroid Build Coastguard Worker assertBlock([message isEqual:expected], 1814*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"message %@ not equal to expected %@", 1815*cc02d7e2SAndroid Build Coastguard Worker message, expected]); 1816*cc02d7e2SAndroid Build Coastguard Worker messageIndex += 1; 1817*cc02d7e2SAndroid Build Coastguard Worker if (messageIndex < 4) { 1818*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest 1819*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:requests[messageIndex] 1820*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[messageIndex]]; 1821*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 1822*cc02d7e2SAndroid Build Coastguard Worker [localCall receiveNextMessage]; 1823*cc02d7e2SAndroid Build Coastguard Worker } else { 1824*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 1825*cc02d7e2SAndroid Build Coastguard Worker } 1826*cc02d7e2SAndroid Build Coastguard Worker } 1827*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1828*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1829*cc02d7e2SAndroid Build Coastguard Worker return; 1830*cc02d7e2SAndroid Build Coastguard Worker } 1831*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1832*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1833*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 1834*cc02d7e2SAndroid Build Coastguard Worker assertBlock(messageIndex == 4, 1835*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %@ responses instead of 4.", 1836*cc02d7e2SAndroid Build Coastguard Worker @(messageIndex)]); 1837*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 1838*cc02d7e2SAndroid Build Coastguard Worker } 1839*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:^{ 1840*cc02d7e2SAndroid Build Coastguard Worker writeMessageCount++; 1841*cc02d7e2SAndroid Build Coastguard Worker }] 1842*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1843*cc02d7e2SAndroid Build Coastguard Worker 1844*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1845*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1846*cc02d7e2SAndroid Build Coastguard Worker [call receiveNextMessage]; 1847*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1848*cc02d7e2SAndroid Build Coastguard Worker 1849*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 1850*cc02d7e2SAndroid Build Coastguard Worker 1851*cc02d7e2SAndroid Build Coastguard Worker assertBlock(startCount == 1, [NSString stringWithFormat:@"%@", @(startCount)]); 1852*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeDataCount == 4, [NSString stringWithFormat:@"%@", @(writeDataCount)]); 1853*cc02d7e2SAndroid Build Coastguard Worker assertBlock(finishCount == 1, [NSString stringWithFormat:@"%@", @(finishCount)]); 1854*cc02d7e2SAndroid Build Coastguard Worker assertBlock(receiveNextMessageCount == 4, 1855*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(receiveNextMessageCount)]); 1856*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseHeaderCount == 1, 1857*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(responseHeaderCount)]); 1858*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseDataCount == 4, [NSString stringWithFormat:@"%@", @(responseDataCount)]); 1859*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseCloseCount == 1, [NSString stringWithFormat:@"%@", @(responseCloseCount)]); 1860*cc02d7e2SAndroid Build Coastguard Worker assertBlock(didWriteDataCount == 4, [NSString stringWithFormat:@"%@", @(didWriteDataCount)]); 1861*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeMessageCount == 4, [NSString stringWithFormat:@"%@", @(writeMessageCount)]); 1862*cc02d7e2SAndroid Build Coastguard Worker }); 1863*cc02d7e2SAndroid Build Coastguard Worker} 1864*cc02d7e2SAndroid Build Coastguard Worker 1865*cc02d7e2SAndroid Build Coastguard Worker// Chain a default interceptor and a hook interceptor which, after one write, cancels the call 1866*cc02d7e2SAndroid Build Coastguard Worker// under the hood but forward further data to the user. 1867*cc02d7e2SAndroid Build Coastguard Worker- (void)testHijackingInterceptor { 1868*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 1869*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 1870*cc02d7e2SAndroid Build Coastguard Worker NSUInteger kCancelAfterWrites = 1; 1871*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectUserCallComplete = 1872*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"User call completed."]; 1873*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectResponseCallbackComplete = 1874*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"Hook interceptor response callback completed"]; 1875*cc02d7e2SAndroid Build Coastguard Worker 1876*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @1, @2, @3, @4 ]; 1877*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 1878*cc02d7e2SAndroid Build Coastguard Worker 1879*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger startCount = 0; 1880*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger writeDataCount = 0; 1881*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger finishCount = 0; 1882*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseHeaderCount = 0; 1883*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseDataCount = 0; 1884*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseCloseCount = 0; 1885*cc02d7e2SAndroid Build Coastguard Worker id<GRPCInterceptorFactory> factory = [[HookInterceptorFactory alloc] 1886*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) 1887*cc02d7e2SAndroid Build Coastguard Worker startHook:^(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 1888*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 1889*cc02d7e2SAndroid Build Coastguard Worker startCount++; 1890*cc02d7e2SAndroid Build Coastguard Worker [manager startNextInterceptorWithRequest:[requestOptions copy] 1891*cc02d7e2SAndroid Build Coastguard Worker callOptions:[callOptions copy]]; 1892*cc02d7e2SAndroid Build Coastguard Worker } 1893*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:^(id data, GRPCInterceptorManager *manager) { 1894*cc02d7e2SAndroid Build Coastguard Worker writeDataCount++; 1895*cc02d7e2SAndroid Build Coastguard Worker if (index < kCancelAfterWrites) { 1896*cc02d7e2SAndroid Build Coastguard Worker [manager writeNextInterceptorWithData:data]; 1897*cc02d7e2SAndroid Build Coastguard Worker } else if (index == kCancelAfterWrites) { 1898*cc02d7e2SAndroid Build Coastguard Worker [manager cancelNextInterceptor]; 1899*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:[[RMTStreamingOutputCallResponse 1900*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:responses[index]] 1901*cc02d7e2SAndroid Build Coastguard Worker data]]; 1902*cc02d7e2SAndroid Build Coastguard Worker } else { // (index > kCancelAfterWrites) 1903*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:[[RMTStreamingOutputCallResponse 1904*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:responses[index]] 1905*cc02d7e2SAndroid Build Coastguard Worker data]]; 1906*cc02d7e2SAndroid Build Coastguard Worker } 1907*cc02d7e2SAndroid Build Coastguard Worker } 1908*cc02d7e2SAndroid Build Coastguard Worker finishHook:^(GRPCInterceptorManager *manager) { 1909*cc02d7e2SAndroid Build Coastguard Worker finishCount++; 1910*cc02d7e2SAndroid Build Coastguard Worker // finish must happen after the hijacking, so directly reply with a close 1911*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorCloseWithTrailingMetadata:@{@"grpc-status" : @"0"} 1912*cc02d7e2SAndroid Build Coastguard Worker error:nil]; 1913*cc02d7e2SAndroid Build Coastguard Worker [manager shutDown]; 1914*cc02d7e2SAndroid Build Coastguard Worker } 1915*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:nil 1916*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:^(NSDictionary *initialMetadata, GRPCInterceptorManager *manager) { 1917*cc02d7e2SAndroid Build Coastguard Worker responseHeaderCount++; 1918*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata]; 1919*cc02d7e2SAndroid Build Coastguard Worker } 1920*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:^(id data, GRPCInterceptorManager *manager) { 1921*cc02d7e2SAndroid Build Coastguard Worker responseDataCount++; 1922*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:data]; 1923*cc02d7e2SAndroid Build Coastguard Worker } 1924*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:^(NSDictionary *trailingMetadata, NSError *error, 1925*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 1926*cc02d7e2SAndroid Build Coastguard Worker responseCloseCount++; 1927*cc02d7e2SAndroid Build Coastguard Worker // since we canceled the call, it should return cancel error 1928*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNil(trailingMetadata); 1929*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotNil(error); 1930*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); 1931*cc02d7e2SAndroid Build Coastguard Worker [expectResponseCallbackComplete fulfill]; 1932*cc02d7e2SAndroid Build Coastguard Worker } 1933*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:nil]; 1934*cc02d7e2SAndroid Build Coastguard Worker 1935*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @1, @2, @3, @4 ]; 1936*cc02d7e2SAndroid Build Coastguard Worker 1937*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1938*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1939*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 1940*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 1941*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 1942*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 1943*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 1944*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 1945*cc02d7e2SAndroid Build Coastguard Worker options.interceptorFactories = @[ [[DefaultInterceptorFactory alloc] init], factory ]; 1946*cc02d7e2SAndroid Build Coastguard Worker 1947*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 1948*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 1949*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 1950*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 1951*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 1952*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 1953*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 1954*cc02d7e2SAndroid Build Coastguard Worker return; 1955*cc02d7e2SAndroid Build Coastguard Worker } 1956*cc02d7e2SAndroid Build Coastguard Worker 1957*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 1958*cc02d7e2SAndroid Build Coastguard Worker 1959*cc02d7e2SAndroid Build Coastguard Worker id expected = 1960*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; 1961*cc02d7e2SAndroid Build Coastguard Worker assertBlock([message isEqual:expected], 1962*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"message %@ not equal to expected %@", 1963*cc02d7e2SAndroid Build Coastguard Worker message, expected]); 1964*cc02d7e2SAndroid Build Coastguard Worker index += 1; 1965*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 1966*cc02d7e2SAndroid Build Coastguard Worker id request = 1967*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 1968*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 1969*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 1970*cc02d7e2SAndroid Build Coastguard Worker [localCall receiveNextMessage]; 1971*cc02d7e2SAndroid Build Coastguard Worker } else { 1972*cc02d7e2SAndroid Build Coastguard Worker [self waitForExpectations:@[ expectResponseCallbackComplete ] 1973*cc02d7e2SAndroid Build Coastguard Worker timeout:GRPCInteropTestTimeoutDefault]; 1974*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 1975*cc02d7e2SAndroid Build Coastguard Worker } 1976*cc02d7e2SAndroid Build Coastguard Worker } 1977*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 1978*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 1979*cc02d7e2SAndroid Build Coastguard Worker return; 1980*cc02d7e2SAndroid Build Coastguard Worker } 1981*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1982*cc02d7e2SAndroid Build Coastguard Worker error == nil, 1983*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 1984*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 1985*cc02d7e2SAndroid Build Coastguard Worker index == 4, 1986*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Received %@ responses instead of 4.", @(index)]); 1987*cc02d7e2SAndroid Build Coastguard Worker 1988*cc02d7e2SAndroid Build Coastguard Worker [expectUserCallComplete fulfill]; 1989*cc02d7e2SAndroid Build Coastguard Worker }] 1990*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 1991*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 1992*cc02d7e2SAndroid Build Coastguard Worker [call start]; 1993*cc02d7e2SAndroid Build Coastguard Worker [call receiveNextMessage]; 1994*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 1995*cc02d7e2SAndroid Build Coastguard Worker 1996*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectUserCallComplete ], GRPCInteropTestTimeoutDefault); 1997*cc02d7e2SAndroid Build Coastguard Worker assertBlock(startCount == 1, [NSString stringWithFormat:@"%@", @(startCount)]); 1998*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeDataCount == 4, [NSString stringWithFormat:@"%@", @(writeDataCount)]); 1999*cc02d7e2SAndroid Build Coastguard Worker assertBlock(finishCount == 1, [NSString stringWithFormat:@"%@", @(finishCount)]); 2000*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseHeaderCount == 1, 2001*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(responseHeaderCount)]); 2002*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseDataCount == 1, [NSString stringWithFormat:@"%@", @(responseDataCount)]); 2003*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseCloseCount == 1, [NSString stringWithFormat:@"%@", @(responseCloseCount)]); 2004*cc02d7e2SAndroid Build Coastguard Worker }); 2005*cc02d7e2SAndroid Build Coastguard Worker} 2006*cc02d7e2SAndroid Build Coastguard Worker 2007*cc02d7e2SAndroid Build Coastguard Worker- (void)testGlobalInterceptor { 2008*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 2009*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 2010*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 2011*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"testGlobalInterceptor"]; 2012*cc02d7e2SAndroid Build Coastguard Worker 2013*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger startCount = 0; 2014*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger writeDataCount = 0; 2015*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger finishCount = 0; 2016*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger receiveNextMessageCount = 0; 2017*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseHeaderCount = 0; 2018*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseDataCount = 0; 2019*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseCloseCount = 0; 2020*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger didWriteDataCount = 0; 2021*cc02d7e2SAndroid Build Coastguard Worker [globalInterceptorFactory 2022*cc02d7e2SAndroid Build Coastguard Worker setStartHook:^(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 2023*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2024*cc02d7e2SAndroid Build Coastguard Worker startCount++; 2025*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.host, [[self class] host]); 2026*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.path, @"/grpc.testing.TestService/FullDuplexCall"); 2027*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(requestOptions.safety, GRPCCallSafetyDefault); 2028*cc02d7e2SAndroid Build Coastguard Worker [manager startNextInterceptorWithRequest:[requestOptions copy] 2029*cc02d7e2SAndroid Build Coastguard Worker callOptions:[callOptions copy]]; 2030*cc02d7e2SAndroid Build Coastguard Worker } 2031*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:^(id data, GRPCInterceptorManager *manager) { 2032*cc02d7e2SAndroid Build Coastguard Worker writeDataCount++; 2033*cc02d7e2SAndroid Build Coastguard Worker [manager writeNextInterceptorWithData:data]; 2034*cc02d7e2SAndroid Build Coastguard Worker } 2035*cc02d7e2SAndroid Build Coastguard Worker finishHook:^(GRPCInterceptorManager *manager) { 2036*cc02d7e2SAndroid Build Coastguard Worker finishCount++; 2037*cc02d7e2SAndroid Build Coastguard Worker [manager finishNextInterceptor]; 2038*cc02d7e2SAndroid Build Coastguard Worker } 2039*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:^(NSUInteger numberOfMessages, GRPCInterceptorManager *manager) { 2040*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessageCount++; 2041*cc02d7e2SAndroid Build Coastguard Worker [manager receiveNextInterceptorMessages:numberOfMessages]; 2042*cc02d7e2SAndroid Build Coastguard Worker } 2043*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:^(NSDictionary *initialMetadata, GRPCInterceptorManager *manager) { 2044*cc02d7e2SAndroid Build Coastguard Worker responseHeaderCount++; 2045*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata]; 2046*cc02d7e2SAndroid Build Coastguard Worker } 2047*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:^(id data, GRPCInterceptorManager *manager) { 2048*cc02d7e2SAndroid Build Coastguard Worker responseDataCount++; 2049*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:data]; 2050*cc02d7e2SAndroid Build Coastguard Worker } 2051*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:^(NSDictionary *trailingMetadata, NSError *error, 2052*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2053*cc02d7e2SAndroid Build Coastguard Worker responseCloseCount++; 2054*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata 2055*cc02d7e2SAndroid Build Coastguard Worker error:error]; 2056*cc02d7e2SAndroid Build Coastguard Worker } 2057*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:^(GRPCInterceptorManager *manager) { 2058*cc02d7e2SAndroid Build Coastguard Worker didWriteDataCount++; 2059*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorDidWriteData]; 2060*cc02d7e2SAndroid Build Coastguard Worker }]; 2061*cc02d7e2SAndroid Build Coastguard Worker 2062*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @1, @2, @3, @4 ]; 2063*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @1, @2, @3, @4 ]; 2064*cc02d7e2SAndroid Build Coastguard Worker 2065*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 2066*cc02d7e2SAndroid Build Coastguard Worker 2067*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 2068*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 2069*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 2070*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 2071*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 2072*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 2073*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 2074*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 2075*cc02d7e2SAndroid Build Coastguard Worker options.flowControlEnabled = YES; 2076*cc02d7e2SAndroid Build Coastguard Worker globalInterceptorFactory.enabled = YES; 2077*cc02d7e2SAndroid Build Coastguard Worker 2078*cc02d7e2SAndroid Build Coastguard Worker __block int writeMessageCount = 0; 2079*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 2080*cc02d7e2SAndroid Build Coastguard Worker __block GRPCStreamingProtoCall *call = [service 2081*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler: 2082*cc02d7e2SAndroid Build Coastguard Worker [[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil 2083*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 2084*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 2085*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 2086*cc02d7e2SAndroid Build Coastguard Worker return; 2087*cc02d7e2SAndroid Build Coastguard Worker } 2088*cc02d7e2SAndroid Build Coastguard Worker assertBlock(index < 4, @"More than 4 responses received."); 2089*cc02d7e2SAndroid Build Coastguard Worker 2090*cc02d7e2SAndroid Build Coastguard Worker index += 1; 2091*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 2092*cc02d7e2SAndroid Build Coastguard Worker id request = 2093*cc02d7e2SAndroid Build Coastguard Worker [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 2094*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 2095*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 2096*cc02d7e2SAndroid Build Coastguard Worker [localCall receiveNextMessage]; 2097*cc02d7e2SAndroid Build Coastguard Worker } else { 2098*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 2099*cc02d7e2SAndroid Build Coastguard Worker } 2100*cc02d7e2SAndroid Build Coastguard Worker } 2101*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 2102*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 2103*cc02d7e2SAndroid Build Coastguard Worker return; 2104*cc02d7e2SAndroid Build Coastguard Worker } 2105*cc02d7e2SAndroid Build Coastguard Worker assertBlock( 2106*cc02d7e2SAndroid Build Coastguard Worker error == nil, 2107*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"Finished with unexpected error: %@", error]); 2108*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 2109*cc02d7e2SAndroid Build Coastguard Worker } 2110*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:^{ 2111*cc02d7e2SAndroid Build Coastguard Worker writeMessageCount++; 2112*cc02d7e2SAndroid Build Coastguard Worker }] 2113*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 2114*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 2115*cc02d7e2SAndroid Build Coastguard Worker [call start]; 2116*cc02d7e2SAndroid Build Coastguard Worker [call receiveNextMessage]; 2117*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 2118*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 2119*cc02d7e2SAndroid Build Coastguard Worker 2120*cc02d7e2SAndroid Build Coastguard Worker assertBlock(startCount == 1, [NSString stringWithFormat:@"%@", @(startCount)]); 2121*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeDataCount == 4, [NSString stringWithFormat:@"%@", @(writeDataCount)]); 2122*cc02d7e2SAndroid Build Coastguard Worker assertBlock(finishCount == 1, [NSString stringWithFormat:@"%@", @(finishCount)]); 2123*cc02d7e2SAndroid Build Coastguard Worker assertBlock(receiveNextMessageCount == 4, 2124*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(receiveNextMessageCount)]); 2125*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseHeaderCount == 1, 2126*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(responseHeaderCount)]); 2127*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseDataCount == 4, [NSString stringWithFormat:@"%@", @(responseDataCount)]); 2128*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseCloseCount == 1, [NSString stringWithFormat:@"%@", @(responseCloseCount)]); 2129*cc02d7e2SAndroid Build Coastguard Worker assertBlock(didWriteDataCount == 4, [NSString stringWithFormat:@"%@", @(didWriteDataCount)]); 2130*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeMessageCount == 4, [NSString stringWithFormat:@"%@", @(writeMessageCount)]); 2131*cc02d7e2SAndroid Build Coastguard Worker globalInterceptorFactory.enabled = NO; 2132*cc02d7e2SAndroid Build Coastguard Worker }); 2133*cc02d7e2SAndroid Build Coastguard Worker} 2134*cc02d7e2SAndroid Build Coastguard Worker 2135*cc02d7e2SAndroid Build Coastguard Worker- (void)testConflictingGlobalInterceptors { 2136*cc02d7e2SAndroid Build Coastguard Worker id<GRPCInterceptorFactory> factory = [[HookInterceptorFactory alloc] 2137*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) 2138*cc02d7e2SAndroid Build Coastguard Worker startHook:nil 2139*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:nil 2140*cc02d7e2SAndroid Build Coastguard Worker finishHook:nil 2141*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:nil 2142*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:nil 2143*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:nil 2144*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:nil 2145*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:nil]; 2146*cc02d7e2SAndroid Build Coastguard Worker @try { 2147*cc02d7e2SAndroid Build Coastguard Worker [GRPCCall2 registerGlobalInterceptor:factory]; 2148*cc02d7e2SAndroid Build Coastguard Worker XCTFail(@"Did not receive an exception when registering global interceptor the second time"); 2149*cc02d7e2SAndroid Build Coastguard Worker } @catch (NSException *exception) { 2150*cc02d7e2SAndroid Build Coastguard Worker // Do nothing; test passes 2151*cc02d7e2SAndroid Build Coastguard Worker } 2152*cc02d7e2SAndroid Build Coastguard Worker} 2153*cc02d7e2SAndroid Build Coastguard Worker 2154*cc02d7e2SAndroid Build Coastguard Worker- (void)testInterceptorAndGlobalInterceptor { 2155*cc02d7e2SAndroid Build Coastguard Worker GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 2156*cc02d7e2SAndroid Build Coastguard Worker RMTTestService *service = [RMTTestService serviceWithHost:[[self class] host]]; 2157*cc02d7e2SAndroid Build Coastguard Worker __weak XCTestExpectation *expectation = 2158*cc02d7e2SAndroid Build Coastguard Worker [self expectationWithDescription:@"testInterceptorAndGlobalInterceptor"]; 2159*cc02d7e2SAndroid Build Coastguard Worker 2160*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger startCount = 0; 2161*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger writeDataCount = 0; 2162*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger finishCount = 0; 2163*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger receiveNextMessageCount = 0; 2164*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseHeaderCount = 0; 2165*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseDataCount = 0; 2166*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger responseCloseCount = 0; 2167*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger didWriteDataCount = 0; 2168*cc02d7e2SAndroid Build Coastguard Worker 2169*cc02d7e2SAndroid Build Coastguard Worker id<GRPCInterceptorFactory> factory = [[HookInterceptorFactory alloc] 2170*cc02d7e2SAndroid Build Coastguard Worker initWithDispatchQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) 2171*cc02d7e2SAndroid Build Coastguard Worker startHook:^(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 2172*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2173*cc02d7e2SAndroid Build Coastguard Worker startCount++; 2174*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.host, [[self class] host]); 2175*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.path, @"/grpc.testing.TestService/FullDuplexCall"); 2176*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(requestOptions.safety, GRPCCallSafetyDefault); 2177*cc02d7e2SAndroid Build Coastguard Worker [manager startNextInterceptorWithRequest:[requestOptions copy] 2178*cc02d7e2SAndroid Build Coastguard Worker callOptions:[callOptions copy]]; 2179*cc02d7e2SAndroid Build Coastguard Worker } 2180*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:^(id data, GRPCInterceptorManager *manager) { 2181*cc02d7e2SAndroid Build Coastguard Worker writeDataCount++; 2182*cc02d7e2SAndroid Build Coastguard Worker [manager writeNextInterceptorWithData:data]; 2183*cc02d7e2SAndroid Build Coastguard Worker } 2184*cc02d7e2SAndroid Build Coastguard Worker finishHook:^(GRPCInterceptorManager *manager) { 2185*cc02d7e2SAndroid Build Coastguard Worker finishCount++; 2186*cc02d7e2SAndroid Build Coastguard Worker [manager finishNextInterceptor]; 2187*cc02d7e2SAndroid Build Coastguard Worker } 2188*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:^(NSUInteger numberOfMessages, GRPCInterceptorManager *manager) { 2189*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessageCount++; 2190*cc02d7e2SAndroid Build Coastguard Worker [manager receiveNextInterceptorMessages:numberOfMessages]; 2191*cc02d7e2SAndroid Build Coastguard Worker } 2192*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:^(NSDictionary *initialMetadata, GRPCInterceptorManager *manager) { 2193*cc02d7e2SAndroid Build Coastguard Worker responseHeaderCount++; 2194*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata]; 2195*cc02d7e2SAndroid Build Coastguard Worker } 2196*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:^(id data, GRPCInterceptorManager *manager) { 2197*cc02d7e2SAndroid Build Coastguard Worker responseDataCount++; 2198*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:data]; 2199*cc02d7e2SAndroid Build Coastguard Worker } 2200*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:^(NSDictionary *trailingMetadata, NSError *error, 2201*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2202*cc02d7e2SAndroid Build Coastguard Worker responseCloseCount++; 2203*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata 2204*cc02d7e2SAndroid Build Coastguard Worker error:error]; 2205*cc02d7e2SAndroid Build Coastguard Worker } 2206*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:^(GRPCInterceptorManager *manager) { 2207*cc02d7e2SAndroid Build Coastguard Worker didWriteDataCount++; 2208*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorDidWriteData]; 2209*cc02d7e2SAndroid Build Coastguard Worker }]; 2210*cc02d7e2SAndroid Build Coastguard Worker 2211*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalStartCount = 0; 2212*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalWriteDataCount = 0; 2213*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalFinishCount = 0; 2214*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalReceiveNextMessageCount = 0; 2215*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalResponseHeaderCount = 0; 2216*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalResponseDataCount = 0; 2217*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalResponseCloseCount = 0; 2218*cc02d7e2SAndroid Build Coastguard Worker __block NSUInteger globalDidWriteDataCount = 0; 2219*cc02d7e2SAndroid Build Coastguard Worker 2220*cc02d7e2SAndroid Build Coastguard Worker [globalInterceptorFactory 2221*cc02d7e2SAndroid Build Coastguard Worker setStartHook:^(GRPCRequestOptions *requestOptions, GRPCCallOptions *callOptions, 2222*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2223*cc02d7e2SAndroid Build Coastguard Worker globalStartCount++; 2224*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.host, [[self class] host]); 2225*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqualObjects(requestOptions.path, @"/grpc.testing.TestService/FullDuplexCall"); 2226*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(requestOptions.safety, GRPCCallSafetyDefault); 2227*cc02d7e2SAndroid Build Coastguard Worker [manager startNextInterceptorWithRequest:[requestOptions copy] 2228*cc02d7e2SAndroid Build Coastguard Worker callOptions:[callOptions copy]]; 2229*cc02d7e2SAndroid Build Coastguard Worker } 2230*cc02d7e2SAndroid Build Coastguard Worker writeDataHook:^(id data, GRPCInterceptorManager *manager) { 2231*cc02d7e2SAndroid Build Coastguard Worker globalWriteDataCount++; 2232*cc02d7e2SAndroid Build Coastguard Worker [manager writeNextInterceptorWithData:data]; 2233*cc02d7e2SAndroid Build Coastguard Worker } 2234*cc02d7e2SAndroid Build Coastguard Worker finishHook:^(GRPCInterceptorManager *manager) { 2235*cc02d7e2SAndroid Build Coastguard Worker globalFinishCount++; 2236*cc02d7e2SAndroid Build Coastguard Worker [manager finishNextInterceptor]; 2237*cc02d7e2SAndroid Build Coastguard Worker } 2238*cc02d7e2SAndroid Build Coastguard Worker receiveNextMessagesHook:^(NSUInteger numberOfMessages, GRPCInterceptorManager *manager) { 2239*cc02d7e2SAndroid Build Coastguard Worker globalReceiveNextMessageCount++; 2240*cc02d7e2SAndroid Build Coastguard Worker [manager receiveNextInterceptorMessages:numberOfMessages]; 2241*cc02d7e2SAndroid Build Coastguard Worker } 2242*cc02d7e2SAndroid Build Coastguard Worker responseHeaderHook:^(NSDictionary *initialMetadata, GRPCInterceptorManager *manager) { 2243*cc02d7e2SAndroid Build Coastguard Worker globalResponseHeaderCount++; 2244*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata]; 2245*cc02d7e2SAndroid Build Coastguard Worker } 2246*cc02d7e2SAndroid Build Coastguard Worker responseDataHook:^(id data, GRPCInterceptorManager *manager) { 2247*cc02d7e2SAndroid Build Coastguard Worker globalResponseDataCount++; 2248*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorWithData:data]; 2249*cc02d7e2SAndroid Build Coastguard Worker } 2250*cc02d7e2SAndroid Build Coastguard Worker responseCloseHook:^(NSDictionary *trailingMetadata, NSError *error, 2251*cc02d7e2SAndroid Build Coastguard Worker GRPCInterceptorManager *manager) { 2252*cc02d7e2SAndroid Build Coastguard Worker globalResponseCloseCount++; 2253*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata 2254*cc02d7e2SAndroid Build Coastguard Worker error:error]; 2255*cc02d7e2SAndroid Build Coastguard Worker } 2256*cc02d7e2SAndroid Build Coastguard Worker didWriteDataHook:^(GRPCInterceptorManager *manager) { 2257*cc02d7e2SAndroid Build Coastguard Worker globalDidWriteDataCount++; 2258*cc02d7e2SAndroid Build Coastguard Worker [manager forwardPreviousInterceptorDidWriteData]; 2259*cc02d7e2SAndroid Build Coastguard Worker }]; 2260*cc02d7e2SAndroid Build Coastguard Worker 2261*cc02d7e2SAndroid Build Coastguard Worker NSArray *requests = @[ @1, @2, @3, @4 ]; 2262*cc02d7e2SAndroid Build Coastguard Worker NSArray *responses = @[ @1, @2, @3, @4 ]; 2263*cc02d7e2SAndroid Build Coastguard Worker 2264*cc02d7e2SAndroid Build Coastguard Worker __block int index = 0; 2265*cc02d7e2SAndroid Build Coastguard Worker 2266*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] 2267*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 2268*cc02d7e2SAndroid Build Coastguard Worker GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 2269*cc02d7e2SAndroid Build Coastguard Worker // For backwards compatibility 2270*cc02d7e2SAndroid Build Coastguard Worker options.transportType = [[self class] transportType]; 2271*cc02d7e2SAndroid Build Coastguard Worker options.transport = [[self class] transport]; 2272*cc02d7e2SAndroid Build Coastguard Worker options.PEMRootCertificates = [[self class] PEMRootCertificates]; 2273*cc02d7e2SAndroid Build Coastguard Worker options.hostNameOverride = [[self class] hostNameOverride]; 2274*cc02d7e2SAndroid Build Coastguard Worker options.flowControlEnabled = YES; 2275*cc02d7e2SAndroid Build Coastguard Worker options.interceptorFactories = @[ factory ]; 2276*cc02d7e2SAndroid Build Coastguard Worker globalInterceptorFactory.enabled = YES; 2277*cc02d7e2SAndroid Build Coastguard Worker 2278*cc02d7e2SAndroid Build Coastguard Worker __block int writeMessageCount = 0; 2279*cc02d7e2SAndroid Build Coastguard Worker __weak __block GRPCStreamingProtoCall *weakCall; 2280*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *call = [service 2281*cc02d7e2SAndroid Build Coastguard Worker fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] 2282*cc02d7e2SAndroid Build Coastguard Worker initWithInitialMetadataCallback:nil 2283*cc02d7e2SAndroid Build Coastguard Worker messageCallback:^(id message) { 2284*cc02d7e2SAndroid Build Coastguard Worker GRPCStreamingProtoCall *localCall = weakCall; 2285*cc02d7e2SAndroid Build Coastguard Worker if (localCall == nil) { 2286*cc02d7e2SAndroid Build Coastguard Worker return; 2287*cc02d7e2SAndroid Build Coastguard Worker } 2288*cc02d7e2SAndroid Build Coastguard Worker index += 1; 2289*cc02d7e2SAndroid Build Coastguard Worker if (index < 4) { 2290*cc02d7e2SAndroid Build Coastguard Worker id request = [RMTStreamingOutputCallRequest 2291*cc02d7e2SAndroid Build Coastguard Worker messageWithPayloadSize:requests[index] 2292*cc02d7e2SAndroid Build Coastguard Worker requestedResponseSize:responses[index]]; 2293*cc02d7e2SAndroid Build Coastguard Worker [localCall writeMessage:request]; 2294*cc02d7e2SAndroid Build Coastguard Worker [localCall receiveNextMessage]; 2295*cc02d7e2SAndroid Build Coastguard Worker } else { 2296*cc02d7e2SAndroid Build Coastguard Worker [localCall finish]; 2297*cc02d7e2SAndroid Build Coastguard Worker } 2298*cc02d7e2SAndroid Build Coastguard Worker } 2299*cc02d7e2SAndroid Build Coastguard Worker closeCallback:^(NSDictionary *trailingMetadata, 2300*cc02d7e2SAndroid Build Coastguard Worker NSError *error) { 2301*cc02d7e2SAndroid Build Coastguard Worker if (weakCall == nil) { 2302*cc02d7e2SAndroid Build Coastguard Worker return; 2303*cc02d7e2SAndroid Build Coastguard Worker } 2304*cc02d7e2SAndroid Build Coastguard Worker [expectation fulfill]; 2305*cc02d7e2SAndroid Build Coastguard Worker } 2306*cc02d7e2SAndroid Build Coastguard Worker writeMessageCallback:^{ 2307*cc02d7e2SAndroid Build Coastguard Worker writeMessageCount++; 2308*cc02d7e2SAndroid Build Coastguard Worker }] 2309*cc02d7e2SAndroid Build Coastguard Worker callOptions:options]; 2310*cc02d7e2SAndroid Build Coastguard Worker weakCall = call; 2311*cc02d7e2SAndroid Build Coastguard Worker [call start]; 2312*cc02d7e2SAndroid Build Coastguard Worker [call receiveNextMessage]; 2313*cc02d7e2SAndroid Build Coastguard Worker [call writeMessage:request]; 2314*cc02d7e2SAndroid Build Coastguard Worker 2315*cc02d7e2SAndroid Build Coastguard Worker waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 2316*cc02d7e2SAndroid Build Coastguard Worker assertBlock(startCount == 1, [NSString stringWithFormat:@"%@", @(startCount)]); 2317*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeDataCount == 4, [NSString stringWithFormat:@"%@", @(writeDataCount)]); 2318*cc02d7e2SAndroid Build Coastguard Worker assertBlock(finishCount == 1, [NSString stringWithFormat:@"%@", @(finishCount)]); 2319*cc02d7e2SAndroid Build Coastguard Worker assertBlock(receiveNextMessageCount == 4, 2320*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(receiveNextMessageCount)]); 2321*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseHeaderCount == 1, 2322*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(responseHeaderCount)]); 2323*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseDataCount == 4, [NSString stringWithFormat:@"%@", @(responseDataCount)]); 2324*cc02d7e2SAndroid Build Coastguard Worker assertBlock(responseCloseCount == 1, [NSString stringWithFormat:@"%@", @(responseCloseCount)]); 2325*cc02d7e2SAndroid Build Coastguard Worker assertBlock(didWriteDataCount == 4, [NSString stringWithFormat:@"%@", @(didWriteDataCount)]); 2326*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalStartCount == 1, [NSString stringWithFormat:@"%@", @(globalStartCount)]); 2327*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalWriteDataCount == 4, 2328*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalWriteDataCount)]); 2329*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalFinishCount == 1, [NSString stringWithFormat:@"%@", @(globalFinishCount)]); 2330*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalReceiveNextMessageCount == 4, 2331*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalReceiveNextMessageCount)]); 2332*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalResponseHeaderCount == 1, 2333*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalResponseHeaderCount)]); 2334*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalResponseDataCount == 4, 2335*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalResponseDataCount)]); 2336*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalResponseCloseCount == 1, 2337*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalResponseCloseCount)]); 2338*cc02d7e2SAndroid Build Coastguard Worker assertBlock(globalDidWriteDataCount == 4, 2339*cc02d7e2SAndroid Build Coastguard Worker [NSString stringWithFormat:@"%@", @(globalDidWriteDataCount)]); 2340*cc02d7e2SAndroid Build Coastguard Worker assertBlock(writeMessageCount == 4, [NSString stringWithFormat:@"%@", @(writeMessageCount)]); 2341*cc02d7e2SAndroid Build Coastguard Worker globalInterceptorFactory.enabled = NO; 2342*cc02d7e2SAndroid Build Coastguard Worker }); 2343*cc02d7e2SAndroid Build Coastguard Worker} 2344*cc02d7e2SAndroid Build Coastguard Worker 2345*cc02d7e2SAndroid Build Coastguard Worker@end 2346