1*cc02d7e2SAndroid Build Coastguard Worker/* 2*cc02d7e2SAndroid Build Coastguard Worker * 3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2019 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 <Cronet/Cronet.h> 20*cc02d7e2SAndroid Build Coastguard Worker#import <XCTest/XCTest.h> 21*cc02d7e2SAndroid Build Coastguard Worker 22*cc02d7e2SAndroid Build Coastguard Worker#import <grpc/grpc_cronet.h> 23*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/client_context.h> 24*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/create_channel.h> 25*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/resource_quota.h> 26*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/security/cronet_credentials.h> 27*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/server_builder.h> 28*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/server_context.h> 29*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/support/client_interceptor.h> 30*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/support/config.h> 31*cc02d7e2SAndroid Build Coastguard Worker#import "src/proto/grpc/testing/echo.grpc.pb.h" 32*cc02d7e2SAndroid Build Coastguard Worker 33*cc02d7e2SAndroid Build Coastguard Worker#import "TestHelper.h" 34*cc02d7e2SAndroid Build Coastguard Worker#import "test/core/end2end/data/ssl_test_data.h" 35*cc02d7e2SAndroid Build Coastguard Worker 36*cc02d7e2SAndroid Build Coastguard Worker#import <map> 37*cc02d7e2SAndroid Build Coastguard Worker#import <sstream> 38*cc02d7e2SAndroid Build Coastguard Worker#import <thread> 39*cc02d7e2SAndroid Build Coastguard Worker#import <vector> 40*cc02d7e2SAndroid Build Coastguard Worker 41*cc02d7e2SAndroid Build Coastguard Workerusing namespace grpc::testing; 42*cc02d7e2SAndroid Build Coastguard Workerusing grpc::ClientContext; 43*cc02d7e2SAndroid Build Coastguard Workerusing grpc::ServerContext; 44*cc02d7e2SAndroid Build Coastguard Workerusing grpc::Status; 45*cc02d7e2SAndroid Build Coastguard Workerusing std::chrono::system_clock; 46*cc02d7e2SAndroid Build Coastguard Worker 47*cc02d7e2SAndroid Build Coastguard Worker@interface CppCronetEnd2EndTests : XCTestCase 48*cc02d7e2SAndroid Build Coastguard Worker 49*cc02d7e2SAndroid Build Coastguard Worker@end 50*cc02d7e2SAndroid Build Coastguard Worker 51*cc02d7e2SAndroid Build Coastguard Worker@implementation CppCronetEnd2EndTests { 52*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<grpc::Server> _server; 53*cc02d7e2SAndroid Build Coastguard Worker TestServiceImpl _service; 54*cc02d7e2SAndroid Build Coastguard Worker TestServiceImpl _foo_service; 55*cc02d7e2SAndroid Build Coastguard Worker} 56*cc02d7e2SAndroid Build Coastguard Worker 57*cc02d7e2SAndroid Build Coastguard Worker// The setUp() function is run before the test cases run and only run once 58*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp { 59*cc02d7e2SAndroid Build Coastguard Worker [super setUp]; 60*cc02d7e2SAndroid Build Coastguard Worker configureCronet(); 61*cc02d7e2SAndroid Build Coastguard Worker} 62*cc02d7e2SAndroid Build Coastguard Worker 63*cc02d7e2SAndroid Build Coastguard Worker- (void)startServer { 64*cc02d7e2SAndroid Build Coastguard Worker if (_server) { 65*cc02d7e2SAndroid Build Coastguard Worker // server is already running 66*cc02d7e2SAndroid Build Coastguard Worker return; 67*cc02d7e2SAndroid Build Coastguard Worker } 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Worker grpc::ServerBuilder builder; 70*cc02d7e2SAndroid Build Coastguard Worker grpc::SslServerCredentialsOptions ssl_opts; 71*cc02d7e2SAndroid Build Coastguard Worker 72*cc02d7e2SAndroid Build Coastguard Worker ssl_opts.pem_root_certs = ""; 73*cc02d7e2SAndroid Build Coastguard Worker grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, test_server1_cert}; 74*cc02d7e2SAndroid Build Coastguard Worker ssl_opts.pem_key_cert_pairs.push_back(pkcp); 75*cc02d7e2SAndroid Build Coastguard Worker auto server_creds = SslServerCredentials(ssl_opts); 76*cc02d7e2SAndroid Build Coastguard Worker builder.AddListeningPort("localhost:5000", server_creds); 77*cc02d7e2SAndroid Build Coastguard Worker builder.RegisterService(&_service); 78*cc02d7e2SAndroid Build Coastguard Worker builder.RegisterService("foo.test.youtube.com", &_foo_service); 79*cc02d7e2SAndroid Build Coastguard Worker _server = builder.BuildAndStart(); 80*cc02d7e2SAndroid Build Coastguard Worker} 81*cc02d7e2SAndroid Build Coastguard Worker 82*cc02d7e2SAndroid Build Coastguard Worker- (void)stopServer { 83*cc02d7e2SAndroid Build Coastguard Worker _server.reset(); 84*cc02d7e2SAndroid Build Coastguard Worker} 85*cc02d7e2SAndroid Build Coastguard Worker 86*cc02d7e2SAndroid Build Coastguard Worker- (void)restartServer { 87*cc02d7e2SAndroid Build Coastguard Worker [self stopServer]; 88*cc02d7e2SAndroid Build Coastguard Worker [self startServer]; 89*cc02d7e2SAndroid Build Coastguard Worker} 90*cc02d7e2SAndroid Build Coastguard Worker 91*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 92*cc02d7e2SAndroid Build Coastguard Worker [self startServer]; 93*cc02d7e2SAndroid Build Coastguard Worker} 94*cc02d7e2SAndroid Build Coastguard Worker 95*cc02d7e2SAndroid Build Coastguard Worker- (void)sendRPCWithStub:(EchoTestService::Stub*)stub 96*cc02d7e2SAndroid Build Coastguard Worker numRPCs:(int)num_rpcs 97*cc02d7e2SAndroid Build Coastguard Worker withBinaryMetadata:(BOOL)with_binary_metadata { 98*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 99*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 100*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello hello hello hello"); 101*cc02d7e2SAndroid Build Coastguard Worker 102*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < num_rpcs; ++i) { 103*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 104*cc02d7e2SAndroid Build Coastguard Worker if (with_binary_metadata) { 105*cc02d7e2SAndroid Build Coastguard Worker char bytes[8] = {'\0', '\1', '\2', '\3', '\4', '\5', '\6', static_cast<char>(i)}; 106*cc02d7e2SAndroid Build Coastguard Worker context.AddMetadata("custom-bin", std::string(bytes, 8)); 107*cc02d7e2SAndroid Build Coastguard Worker } 108*cc02d7e2SAndroid Build Coastguard Worker context.set_compression_algorithm(GRPC_COMPRESS_GZIP); 109*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 110*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 111*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 112*cc02d7e2SAndroid Build Coastguard Worker } 113*cc02d7e2SAndroid Build Coastguard Worker} 114*cc02d7e2SAndroid Build Coastguard Worker 115*cc02d7e2SAndroid Build Coastguard Worker- (std::shared_ptr<::grpc::Channel>)getChannel { 116*cc02d7e2SAndroid Build Coastguard Worker stream_engine* cronetEngine = [Cronet getGlobalEngine]; 117*cc02d7e2SAndroid Build Coastguard Worker auto cronetChannelCredentials = grpc::CronetChannelCredentials(cronetEngine); 118*cc02d7e2SAndroid Build Coastguard Worker grpc::ChannelArguments args; 119*cc02d7e2SAndroid Build Coastguard Worker args.SetSslTargetNameOverride("foo.test.google.fr"); 120*cc02d7e2SAndroid Build Coastguard Worker args.SetUserAgentPrefix("custom_prefix"); 121*cc02d7e2SAndroid Build Coastguard Worker args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); 122*cc02d7e2SAndroid Build Coastguard Worker auto channel = grpc::CreateCustomChannel("127.0.0.1:5000", cronetChannelCredentials, args); 123*cc02d7e2SAndroid Build Coastguard Worker return channel; 124*cc02d7e2SAndroid Build Coastguard Worker} 125*cc02d7e2SAndroid Build Coastguard Worker 126*cc02d7e2SAndroid Build Coastguard Worker- (std::shared_ptr<::grpc::Channel>)getChannelWithInterceptors: 127*cc02d7e2SAndroid Build Coastguard Worker (std::vector<std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>)creators { 128*cc02d7e2SAndroid Build Coastguard Worker stream_engine* cronetEngine = [Cronet getGlobalEngine]; 129*cc02d7e2SAndroid Build Coastguard Worker auto cronetChannelCredentials = grpc::CronetChannelCredentials(cronetEngine); 130*cc02d7e2SAndroid Build Coastguard Worker grpc::ChannelArguments args; 131*cc02d7e2SAndroid Build Coastguard Worker args.SetSslTargetNameOverride("foo.test.google.fr"); 132*cc02d7e2SAndroid Build Coastguard Worker args.SetUserAgentPrefix("custom_prefix"); 133*cc02d7e2SAndroid Build Coastguard Worker args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); 134*cc02d7e2SAndroid Build Coastguard Worker auto channel = grpc::experimental::CreateCustomChannelWithInterceptors( 135*cc02d7e2SAndroid Build Coastguard Worker "127.0.01:5000", cronetChannelCredentials, args, std::move(creators)); 136*cc02d7e2SAndroid Build Coastguard Worker return channel; 137*cc02d7e2SAndroid Build Coastguard Worker} 138*cc02d7e2SAndroid Build Coastguard Worker 139*cc02d7e2SAndroid Build Coastguard Worker- (std::unique_ptr<EchoTestService::Stub>)getStub { 140*cc02d7e2SAndroid Build Coastguard Worker auto channel = [self getChannel]; 141*cc02d7e2SAndroid Build Coastguard Worker auto stub = EchoTestService::NewStub(channel); 142*cc02d7e2SAndroid Build Coastguard Worker return stub; 143*cc02d7e2SAndroid Build Coastguard Worker} 144*cc02d7e2SAndroid Build Coastguard Worker 145*cc02d7e2SAndroid Build Coastguard Worker- (void)testUserAgent { 146*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 147*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 148*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 149*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 150*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_echo_metadata(true); 151*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 152*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 153*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 154*cc02d7e2SAndroid Build Coastguard Worker const auto& trailing_metadata = context.GetServerTrailingMetadata(); 155*cc02d7e2SAndroid Build Coastguard Worker auto iter = trailing_metadata.find("user-agent"); 156*cc02d7e2SAndroid Build Coastguard Worker XCTAssert(iter->second.starts_with("custom_prefix grpc-c++")); 157*cc02d7e2SAndroid Build Coastguard Worker} 158*cc02d7e2SAndroid Build Coastguard Worker 159*cc02d7e2SAndroid Build Coastguard Worker- (void)testMultipleRPCs { 160*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 161*cc02d7e2SAndroid Build Coastguard Worker std::vector<std::thread> threads; 162*cc02d7e2SAndroid Build Coastguard Worker threads.reserve(10); 163*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 164*cc02d7e2SAndroid Build Coastguard Worker threads.emplace_back( 165*cc02d7e2SAndroid Build Coastguard Worker [self, &stub]() { [self sendRPCWithStub:stub.get() numRPCs:10 withBinaryMetadata:NO]; }); 166*cc02d7e2SAndroid Build Coastguard Worker } 167*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 168*cc02d7e2SAndroid Build Coastguard Worker threads[i].join(); 169*cc02d7e2SAndroid Build Coastguard Worker } 170*cc02d7e2SAndroid Build Coastguard Worker} 171*cc02d7e2SAndroid Build Coastguard Worker 172*cc02d7e2SAndroid Build Coastguard Worker- (void)testMultipleRPCsWithBinaryMetadata { 173*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 174*cc02d7e2SAndroid Build Coastguard Worker std::vector<std::thread> threads; 175*cc02d7e2SAndroid Build Coastguard Worker threads.reserve(10); 176*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 177*cc02d7e2SAndroid Build Coastguard Worker threads.emplace_back( 178*cc02d7e2SAndroid Build Coastguard Worker [self, &stub]() { [self sendRPCWithStub:stub.get() numRPCs:10 withBinaryMetadata:YES]; }); 179*cc02d7e2SAndroid Build Coastguard Worker } 180*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 181*cc02d7e2SAndroid Build Coastguard Worker threads[i].join(); 182*cc02d7e2SAndroid Build Coastguard Worker } 183*cc02d7e2SAndroid Build Coastguard Worker} 184*cc02d7e2SAndroid Build Coastguard Worker 185*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyBinaryMetadata { 186*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 187*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 188*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello hello hello hello"); 189*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 190*cc02d7e2SAndroid Build Coastguard Worker context.AddMetadata("custom-bin", ""); 191*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 192*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 193*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 194*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 195*cc02d7e2SAndroid Build Coastguard Worker} 196*cc02d7e2SAndroid Build Coastguard Worker 197*cc02d7e2SAndroid Build Coastguard Worker- (void)testReconnectChannel { 198*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 199*cc02d7e2SAndroid Build Coastguard Worker [self sendRPCWithStub:stub.get() numRPCs:1 withBinaryMetadata:NO]; 200*cc02d7e2SAndroid Build Coastguard Worker 201*cc02d7e2SAndroid Build Coastguard Worker [self restartServer]; 202*cc02d7e2SAndroid Build Coastguard Worker [self sendRPCWithStub:stub.get() numRPCs:1 withBinaryMetadata:NO]; 203*cc02d7e2SAndroid Build Coastguard Worker} 204*cc02d7e2SAndroid Build Coastguard Worker 205*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamOneRequest { 206*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 207*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 208*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 209*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 210*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->RequestStream(&context, &response); 211*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 212*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 213*cc02d7e2SAndroid Build Coastguard Worker stream->WritesDone(); 214*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 215*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 216*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 217*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().empty()); 218*cc02d7e2SAndroid Build Coastguard Worker} 219*cc02d7e2SAndroid Build Coastguard Worker 220*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamOneRequestWithCoalescingApi { 221*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 222*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 223*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 224*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 225*cc02d7e2SAndroid Build Coastguard Worker context.set_initial_metadata_corked(true); 226*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->RequestStream(&context, &response); 227*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 228*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 229*cc02d7e2SAndroid Build Coastguard Worker stream->WritesDone(); 230*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 231*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 232*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 233*cc02d7e2SAndroid Build Coastguard Worker} 234*cc02d7e2SAndroid Build Coastguard Worker 235*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamTwoRequests { 236*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 237*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 238*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 239*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 240*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->RequestStream(&context, &response); 241*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 242*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 243*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 244*cc02d7e2SAndroid Build Coastguard Worker stream->WritesDone(); 245*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 246*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), "hellohello"); 247*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 248*cc02d7e2SAndroid Build Coastguard Worker} 249*cc02d7e2SAndroid Build Coastguard Worker 250*cc02d7e2SAndroid Build Coastguard Worker- (void)testResponseStream { 251*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 252*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 253*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 254*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 255*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 256*cc02d7e2SAndroid Build Coastguard Worker 257*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->ResponseStream(&context, request); 258*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { 259*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 260*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message() + std::to_string(i)); 261*cc02d7e2SAndroid Build Coastguard Worker } 262*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 263*cc02d7e2SAndroid Build Coastguard Worker 264*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 265*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 266*cc02d7e2SAndroid Build Coastguard Worker} 267*cc02d7e2SAndroid Build Coastguard Worker 268*cc02d7e2SAndroid Build Coastguard Worker- (void)testBidiStream { 269*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 270*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 271*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 272*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 273*cc02d7e2SAndroid Build Coastguard Worker std::string msg("hello"); 274*cc02d7e2SAndroid Build Coastguard Worker 275*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->BidiStream(&context); 276*cc02d7e2SAndroid Build Coastguard Worker 277*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) { 278*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + std::to_string(i)); 279*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 280*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 281*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 282*cc02d7e2SAndroid Build Coastguard Worker } 283*cc02d7e2SAndroid Build Coastguard Worker 284*cc02d7e2SAndroid Build Coastguard Worker stream->WritesDone(); 285*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 286*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 287*cc02d7e2SAndroid Build Coastguard Worker 288*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 289*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 290*cc02d7e2SAndroid Build Coastguard Worker} 291*cc02d7e2SAndroid Build Coastguard Worker 292*cc02d7e2SAndroid Build Coastguard Worker- (void)testBidiStreamWithCoalescingApi { 293*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 294*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 295*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 296*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 297*cc02d7e2SAndroid Build Coastguard Worker context.AddMetadata(kServerFinishAfterNReads, "3"); 298*cc02d7e2SAndroid Build Coastguard Worker context.set_initial_metadata_corked(true); 299*cc02d7e2SAndroid Build Coastguard Worker std::string msg("hello"); 300*cc02d7e2SAndroid Build Coastguard Worker 301*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->BidiStream(&context); 302*cc02d7e2SAndroid Build Coastguard Worker 303*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + "0"); 304*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 305*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 306*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 307*cc02d7e2SAndroid Build Coastguard Worker 308*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + "1"); 309*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 310*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 311*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 312*cc02d7e2SAndroid Build Coastguard Worker 313*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + "2"); 314*cc02d7e2SAndroid Build Coastguard Worker stream->WriteLast(request, grpc::WriteOptions()); 315*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 316*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 317*cc02d7e2SAndroid Build Coastguard Worker 318*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 319*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 320*cc02d7e2SAndroid Build Coastguard Worker 321*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 322*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 323*cc02d7e2SAndroid Build Coastguard Worker} 324*cc02d7e2SAndroid Build Coastguard Worker 325*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelBeforeStart { 326*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 327*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 328*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 329*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 330*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 331*cc02d7e2SAndroid Build Coastguard Worker context.TryCancel(); 332*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 333*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual("", response.message()); 334*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code()); 335*cc02d7e2SAndroid Build Coastguard Worker} 336*cc02d7e2SAndroid Build Coastguard Worker 337*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientCancelsRequestStream { 338*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 339*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 340*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 341*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 342*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 343*cc02d7e2SAndroid Build Coastguard Worker 344*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->RequestStream(&context, &response); 345*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 346*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 347*cc02d7e2SAndroid Build Coastguard Worker 348*cc02d7e2SAndroid Build Coastguard Worker context.TryCancel(); 349*cc02d7e2SAndroid Build Coastguard Worker 350*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 351*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code()); 352*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), ""); 353*cc02d7e2SAndroid Build Coastguard Worker} 354*cc02d7e2SAndroid Build Coastguard Worker 355*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientCancelsResponseStream { 356*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 357*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 358*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 359*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 360*cc02d7e2SAndroid Build Coastguard Worker request.set_message("hello"); 361*cc02d7e2SAndroid Build Coastguard Worker 362*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->ResponseStream(&context, request); 363*cc02d7e2SAndroid Build Coastguard Worker 364*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 365*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message() + "0"); 366*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 367*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message() + "1"); 368*cc02d7e2SAndroid Build Coastguard Worker 369*cc02d7e2SAndroid Build Coastguard Worker context.TryCancel(); 370*cc02d7e2SAndroid Build Coastguard Worker 371*cc02d7e2SAndroid Build Coastguard Worker // The cancellation races with responses, so there might be zero or 372*cc02d7e2SAndroid Build Coastguard Worker // one responses pending, read till failure 373*cc02d7e2SAndroid Build Coastguard Worker 374*cc02d7e2SAndroid Build Coastguard Worker if (stream->Read(&response)) { 375*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message() + "2"); 376*cc02d7e2SAndroid Build Coastguard Worker // Since we have cancelled, we expect the next attempt to read to fail 377*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 378*cc02d7e2SAndroid Build Coastguard Worker } 379*cc02d7e2SAndroid Build Coastguard Worker} 380*cc02d7e2SAndroid Build Coastguard Worker 381*cc02d7e2SAndroid Build Coastguard Worker- (void)testlClientCancelsBidiStream { 382*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 383*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 384*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 385*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 386*cc02d7e2SAndroid Build Coastguard Worker std::string msg("hello"); 387*cc02d7e2SAndroid Build Coastguard Worker 388*cc02d7e2SAndroid Build Coastguard Worker auto stream = stub->BidiStream(&context); 389*cc02d7e2SAndroid Build Coastguard Worker 390*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + "0"); 391*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 392*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Read(&response)); 393*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 394*cc02d7e2SAndroid Build Coastguard Worker 395*cc02d7e2SAndroid Build Coastguard Worker request.set_message(msg + "1"); 396*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(stream->Write(request)); 397*cc02d7e2SAndroid Build Coastguard Worker 398*cc02d7e2SAndroid Build Coastguard Worker context.TryCancel(); 399*cc02d7e2SAndroid Build Coastguard Worker 400*cc02d7e2SAndroid Build Coastguard Worker // The cancellation races with responses, so there might be zero or 401*cc02d7e2SAndroid Build Coastguard Worker // one responses pending, read till failure 402*cc02d7e2SAndroid Build Coastguard Worker 403*cc02d7e2SAndroid Build Coastguard Worker if (stream->Read(&response)) { 404*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 405*cc02d7e2SAndroid Build Coastguard Worker // Since we have cancelled, we expect the next attempt to read to fail 406*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(stream->Read(&response)); 407*cc02d7e2SAndroid Build Coastguard Worker } 408*cc02d7e2SAndroid Build Coastguard Worker 409*cc02d7e2SAndroid Build Coastguard Worker Status s = stream->Finish(); 410*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code()); 411*cc02d7e2SAndroid Build Coastguard Worker} 412*cc02d7e2SAndroid Build Coastguard Worker 413*cc02d7e2SAndroid Build Coastguard Worker- (void)testNonExistingService { 414*cc02d7e2SAndroid Build Coastguard Worker auto channel = [self getChannel]; 415*cc02d7e2SAndroid Build Coastguard Worker auto stub = grpc::testing::UnimplementedEchoService::NewStub(channel); 416*cc02d7e2SAndroid Build Coastguard Worker 417*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 418*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 419*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 420*cc02d7e2SAndroid Build Coastguard Worker 421*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 422*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Unimplemented(&context, request, &response); 423*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(grpc::StatusCode::UNIMPLEMENTED, s.error_code()); 424*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual("", s.error_message()); 425*cc02d7e2SAndroid Build Coastguard Worker} 426*cc02d7e2SAndroid Build Coastguard Worker 427*cc02d7e2SAndroid Build Coastguard Worker- (void)testBinaryTrailer { 428*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 429*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 430*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 431*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 432*cc02d7e2SAndroid Build Coastguard Worker 433*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_echo_metadata(true); 434*cc02d7e2SAndroid Build Coastguard Worker DebugInfo* info = request.mutable_param()->mutable_debug_info(); 435*cc02d7e2SAndroid Build Coastguard Worker info->add_stack_entries("stack_entry_1"); 436*cc02d7e2SAndroid Build Coastguard Worker info->add_stack_entries("stack_entry_2"); 437*cc02d7e2SAndroid Build Coastguard Worker info->add_stack_entries("stack_entry_3"); 438*cc02d7e2SAndroid Build Coastguard Worker info->set_detail("detailed debug info"); 439*cc02d7e2SAndroid Build Coastguard Worker std::string expected_string = info->SerializeAsString(); 440*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 441*cc02d7e2SAndroid Build Coastguard Worker 442*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 443*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(s.ok()); 444*cc02d7e2SAndroid Build Coastguard Worker auto trailers = context.GetServerTrailingMetadata(); 445*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(1u, trailers.count(kDebugInfoTrailerKey)); 446*cc02d7e2SAndroid Build Coastguard Worker auto iter = trailers.find(kDebugInfoTrailerKey); 447*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(expected_string, iter->second); 448*cc02d7e2SAndroid Build Coastguard Worker // Parse the returned trailer into a DebugInfo proto. 449*cc02d7e2SAndroid Build Coastguard Worker DebugInfo returned_info; 450*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(returned_info.ParseFromString(ToString(iter->second))); 451*cc02d7e2SAndroid Build Coastguard Worker} 452*cc02d7e2SAndroid Build Coastguard Worker 453*cc02d7e2SAndroid Build Coastguard Worker- (void)testExpectError { 454*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 455*cc02d7e2SAndroid Build Coastguard Worker std::vector<ErrorStatus> expected_status; 456*cc02d7e2SAndroid Build Coastguard Worker expected_status.emplace_back(); 457*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_code(13); // INTERNAL 458*cc02d7e2SAndroid Build Coastguard Worker // No Error message or details 459*cc02d7e2SAndroid Build Coastguard Worker 460*cc02d7e2SAndroid Build Coastguard Worker expected_status.emplace_back(); 461*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_code(13); // INTERNAL 462*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_error_message("text error message"); 463*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_binary_error_details("text error details"); 464*cc02d7e2SAndroid Build Coastguard Worker 465*cc02d7e2SAndroid Build Coastguard Worker expected_status.emplace_back(); 466*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_code(13); // INTERNAL 467*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_error_message("text error message"); 468*cc02d7e2SAndroid Build Coastguard Worker expected_status.back().set_binary_error_details("\x0\x1\x2\x3\x4\x5\x6\x8\x9\xA\xB"); 469*cc02d7e2SAndroid Build Coastguard Worker 470*cc02d7e2SAndroid Build Coastguard Worker for (auto iter = expected_status.begin(); iter != expected_status.end(); ++iter) { 471*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 472*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 473*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 474*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 475*cc02d7e2SAndroid Build Coastguard Worker auto* error = request.mutable_param()->mutable_expected_error(); 476*cc02d7e2SAndroid Build Coastguard Worker error->set_code(iter->code()); 477*cc02d7e2SAndroid Build Coastguard Worker error->set_error_message(iter->error_message()); 478*cc02d7e2SAndroid Build Coastguard Worker error->set_binary_error_details(iter->binary_error_details()); 479*cc02d7e2SAndroid Build Coastguard Worker 480*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 481*cc02d7e2SAndroid Build Coastguard Worker XCTAssertFalse(s.ok()); 482*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(iter->code(), s.error_code()); 483*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(iter->error_message(), s.error_message()); 484*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(iter->binary_error_details(), s.error_details()); 485*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().find("created") != std::string::npos); 486*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().find("file") != std::string::npos); 487*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().find("line") != std::string::npos); 488*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().find("status") != std::string::npos); 489*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(context.debug_error_string().find("13") != std::string::npos); 490*cc02d7e2SAndroid Build Coastguard Worker } 491*cc02d7e2SAndroid Build Coastguard Worker} 492*cc02d7e2SAndroid Build Coastguard Worker 493*cc02d7e2SAndroid Build Coastguard Worker- (void)testRpcDeadlineExpires { 494*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 495*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 496*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 497*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 498*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_skip_cancelled_check(true); 499*cc02d7e2SAndroid Build Coastguard Worker // Let server sleep for 40 ms first to guarantee expiry. 500*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_server_sleep_us(40 * 1000); 501*cc02d7e2SAndroid Build Coastguard Worker 502*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 503*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::time_point deadline = 504*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::now() + std::chrono::milliseconds(1); 505*cc02d7e2SAndroid Build Coastguard Worker context.set_deadline(deadline); 506*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 507*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(grpc::StatusCode::DEADLINE_EXCEEDED, s.error_code()); 508*cc02d7e2SAndroid Build Coastguard Worker} 509*cc02d7e2SAndroid Build Coastguard Worker 510*cc02d7e2SAndroid Build Coastguard Worker- (void)testRpcLongDeadline { 511*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 512*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 513*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 514*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 515*cc02d7e2SAndroid Build Coastguard Worker 516*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 517*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::time_point deadline = 518*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::now() + std::chrono::hours(1); 519*cc02d7e2SAndroid Build Coastguard Worker context.set_deadline(deadline); 520*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 521*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 522*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 523*cc02d7e2SAndroid Build Coastguard Worker} 524*cc02d7e2SAndroid Build Coastguard Worker 525*cc02d7e2SAndroid Build Coastguard Worker- (void)testEchoDeadlineForNoDeadlineRpc { 526*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 527*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 528*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 529*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 530*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_echo_deadline(true); 531*cc02d7e2SAndroid Build Coastguard Worker 532*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 533*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 534*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 535*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 536*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.param().request_deadline(), gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec); 537*cc02d7e2SAndroid Build Coastguard Worker} 538*cc02d7e2SAndroid Build Coastguard Worker 539*cc02d7e2SAndroid Build Coastguard Worker- (void)testEchoDeadline { 540*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 541*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 542*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 543*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 544*cc02d7e2SAndroid Build Coastguard Worker request.mutable_param()->set_echo_deadline(true); 545*cc02d7e2SAndroid Build Coastguard Worker 546*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 547*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::time_point deadline = 548*cc02d7e2SAndroid Build Coastguard Worker std::chrono::system_clock::now() + std::chrono::seconds(100); 549*cc02d7e2SAndroid Build Coastguard Worker context.set_deadline(deadline); 550*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 551*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(response.message(), request.message()); 552*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 553*cc02d7e2SAndroid Build Coastguard Worker gpr_timespec sent_deadline; 554*cc02d7e2SAndroid Build Coastguard Worker grpc::Timepoint2Timespec(deadline, &sent_deadline); 555*cc02d7e2SAndroid Build Coastguard Worker // We want to allow some reasonable error given: 556*cc02d7e2SAndroid Build Coastguard Worker // - request_deadline() only has 1sec resolution so the best we can do is +-1 557*cc02d7e2SAndroid Build Coastguard Worker // - if sent_deadline.tv_nsec is very close to the next second's boundary we 558*cc02d7e2SAndroid Build Coastguard Worker // can end up being off by 2 in one direction. 559*cc02d7e2SAndroid Build Coastguard Worker XCTAssertLessThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, 2); 560*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, -1); 561*cc02d7e2SAndroid Build Coastguard Worker NSLog(@"request deadline: %d sent_deadline: %d", response.param().request_deadline(), 562*cc02d7e2SAndroid Build Coastguard Worker sent_deadline.tv_sec); 563*cc02d7e2SAndroid Build Coastguard Worker} 564*cc02d7e2SAndroid Build Coastguard Worker 565*cc02d7e2SAndroid Build Coastguard Worker- (void)testPeer { 566*cc02d7e2SAndroid Build Coastguard Worker auto stub = [self getStub]; 567*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 568*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 569*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 570*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 571*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 572*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 573*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(CheckIsLocalhost(context.peer())); 574*cc02d7e2SAndroid Build Coastguard Worker} 575*cc02d7e2SAndroid Build Coastguard Worker 576*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientInterceptor { 577*cc02d7e2SAndroid Build Coastguard Worker PhonyInterceptor::Reset(); 578*cc02d7e2SAndroid Build Coastguard Worker std::vector<std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>> creators; 579*cc02d7e2SAndroid Build Coastguard Worker // Add 20 phony interceptors 580*cc02d7e2SAndroid Build Coastguard Worker for (auto i = 0; i < 20; i++) { 581*cc02d7e2SAndroid Build Coastguard Worker creators.push_back(std::unique_ptr<PhonyInterceptorFactory>(new PhonyInterceptorFactory())); 582*cc02d7e2SAndroid Build Coastguard Worker } 583*cc02d7e2SAndroid Build Coastguard Worker auto channel = [self getChannelWithInterceptors:std::move(creators)]; 584*cc02d7e2SAndroid Build Coastguard Worker auto stub = EchoTestService::NewStub(channel); 585*cc02d7e2SAndroid Build Coastguard Worker 586*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 587*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 588*cc02d7e2SAndroid Build Coastguard Worker ClientContext context; 589*cc02d7e2SAndroid Build Coastguard Worker request.set_message("Hello"); 590*cc02d7e2SAndroid Build Coastguard Worker Status s = stub->Echo(&context, request, &response); 591*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(s.ok()); 592*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(PhonyInterceptor::GetNumTimesRun(), 20); 593*cc02d7e2SAndroid Build Coastguard Worker} 594*cc02d7e2SAndroid Build Coastguard Worker 595*cc02d7e2SAndroid Build Coastguard Worker@end 596