interop_client.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #include "test/cpp/interop/interop_client.h"
  34. #include <fstream>
  35. #include <memory>
  36. #include <unistd.h>
  37. #include <grpc/grpc.h>
  38. #include <grpc/support/log.h>
  39. #include <grpc/support/string_util.h>
  40. #include <grpc++/channel_interface.h>
  41. #include <grpc++/client_context.h>
  42. #include <grpc++/credentials.h>
  43. #include <grpc++/status.h>
  44. #include <grpc++/stream.h>
  45. #include "test/cpp/interop/client_helper.h"
  46. #include "test/proto/test.grpc.pb.h"
  47. #include "test/proto/empty.grpc.pb.h"
  48. #include "test/proto/messages.grpc.pb.h"
  49. #include "src/core/transport/stream_op.h"
  50. namespace grpc {
  51. namespace testing {
  52. static const char* kRandomFile = "test/cpp/interop/rnd.dat";
  53. namespace {
  54. // The same value is defined by the Java client.
  55. const std::vector<int> request_stream_sizes = {27182, 8, 1828, 45904};
  56. const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979};
  57. const int kNumResponseMessages = 2000;
  58. const int kResponseMessageSize = 1030;
  59. const int kReceiveDelayMilliSeconds = 20;
  60. const int kLargeRequestSize = 271828;
  61. const int kLargeResponseSize = 314159;
  62. } // namespace
  63. InteropClient::InteropClient(std::shared_ptr<ChannelInterface> channel)
  64. : channel_(channel) {}
  65. void InteropClient::AssertOkOrPrintErrorStatus(const Status& s) {
  66. if (s.ok()) {
  67. return;
  68. }
  69. gpr_log(GPR_INFO, "Error status code: %d, message: %s", s.error_code(),
  70. s.error_message().c_str());
  71. GPR_ASSERT(0);
  72. }
  73. void InteropClient::DoEmpty() {
  74. gpr_log(GPR_INFO, "Sending an empty rpc...");
  75. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  76. Empty request = Empty::default_instance();
  77. Empty response = Empty::default_instance();
  78. ClientContext context;
  79. Status s = stub->EmptyCall(&context, request, &response);
  80. AssertOkOrPrintErrorStatus(s);
  81. gpr_log(GPR_INFO, "Empty rpc done.");
  82. }
  83. // Shared code to set large payload, make rpc and check response payload.
  84. void InteropClient::PerformLargeUnary(SimpleRequest* request,
  85. SimpleResponse* response) {
  86. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  87. ClientContext context;
  88. InteropClientContextInspector inspector(context);
  89. request->set_response_size(kLargeResponseSize);
  90. grpc::string payload(kLargeRequestSize, '\0');
  91. request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
  92. Status s = stub->UnaryCall(&context, *request, response);
  93. // Compression related checks.
  94. GPR_ASSERT(request->response_compression() ==
  95. GetInteropCompressionTypeFromCompressionAlgorithm(
  96. inspector.GetCallCompressionAlgorithm()));
  97. if (request->response_compression() == NONE) {
  98. GPR_ASSERT(!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
  99. } else if (request->response_type() == PayloadType::COMPRESSABLE) {
  100. // requested compression and compressable response => results should always
  101. // be compressed.
  102. GPR_ASSERT(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS);
  103. }
  104. AssertOkOrPrintErrorStatus(s);
  105. // Payload related checks.
  106. if (request->response_type() != PayloadType::RANDOM) {
  107. GPR_ASSERT(response->payload().type() == request->response_type());
  108. }
  109. switch (response->payload().type()) {
  110. case PayloadType::COMPRESSABLE:
  111. GPR_ASSERT(response->payload().body() ==
  112. grpc::string(kLargeResponseSize, '\0'));
  113. break;
  114. case PayloadType::UNCOMPRESSABLE: {
  115. std::ifstream rnd_file(kRandomFile);
  116. GPR_ASSERT(rnd_file.good());
  117. for (int i = 0; i < kLargeResponseSize; i++) {
  118. GPR_ASSERT(response->payload().body()[i] == (char)rnd_file.get());
  119. }
  120. }
  121. break;
  122. default:
  123. GPR_ASSERT(false);
  124. }
  125. }
  126. void InteropClient::DoComputeEngineCreds(
  127. const grpc::string& default_service_account,
  128. const grpc::string& oauth_scope) {
  129. gpr_log(GPR_INFO,
  130. "Sending a large unary rpc with compute engine credentials ...");
  131. SimpleRequest request;
  132. SimpleResponse response;
  133. request.set_fill_username(true);
  134. request.set_fill_oauth_scope(true);
  135. request.set_response_type(PayloadType::COMPRESSABLE);
  136. PerformLargeUnary(&request, &response);
  137. gpr_log(GPR_INFO, "Got username %s", response.username().c_str());
  138. gpr_log(GPR_INFO, "Got oauth_scope %s", response.oauth_scope().c_str());
  139. GPR_ASSERT(!response.username().empty());
  140. GPR_ASSERT(response.username().c_str() == default_service_account);
  141. GPR_ASSERT(!response.oauth_scope().empty());
  142. const char* oauth_scope_str = response.oauth_scope().c_str();
  143. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  144. gpr_log(GPR_INFO, "Large unary with compute engine creds done.");
  145. }
  146. void InteropClient::DoServiceAccountCreds(const grpc::string& username,
  147. const grpc::string& oauth_scope) {
  148. gpr_log(GPR_INFO,
  149. "Sending a large unary rpc with service account credentials ...");
  150. SimpleRequest request;
  151. SimpleResponse response;
  152. request.set_fill_username(true);
  153. request.set_fill_oauth_scope(true);
  154. request.set_response_type(PayloadType::COMPRESSABLE);
  155. PerformLargeUnary(&request, &response);
  156. GPR_ASSERT(!response.username().empty());
  157. GPR_ASSERT(!response.oauth_scope().empty());
  158. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  159. const char* oauth_scope_str = response.oauth_scope().c_str();
  160. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  161. gpr_log(GPR_INFO, "Large unary with service account creds done.");
  162. }
  163. void InteropClient::DoOauth2AuthToken(const grpc::string& username,
  164. const grpc::string& oauth_scope) {
  165. gpr_log(GPR_INFO,
  166. "Sending a unary rpc with raw oauth2 access token credentials ...");
  167. SimpleRequest request;
  168. SimpleResponse response;
  169. request.set_fill_username(true);
  170. request.set_fill_oauth_scope(true);
  171. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  172. ClientContext context;
  173. Status s = stub->UnaryCall(&context, request, &response);
  174. AssertOkOrPrintErrorStatus(s);
  175. GPR_ASSERT(!response.username().empty());
  176. GPR_ASSERT(!response.oauth_scope().empty());
  177. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  178. const char* oauth_scope_str = response.oauth_scope().c_str();
  179. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  180. gpr_log(GPR_INFO, "Unary with oauth2 access token credentials done.");
  181. }
  182. void InteropClient::DoPerRpcCreds(const grpc::string& username,
  183. const grpc::string& oauth_scope) {
  184. gpr_log(GPR_INFO,
  185. "Sending a unary rpc with per-rpc raw oauth2 access token ...");
  186. SimpleRequest request;
  187. SimpleResponse response;
  188. request.set_fill_username(true);
  189. request.set_fill_oauth_scope(true);
  190. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  191. ClientContext context;
  192. grpc::string access_token = GetOauth2AccessToken();
  193. std::shared_ptr<Credentials> creds = AccessTokenCredentials(access_token);
  194. context.set_credentials(creds);
  195. Status s = stub->UnaryCall(&context, request, &response);
  196. AssertOkOrPrintErrorStatus(s);
  197. GPR_ASSERT(!response.username().empty());
  198. GPR_ASSERT(!response.oauth_scope().empty());
  199. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  200. const char* oauth_scope_str = response.oauth_scope().c_str();
  201. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  202. gpr_log(GPR_INFO, "Unary with per-rpc oauth2 access token done.");
  203. }
  204. void InteropClient::DoJwtTokenCreds(const grpc::string& username) {
  205. gpr_log(GPR_INFO, "Sending a large unary rpc with JWT token credentials ...");
  206. SimpleRequest request;
  207. SimpleResponse response;
  208. request.set_fill_username(true);
  209. request.set_response_type(PayloadType::COMPRESSABLE);
  210. PerformLargeUnary(&request, &response);
  211. GPR_ASSERT(!response.username().empty());
  212. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  213. gpr_log(GPR_INFO, "Large unary with JWT token creds done.");
  214. }
  215. void InteropClient::DoLargeUnary() {
  216. const CompressionType compression_types[] = {NONE, GZIP, DEFLATE};
  217. const PayloadType payload_types[] = {COMPRESSABLE, UNCOMPRESSABLE, RANDOM};
  218. for (const auto payload_type : payload_types) {
  219. for (const auto compression_type : compression_types) {
  220. char* log_suffix;
  221. gpr_asprintf(&log_suffix, "(compression=%s; payload=%s)",
  222. CompressionType_Name(compression_type).c_str(),
  223. PayloadType_Name(payload_type).c_str());
  224. gpr_log(GPR_INFO, "Sending a large unary rpc %s.", log_suffix);
  225. SimpleRequest request;
  226. SimpleResponse response;
  227. request.set_response_type(payload_type);
  228. request.set_response_compression(compression_type);
  229. PerformLargeUnary(&request, &response);
  230. gpr_log(GPR_INFO, "Large unary done %s.", log_suffix);
  231. gpr_free(log_suffix);
  232. }
  233. }
  234. }
  235. void InteropClient::DoRequestStreaming() {
  236. gpr_log(GPR_INFO, "Sending request steaming rpc ...");
  237. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  238. ClientContext context;
  239. StreamingInputCallRequest request;
  240. StreamingInputCallResponse response;
  241. std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
  242. stub->StreamingInputCall(&context, &response));
  243. int aggregated_payload_size = 0;
  244. for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
  245. Payload* payload = request.mutable_payload();
  246. payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
  247. GPR_ASSERT(stream->Write(request));
  248. aggregated_payload_size += request_stream_sizes[i];
  249. }
  250. stream->WritesDone();
  251. Status s = stream->Finish();
  252. GPR_ASSERT(response.aggregated_payload_size() == aggregated_payload_size);
  253. AssertOkOrPrintErrorStatus(s);
  254. gpr_log(GPR_INFO, "Request streaming done.");
  255. }
  256. void InteropClient::DoResponseStreaming() {
  257. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  258. const CompressionType compression_types[] = {NONE, GZIP, DEFLATE};
  259. const PayloadType payload_types[] = {COMPRESSABLE, UNCOMPRESSABLE, RANDOM};
  260. for (const auto payload_type : payload_types) {
  261. for (const auto compression_type : compression_types) {
  262. ClientContext context;
  263. InteropClientContextInspector inspector(context);
  264. StreamingOutputCallRequest request;
  265. char* log_suffix;
  266. gpr_asprintf(&log_suffix, "(compression=%s; payload=%s)",
  267. CompressionType_Name(compression_type).c_str(),
  268. PayloadType_Name(payload_type).c_str());
  269. gpr_log(GPR_INFO, "Receiving response steaming rpc %s.", log_suffix);
  270. request.set_response_type(payload_type);
  271. request.set_response_compression(compression_type);
  272. for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
  273. ResponseParameters* response_parameter =
  274. request.add_response_parameters();
  275. response_parameter->set_size(response_stream_sizes[i]);
  276. }
  277. StreamingOutputCallResponse response;
  278. std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
  279. stub->StreamingOutputCall(&context, request));
  280. unsigned int i = 0;
  281. while (stream->Read(&response)) {
  282. GPR_ASSERT(response.payload().body() ==
  283. grpc::string(response_stream_sizes[i], '\0'));
  284. // Compression related checks.
  285. GPR_ASSERT(request.response_compression() ==
  286. GetInteropCompressionTypeFromCompressionAlgorithm(
  287. inspector.GetCallCompressionAlgorithm()));
  288. if (request.response_compression() == NONE) {
  289. GPR_ASSERT(
  290. !(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS));
  291. } else if (request.response_type() == PayloadType::COMPRESSABLE) {
  292. // requested compression and compressable response => results should
  293. // always be compressed.
  294. GPR_ASSERT(inspector.GetMessageFlags() &
  295. GRPC_WRITE_INTERNAL_COMPRESS);
  296. }
  297. ++i;
  298. }
  299. GPR_ASSERT(response_stream_sizes.size() == i);
  300. Status s = stream->Finish();
  301. AssertOkOrPrintErrorStatus(s);
  302. gpr_log(GPR_INFO, "Response streaming done %s.", log_suffix);
  303. gpr_free(log_suffix);
  304. }
  305. }
  306. }
  307. void InteropClient::DoResponseStreamingWithSlowConsumer() {
  308. gpr_log(GPR_INFO, "Receiving response steaming rpc with slow consumer ...");
  309. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  310. ClientContext context;
  311. StreamingOutputCallRequest request;
  312. for (int i = 0; i < kNumResponseMessages; ++i) {
  313. ResponseParameters* response_parameter = request.add_response_parameters();
  314. response_parameter->set_size(kResponseMessageSize);
  315. }
  316. StreamingOutputCallResponse response;
  317. std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
  318. stub->StreamingOutputCall(&context, request));
  319. int i = 0;
  320. while (stream->Read(&response)) {
  321. GPR_ASSERT(response.payload().body() ==
  322. grpc::string(kResponseMessageSize, '\0'));
  323. gpr_log(GPR_INFO, "received message %d", i);
  324. usleep(kReceiveDelayMilliSeconds * 1000);
  325. ++i;
  326. }
  327. GPR_ASSERT(kNumResponseMessages == i);
  328. Status s = stream->Finish();
  329. AssertOkOrPrintErrorStatus(s);
  330. gpr_log(GPR_INFO, "Response streaming done.");
  331. }
  332. void InteropClient::DoHalfDuplex() {
  333. gpr_log(GPR_INFO, "Sending half-duplex streaming rpc ...");
  334. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  335. ClientContext context;
  336. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  337. StreamingOutputCallResponse>>
  338. stream(stub->HalfDuplexCall(&context));
  339. StreamingOutputCallRequest request;
  340. ResponseParameters* response_parameter = request.add_response_parameters();
  341. for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
  342. response_parameter->set_size(response_stream_sizes[i]);
  343. GPR_ASSERT(stream->Write(request));
  344. }
  345. stream->WritesDone();
  346. unsigned int i = 0;
  347. StreamingOutputCallResponse response;
  348. while (stream->Read(&response)) {
  349. GPR_ASSERT(response.payload().has_body());
  350. GPR_ASSERT(response.payload().body() ==
  351. grpc::string(response_stream_sizes[i], '\0'));
  352. ++i;
  353. }
  354. GPR_ASSERT(response_stream_sizes.size() == i);
  355. Status s = stream->Finish();
  356. AssertOkOrPrintErrorStatus(s);
  357. gpr_log(GPR_INFO, "Half-duplex streaming rpc done.");
  358. }
  359. void InteropClient::DoPingPong() {
  360. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
  361. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  362. ClientContext context;
  363. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  364. StreamingOutputCallResponse>>
  365. stream(stub->FullDuplexCall(&context));
  366. StreamingOutputCallRequest request;
  367. request.set_response_type(PayloadType::COMPRESSABLE);
  368. ResponseParameters* response_parameter = request.add_response_parameters();
  369. Payload* payload = request.mutable_payload();
  370. StreamingOutputCallResponse response;
  371. for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
  372. response_parameter->set_size(response_stream_sizes[i]);
  373. payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
  374. GPR_ASSERT(stream->Write(request));
  375. GPR_ASSERT(stream->Read(&response));
  376. GPR_ASSERT(response.payload().has_body());
  377. GPR_ASSERT(response.payload().body() ==
  378. grpc::string(response_stream_sizes[i], '\0'));
  379. }
  380. stream->WritesDone();
  381. GPR_ASSERT(!stream->Read(&response));
  382. Status s = stream->Finish();
  383. AssertOkOrPrintErrorStatus(s);
  384. gpr_log(GPR_INFO, "Ping pong streaming done.");
  385. }
  386. void InteropClient::DoCancelAfterBegin() {
  387. gpr_log(GPR_INFO, "Sending request steaming rpc ...");
  388. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  389. ClientContext context;
  390. StreamingInputCallRequest request;
  391. StreamingInputCallResponse response;
  392. std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
  393. stub->StreamingInputCall(&context, &response));
  394. gpr_log(GPR_INFO, "Trying to cancel...");
  395. context.TryCancel();
  396. Status s = stream->Finish();
  397. GPR_ASSERT(s.error_code() == StatusCode::CANCELLED);
  398. gpr_log(GPR_INFO, "Canceling streaming done.");
  399. }
  400. void InteropClient::DoCancelAfterFirstResponse() {
  401. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
  402. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  403. ClientContext context;
  404. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  405. StreamingOutputCallResponse>>
  406. stream(stub->FullDuplexCall(&context));
  407. StreamingOutputCallRequest request;
  408. request.set_response_type(PayloadType::COMPRESSABLE);
  409. ResponseParameters* response_parameter = request.add_response_parameters();
  410. response_parameter->set_size(31415);
  411. request.mutable_payload()->set_body(grpc::string(27182, '\0'));
  412. StreamingOutputCallResponse response;
  413. GPR_ASSERT(stream->Write(request));
  414. GPR_ASSERT(stream->Read(&response));
  415. GPR_ASSERT(response.payload().has_body());
  416. GPR_ASSERT(response.payload().body() == grpc::string(31415, '\0'));
  417. gpr_log(GPR_INFO, "Trying to cancel...");
  418. context.TryCancel();
  419. Status s = stream->Finish();
  420. gpr_log(GPR_INFO, "Canceling pingpong streaming done.");
  421. }
  422. void InteropClient::DoTimeoutOnSleepingServer() {
  423. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc with a short deadline...");
  424. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  425. ClientContext context;
  426. std::chrono::system_clock::time_point deadline =
  427. std::chrono::system_clock::now() + std::chrono::milliseconds(1);
  428. context.set_deadline(deadline);
  429. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  430. StreamingOutputCallResponse>>
  431. stream(stub->FullDuplexCall(&context));
  432. StreamingOutputCallRequest request;
  433. request.mutable_payload()->set_body(grpc::string(27182, '\0'));
  434. stream->Write(request);
  435. Status s = stream->Finish();
  436. GPR_ASSERT(s.error_code() == StatusCode::DEADLINE_EXCEEDED);
  437. gpr_log(GPR_INFO, "Pingpong streaming timeout done.");
  438. }
  439. } // namespace testing
  440. } // namespace grpc