TestHelper.mm 7.3 KB

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