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 "TestHelper.h" 20*cc02d7e2SAndroid Build Coastguard Worker#import <Cronet/Cronet.h> 21*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/impl/codegen/string_ref.h> 22*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/support/config.h> 23*cc02d7e2SAndroid Build Coastguard Worker 24*cc02d7e2SAndroid Build Coastguard Workerusing grpc::ServerContext; 25*cc02d7e2SAndroid Build Coastguard Workerusing grpc::Status; 26*cc02d7e2SAndroid Build Coastguard Workerusing grpc::testing::EchoRequest; 27*cc02d7e2SAndroid Build Coastguard Workerusing grpc::testing::EchoResponse; 28*cc02d7e2SAndroid Build Coastguard Workerusing grpc::testing::EchoTestService; 29*cc02d7e2SAndroid Build Coastguard Workerusing std::chrono::system_clock; 30*cc02d7e2SAndroid Build Coastguard Worker 31*cc02d7e2SAndroid Build Coastguard Workerstd::atomic<int> PhonyInterceptor::num_times_run_; 32*cc02d7e2SAndroid Build Coastguard Workerstd::atomic<int> PhonyInterceptor::num_times_run_reverse_; 33*cc02d7e2SAndroid Build Coastguard Worker 34*cc02d7e2SAndroid Build Coastguard Workerstd::string ToString(const grpc::string_ref& r) { return std::string(r.data(), r.size()); } 35*cc02d7e2SAndroid Build Coastguard Worker 36*cc02d7e2SAndroid Build Coastguard Workervoid configureCronet(void) { 37*cc02d7e2SAndroid Build Coastguard Worker static dispatch_once_t configureCronet; 38*cc02d7e2SAndroid Build Coastguard Worker dispatch_once(&configureCronet, ^{ 39*cc02d7e2SAndroid Build Coastguard Worker [Cronet setHttp2Enabled:YES]; 40*cc02d7e2SAndroid Build Coastguard Worker [Cronet setSslKeyLogFileName:@"Documents/key"]; 41*cc02d7e2SAndroid Build Coastguard Worker [Cronet enableTestCertVerifierForTesting]; 42*cc02d7e2SAndroid Build Coastguard Worker NSURL* url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory 43*cc02d7e2SAndroid Build Coastguard Worker inDomains:NSUserDomainMask] lastObject]; 44*cc02d7e2SAndroid Build Coastguard Worker [Cronet start]; 45*cc02d7e2SAndroid Build Coastguard Worker [Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES]; 46*cc02d7e2SAndroid Build Coastguard Worker }); 47*cc02d7e2SAndroid Build Coastguard Worker} 48*cc02d7e2SAndroid Build Coastguard Worker 49*cc02d7e2SAndroid Build Coastguard Workerbool CheckIsLocalhost(const std::string& addr) { 50*cc02d7e2SAndroid Build Coastguard Worker const std::string kIpv6("[::1]:"); 51*cc02d7e2SAndroid Build Coastguard Worker const std::string kIpv4MappedIpv6("[::ffff:127.0.0.1]:"); 52*cc02d7e2SAndroid Build Coastguard Worker const std::string kIpv4("127.0.0.1:"); 53*cc02d7e2SAndroid Build Coastguard Worker return addr.substr(0, kIpv4.size()) == kIpv4 || 54*cc02d7e2SAndroid Build Coastguard Worker addr.substr(0, kIpv4MappedIpv6.size()) == kIpv4MappedIpv6 || 55*cc02d7e2SAndroid Build Coastguard Worker addr.substr(0, kIpv6.size()) == kIpv6; 56*cc02d7e2SAndroid Build Coastguard Worker} 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard Workerint GetIntValueFromMetadataHelper(const char* key, 59*cc02d7e2SAndroid Build Coastguard Worker const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, 60*cc02d7e2SAndroid Build Coastguard Worker int default_value) { 61*cc02d7e2SAndroid Build Coastguard Worker if (metadata.find(key) != metadata.end()) { 62*cc02d7e2SAndroid Build Coastguard Worker std::istringstream iss(ToString(metadata.find(key)->second)); 63*cc02d7e2SAndroid Build Coastguard Worker iss >> default_value; 64*cc02d7e2SAndroid Build Coastguard Worker } 65*cc02d7e2SAndroid Build Coastguard Worker 66*cc02d7e2SAndroid Build Coastguard Worker return default_value; 67*cc02d7e2SAndroid Build Coastguard Worker} 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Workerint GetIntValueFromMetadata(const char* key, 70*cc02d7e2SAndroid Build Coastguard Worker const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, 71*cc02d7e2SAndroid Build Coastguard Worker int default_value) { 72*cc02d7e2SAndroid Build Coastguard Worker return GetIntValueFromMetadataHelper(key, metadata, default_value); 73*cc02d7e2SAndroid Build Coastguard Worker} 74*cc02d7e2SAndroid Build Coastguard Worker 75*cc02d7e2SAndroid Build Coastguard Worker// When echo_deadline is requested, deadline seen in the ServerContext is set in 76*cc02d7e2SAndroid Build Coastguard Worker// the response in seconds. 77*cc02d7e2SAndroid Build Coastguard Workervoid MaybeEchoDeadline(ServerContext* context, const EchoRequest* request, EchoResponse* response) { 78*cc02d7e2SAndroid Build Coastguard Worker if (request->has_param() && request->param().echo_deadline()) { 79*cc02d7e2SAndroid Build Coastguard Worker gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_REALTIME); 80*cc02d7e2SAndroid Build Coastguard Worker if (context->deadline() != system_clock::time_point::max()) { 81*cc02d7e2SAndroid Build Coastguard Worker grpc::Timepoint2Timespec(context->deadline(), &deadline); 82*cc02d7e2SAndroid Build Coastguard Worker } 83*cc02d7e2SAndroid Build Coastguard Worker response->mutable_param()->set_request_deadline(deadline.tv_sec); 84*cc02d7e2SAndroid Build Coastguard Worker } 85*cc02d7e2SAndroid Build Coastguard Worker} 86*cc02d7e2SAndroid Build Coastguard Worker 87*cc02d7e2SAndroid Build Coastguard WorkerStatus TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, 88*cc02d7e2SAndroid Build Coastguard Worker EchoResponse* response) { 89*cc02d7e2SAndroid Build Coastguard Worker // A bit of sleep to make sure that short deadline tests fail 90*cc02d7e2SAndroid Build Coastguard Worker if (request->has_param() && request->param().server_sleep_us() > 0) { 91*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until( 92*cc02d7e2SAndroid Build Coastguard Worker gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), 93*cc02d7e2SAndroid Build Coastguard Worker gpr_time_from_micros(request->param().server_sleep_us(), GPR_TIMESPAN))); 94*cc02d7e2SAndroid Build Coastguard Worker } 95*cc02d7e2SAndroid Build Coastguard Worker 96*cc02d7e2SAndroid Build Coastguard Worker if (request->has_param() && request->param().has_expected_error()) { 97*cc02d7e2SAndroid Build Coastguard Worker const auto& error = request->param().expected_error(); 98*cc02d7e2SAndroid Build Coastguard Worker return Status(static_cast<grpc::StatusCode>(error.code()), error.error_message(), 99*cc02d7e2SAndroid Build Coastguard Worker error.binary_error_details()); 100*cc02d7e2SAndroid Build Coastguard Worker } 101*cc02d7e2SAndroid Build Coastguard Worker 102*cc02d7e2SAndroid Build Coastguard Worker if (request->has_param() && request->param().echo_metadata()) { 103*cc02d7e2SAndroid Build Coastguard Worker const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata = 104*cc02d7e2SAndroid Build Coastguard Worker context->client_metadata(); 105*cc02d7e2SAndroid Build Coastguard Worker for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator iter = 106*cc02d7e2SAndroid Build Coastguard Worker client_metadata.begin(); 107*cc02d7e2SAndroid Build Coastguard Worker iter != client_metadata.end(); ++iter) { 108*cc02d7e2SAndroid Build Coastguard Worker context->AddTrailingMetadata(ToString(iter->first), ToString(iter->second)); 109*cc02d7e2SAndroid Build Coastguard Worker } 110*cc02d7e2SAndroid Build Coastguard Worker // Terminate rpc with error and debug info in trailer. 111*cc02d7e2SAndroid Build Coastguard Worker if (request->param().debug_info().stack_entries_size() || 112*cc02d7e2SAndroid Build Coastguard Worker !request->param().debug_info().detail().empty()) { 113*cc02d7e2SAndroid Build Coastguard Worker std::string serialized_debug_info = request->param().debug_info().SerializeAsString(); 114*cc02d7e2SAndroid Build Coastguard Worker context->AddTrailingMetadata(kDebugInfoTrailerKey, serialized_debug_info); 115*cc02d7e2SAndroid Build Coastguard Worker return Status::CANCELLED; 116*cc02d7e2SAndroid Build Coastguard Worker } 117*cc02d7e2SAndroid Build Coastguard Worker } 118*cc02d7e2SAndroid Build Coastguard Worker 119*cc02d7e2SAndroid Build Coastguard Worker response->set_message(request->message()); 120*cc02d7e2SAndroid Build Coastguard Worker MaybeEchoDeadline(context, request, response); 121*cc02d7e2SAndroid Build Coastguard Worker return Status::OK; 122*cc02d7e2SAndroid Build Coastguard Worker} 123*cc02d7e2SAndroid Build Coastguard Worker 124*cc02d7e2SAndroid Build Coastguard WorkerStatus TestServiceImpl::RequestStream(ServerContext* context, 125*cc02d7e2SAndroid Build Coastguard Worker grpc::ServerReader<EchoRequest>* reader, 126*cc02d7e2SAndroid Build Coastguard Worker EchoResponse* response) { 127*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 128*cc02d7e2SAndroid Build Coastguard Worker response->set_message(""); 129*cc02d7e2SAndroid Build Coastguard Worker int num_msgs_read = 0; 130*cc02d7e2SAndroid Build Coastguard Worker while (reader->Read(&request)) { 131*cc02d7e2SAndroid Build Coastguard Worker response->mutable_message()->append(request.message()); 132*cc02d7e2SAndroid Build Coastguard Worker ++num_msgs_read; 133*cc02d7e2SAndroid Build Coastguard Worker } 134*cc02d7e2SAndroid Build Coastguard Worker return Status::OK; 135*cc02d7e2SAndroid Build Coastguard Worker} 136*cc02d7e2SAndroid Build Coastguard Worker 137*cc02d7e2SAndroid Build Coastguard WorkerStatus TestServiceImpl::ResponseStream(ServerContext* context, const EchoRequest* request, 138*cc02d7e2SAndroid Build Coastguard Worker grpc::ServerWriter<EchoResponse>* writer) { 139*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 140*cc02d7e2SAndroid Build Coastguard Worker int server_responses_to_send = 141*cc02d7e2SAndroid Build Coastguard Worker GetIntValueFromMetadata(kServerResponseStreamsToSend, context->client_metadata(), 142*cc02d7e2SAndroid Build Coastguard Worker kServerDefaultResponseStreamsToSend); 143*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < server_responses_to_send; i++) { 144*cc02d7e2SAndroid Build Coastguard Worker response.set_message(request->message() + std::to_string(i)); 145*cc02d7e2SAndroid Build Coastguard Worker if (i == server_responses_to_send - 1) { 146*cc02d7e2SAndroid Build Coastguard Worker writer->WriteLast(response, grpc::WriteOptions()); 147*cc02d7e2SAndroid Build Coastguard Worker } else { 148*cc02d7e2SAndroid Build Coastguard Worker writer->Write(response); 149*cc02d7e2SAndroid Build Coastguard Worker } 150*cc02d7e2SAndroid Build Coastguard Worker } 151*cc02d7e2SAndroid Build Coastguard Worker return Status::OK; 152*cc02d7e2SAndroid Build Coastguard Worker} 153*cc02d7e2SAndroid Build Coastguard Worker 154*cc02d7e2SAndroid Build Coastguard WorkerStatus TestServiceImpl::BidiStream(ServerContext* context, 155*cc02d7e2SAndroid Build Coastguard Worker grpc::ServerReaderWriter<EchoResponse, EchoRequest>* stream) { 156*cc02d7e2SAndroid Build Coastguard Worker EchoRequest request; 157*cc02d7e2SAndroid Build Coastguard Worker EchoResponse response; 158*cc02d7e2SAndroid Build Coastguard Worker 159*cc02d7e2SAndroid Build Coastguard Worker // kServerFinishAfterNReads suggests after how many reads, the server should 160*cc02d7e2SAndroid Build Coastguard Worker // write the last message and send status (coalesced using WriteLast) 161*cc02d7e2SAndroid Build Coastguard Worker int server_write_last = 162*cc02d7e2SAndroid Build Coastguard Worker GetIntValueFromMetadata(kServerFinishAfterNReads, context->client_metadata(), 0); 163*cc02d7e2SAndroid Build Coastguard Worker 164*cc02d7e2SAndroid Build Coastguard Worker int read_counts = 0; 165*cc02d7e2SAndroid Build Coastguard Worker while (stream->Read(&request)) { 166*cc02d7e2SAndroid Build Coastguard Worker read_counts++; 167*cc02d7e2SAndroid Build Coastguard Worker response.set_message(request.message()); 168*cc02d7e2SAndroid Build Coastguard Worker if (read_counts == server_write_last) { 169*cc02d7e2SAndroid Build Coastguard Worker stream->WriteLast(response, grpc::WriteOptions()); 170*cc02d7e2SAndroid Build Coastguard Worker } else { 171*cc02d7e2SAndroid Build Coastguard Worker stream->Write(response); 172*cc02d7e2SAndroid Build Coastguard Worker } 173*cc02d7e2SAndroid Build Coastguard Worker } 174*cc02d7e2SAndroid Build Coastguard Worker 175*cc02d7e2SAndroid Build Coastguard Worker return Status::OK; 176*cc02d7e2SAndroid Build Coastguard Worker} 177*cc02d7e2SAndroid Build Coastguard Worker 178*cc02d7e2SAndroid Build Coastguard Workervoid PhonyInterceptor::Intercept(grpc::experimental::InterceptorBatchMethods* methods) { 179*cc02d7e2SAndroid Build Coastguard Worker if (methods->QueryInterceptionHookPoint( 180*cc02d7e2SAndroid Build Coastguard Worker grpc::experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { 181*cc02d7e2SAndroid Build Coastguard Worker num_times_run_++; 182*cc02d7e2SAndroid Build Coastguard Worker } else if (methods->QueryInterceptionHookPoint( 183*cc02d7e2SAndroid Build Coastguard Worker grpc::experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { 184*cc02d7e2SAndroid Build Coastguard Worker num_times_run_reverse_++; 185*cc02d7e2SAndroid Build Coastguard Worker } 186*cc02d7e2SAndroid Build Coastguard Worker methods->Proceed(); 187*cc02d7e2SAndroid Build Coastguard Worker} 188*cc02d7e2SAndroid Build Coastguard Worker 189*cc02d7e2SAndroid Build Coastguard Workervoid PhonyInterceptor::Reset() { 190*cc02d7e2SAndroid Build Coastguard Worker num_times_run_.store(0); 191*cc02d7e2SAndroid Build Coastguard Worker num_times_run_reverse_.store(0); 192*cc02d7e2SAndroid Build Coastguard Worker} 193*cc02d7e2SAndroid Build Coastguard Worker 194*cc02d7e2SAndroid Build Coastguard Workerint PhonyInterceptor::GetNumTimesRun() { 195*cc02d7e2SAndroid Build Coastguard Worker NSCAssert(num_times_run_.load() == num_times_run_reverse_.load(), 196*cc02d7e2SAndroid Build Coastguard Worker @"Interceptor must run same number of times in both directions"); 197*cc02d7e2SAndroid Build Coastguard Worker return num_times_run_.load(); 198*cc02d7e2SAndroid Build Coastguard Worker} 199