1/* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19#import <GRPCClient/GRPCCall+Tests.h> 20#import <GRPCClient/GRPCCall.h> 21#import <GRPCClient/internal_testing/GRPCCall+InternalTests.h> 22#import <RxLibrary/GRXWriter+Immediate.h> 23 24#import "../Common/GRPCBlockCallbackResponseHandler.h" 25 26#import "src/objective-c/tests/RemoteTestClient/Messages.pbobjc.h" 27#import "src/objective-c/tests/RemoteTestClient/Test.pbobjc.h" 28#import "src/objective-c/tests/RemoteTestClient/Test.pbrpc.h" 29 30#import "../Common/TestUtils.h" 31#import "InteropTests.h" 32 33// Package and service name of test server 34static NSString *const kPackage = @"grpc.testing"; 35static NSString *const kService = @"TestService"; 36 37// The Protocol Buffers encoding overhead of remote interop server. Acquired 38// by experiment. Adjust this when server's proto file changes. 39static int32_t kRemoteInteropServerOverhead = 12; 40 41static GRPCProtoMethod *kUnaryCallMethod; 42 43/** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ 44@interface InteropTestsRemote : InteropTests 45@end 46 47@implementation InteropTestsRemote 48 49#pragma mark - InteropTests 50 51+ (NSString *)host { 52 return GRPCGetRemoteInteropTestServerAddress(); 53} 54 55+ (NSString *)PEMRootCertificates { 56 return nil; 57} 58 59+ (NSString *)hostNameOverride { 60 return nil; 61} 62 63- (int32_t)encodingOverhead { 64 return kRemoteInteropServerOverhead; // bytes 65} 66 67+ (GRPCTransportType)transportType { 68 return GRPCTransportTypeChttp2BoringSSL; 69} 70 71+ (BOOL)isRemoteTest { 72 return YES; 73} 74 75#pragma mark - InteropTestsRemote tests 76 77- (void)setUp { 78 [super setUp]; 79 80 kUnaryCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage 81 service:kService 82 method:@"UnaryCall"]; 83} 84 85- (void)testMetadataForV2Call { 86 GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 87 XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; 88 89 RMTSimpleRequest *request = [RMTSimpleRequest message]; 90 request.fillUsername = YES; 91 request.fillOauthScope = YES; 92 93 GRPCRequestOptions *callRequest = 94 [[GRPCRequestOptions alloc] initWithHost:[[self class] host] 95 path:kUnaryCallMethod.HTTPPath 96 safety:GRPCCallSafetyDefault]; 97 __block NSDictionary *init_md; 98 __block NSDictionary *trailing_md; 99 GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; 100 options.oauth2AccessToken = @"bogusToken"; 101 102 GRPCCall2 *call = [[GRPCCall2 alloc] 103 initWithRequestOptions:callRequest 104 responseHandler:[[GRPCBlockCallbackResponseHandler alloc] 105 initWithInitialMetadataCallback:^( 106 NSDictionary *initialMetadata) { 107 init_md = initialMetadata; 108 } 109 messageCallback:^(id message) { 110 XCTFail(@"Received unexpected response."); 111 } 112 closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { 113 trailing_md = trailingMetadata; 114 if (error) { 115 XCTAssertEqual(error.code, 16, 116 @"Finished with unexpected error: %@", error); 117 XCTAssertEqualObjects(init_md, 118 error.userInfo[kGRPCHeadersKey]); 119 XCTAssertEqualObjects(trailing_md, 120 error.userInfo[kGRPCTrailersKey]); 121 NSString *challengeHeader = init_md[@"www-authenticate"]; 122 XCTAssertGreaterThan(challengeHeader.length, 0, 123 @"No challenge in response headers %@", 124 init_md); 125 [expectation fulfill]; 126 } 127 }] 128 callOptions:options]; 129 130 [call start]; 131 [call writeData:[request data]]; 132 [call finish]; 133 134 waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 135 }); 136} 137 138- (void)testMetadataForV1Call { 139 GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 140 XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; 141 142 RMTSimpleRequest *request = [RMTSimpleRequest message]; 143 request.fillUsername = YES; 144 request.fillOauthScope = YES; 145 GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; 146 147 GRPCCall *call = [[GRPCCall alloc] initWithHost:GRPCGetRemoteInteropTestServerAddress() 148 path:kUnaryCallMethod.HTTPPath 149 requestsWriter:requestsWriter]; 150 GRPCCall *weakCall = call; 151 152 call.oauth2AccessToken = @"bogusToken"; 153 154 id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] 155 initWithValueHandler:^(NSData *value) { 156 if (weakCall == nil) { 157 return; 158 } 159 XCTFail(@"Received unexpected response: %@", value); 160 } 161 completionHandler:^(NSError *errorOrNil) { 162 GRPCCall *localCall = weakCall; 163 if (localCall == nil) { 164 return; 165 } 166 167 XCTAssertNotNil(errorOrNil, @"Finished without error!"); 168 XCTAssertEqual(errorOrNil.code, 16, @"Finished with unexpected error: %@", errorOrNil); 169 XCTAssertEqualObjects(localCall.responseHeaders, errorOrNil.userInfo[kGRPCHeadersKey], 170 @"Headers in the NSError object and call object differ."); 171 XCTAssertEqualObjects(localCall.responseTrailers, errorOrNil.userInfo[kGRPCTrailersKey], 172 @"Trailers in the NSError object and call object differ."); 173 NSString *challengeHeader = localCall.oauth2ChallengeHeader; 174 XCTAssertGreaterThan(challengeHeader.length, 0, @"No challenge in response headers %@", 175 localCall.responseHeaders); 176 [expectation fulfill]; 177 }]; 178 179 [call startWithWriteable:responsesWriteable]; 180 181 waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 182 }); 183} 184 185- (void)testErrorDebugInformation { 186 GRPCTestRunWithFlakeRepeats(self, ^(GRPCTestWaiter waiterBlock, GRPCTestAssert assertBlock) { 187 XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; 188 189 RMTSimpleRequest *request = [RMTSimpleRequest message]; 190 request.fillUsername = YES; 191 request.fillOauthScope = YES; 192 GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; 193 194 GRPCCall *call = [[GRPCCall alloc] initWithHost:GRPCGetRemoteInteropTestServerAddress() 195 path:kUnaryCallMethod.HTTPPath 196 requestsWriter:requestsWriter]; 197 GRPCCall *weakCall = call; 198 199 call.oauth2AccessToken = @"bogusToken"; 200 201 id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] 202 initWithValueHandler:^(NSData *value) { 203 if (weakCall == nil) { 204 return; 205 } 206 XCTFail(@"Received unexpected response: %@", value); 207 } 208 completionHandler:^(NSError *errorOrNil) { 209 GRPCCall *localCall = weakCall; 210 if (localCall == nil) { 211 return; 212 } 213 XCTAssertNotNil(errorOrNil, @"Finished without error!"); 214 NSDictionary *userInfo = errorOrNil.userInfo; 215 NSString *debugInformation = userInfo[NSDebugDescriptionErrorKey]; 216 XCTAssertNotNil(debugInformation); 217 XCTAssertNotEqual([debugInformation length], 0); 218 NSString *challengeHeader = localCall.oauth2ChallengeHeader; 219 XCTAssertGreaterThan(challengeHeader.length, 0, @"No challenge in response headers %@", 220 localCall.responseHeaders); 221 [expectation fulfill]; 222 }]; 223 224 [call startWithWriteable:responsesWriteable]; 225 226 waiterBlock(@[ expectation ], GRPCInteropTestTimeoutDefault); 227 }); 228} 229 230@end 231