interop_client.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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 <memory>
  35. #include <unistd.h>
  36. #include <grpc/grpc.h>
  37. #include <grpc/support/log.h>
  38. #include <grpc++/channel_interface.h>
  39. #include <grpc++/client_context.h>
  40. #include <grpc++/status.h>
  41. #include <grpc++/stream.h>
  42. #include "test/proto/test.grpc.pb.h"
  43. #include "test/proto/empty.grpc.pb.h"
  44. #include "test/proto/messages.grpc.pb.h"
  45. namespace grpc {
  46. namespace testing {
  47. namespace {
  48. // The same value is defined by the Java client.
  49. const std::vector<int> request_stream_sizes = {27182, 8, 1828, 45904};
  50. const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979};
  51. const int kNumResponseMessages = 2000;
  52. const int kResponseMessageSize = 1030;
  53. const int kReceiveDelayMilliSeconds = 20;
  54. const int kLargeRequestSize = 271828;
  55. const int kLargeResponseSize = 314159;
  56. } // namespace
  57. InteropClient::InteropClient(std::shared_ptr<ChannelInterface> channel)
  58. : channel_(channel) {}
  59. void InteropClient::AssertOkOrPrintErrorStatus(const Status& s) {
  60. if (s.ok()) {
  61. return;
  62. }
  63. gpr_log(GPR_INFO, "Error status code: %d, message: %s", s.error_code(),
  64. s.error_message().c_str());
  65. GPR_ASSERT(0);
  66. }
  67. void InteropClient::DoEmpty() {
  68. gpr_log(GPR_INFO, "Sending an empty rpc...");
  69. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  70. Empty request = Empty::default_instance();
  71. Empty response = Empty::default_instance();
  72. ClientContext context;
  73. Status s = stub->EmptyCall(&context, request, &response);
  74. AssertOkOrPrintErrorStatus(s);
  75. gpr_log(GPR_INFO, "Empty rpc done.");
  76. }
  77. // Shared code to set large payload, make rpc and check response payload.
  78. void InteropClient::PerformLargeUnary(SimpleRequest* request,
  79. SimpleResponse* response) {
  80. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  81. ClientContext context;
  82. // XXX: add UNCOMPRESSABLE to the mix
  83. //
  84. // XXX: 1) set request.response_compression to all the diff available
  85. // compression values. We can't check the compression method used at the
  86. // application level, but if something is wrong, two different implementations
  87. // of gRPC (java vs c) won't be able to communicate.
  88. //
  89. // 2) for UNCOMPRESSABLE, verify that the response can be whatever, most
  90. // likely uncompressed
  91. request->set_response_type(PayloadType::COMPRESSABLE);
  92. request->set_response_size(kLargeResponseSize);
  93. grpc::string payload(kLargeRequestSize, '\0');
  94. request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
  95. Status s = stub->UnaryCall(&context, *request, response);
  96. AssertOkOrPrintErrorStatus(s);
  97. GPR_ASSERT(response->payload().type() == PayloadType::COMPRESSABLE);
  98. GPR_ASSERT(response->payload().body() ==
  99. grpc::string(kLargeResponseSize, '\0'));
  100. }
  101. void InteropClient::DoComputeEngineCreds(
  102. const grpc::string& default_service_account,
  103. const grpc::string& oauth_scope) {
  104. gpr_log(GPR_INFO,
  105. "Sending a large unary rpc with compute engine credentials ...");
  106. SimpleRequest request;
  107. SimpleResponse response;
  108. request.set_fill_username(true);
  109. request.set_fill_oauth_scope(true);
  110. PerformLargeUnary(&request, &response);
  111. gpr_log(GPR_INFO, "Got username %s", response.username().c_str());
  112. gpr_log(GPR_INFO, "Got oauth_scope %s", response.oauth_scope().c_str());
  113. GPR_ASSERT(!response.username().empty());
  114. GPR_ASSERT(response.username().c_str() == default_service_account);
  115. GPR_ASSERT(!response.oauth_scope().empty());
  116. const char* oauth_scope_str = response.oauth_scope().c_str();
  117. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  118. gpr_log(GPR_INFO, "Large unary with compute engine creds done.");
  119. }
  120. void InteropClient::DoServiceAccountCreds(const grpc::string& username,
  121. const grpc::string& oauth_scope) {
  122. gpr_log(GPR_INFO,
  123. "Sending a large unary rpc with service account credentials ...");
  124. SimpleRequest request;
  125. SimpleResponse response;
  126. request.set_fill_username(true);
  127. request.set_fill_oauth_scope(true);
  128. PerformLargeUnary(&request, &response);
  129. GPR_ASSERT(!response.username().empty());
  130. GPR_ASSERT(!response.oauth_scope().empty());
  131. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  132. const char* oauth_scope_str = response.oauth_scope().c_str();
  133. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  134. gpr_log(GPR_INFO, "Large unary with service account creds done.");
  135. }
  136. void InteropClient::DoOauth2AuthToken(const grpc::string& username,
  137. const grpc::string& oauth_scope) {
  138. gpr_log(GPR_INFO,
  139. "Sending a unary rpc with raw oauth2 access token credentials ...");
  140. SimpleRequest request;
  141. SimpleResponse response;
  142. request.set_fill_username(true);
  143. request.set_fill_oauth_scope(true);
  144. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  145. ClientContext context;
  146. Status s = stub->UnaryCall(&context, request, &response);
  147. AssertOkOrPrintErrorStatus(s);
  148. GPR_ASSERT(!response.username().empty());
  149. GPR_ASSERT(!response.oauth_scope().empty());
  150. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  151. const char* oauth_scope_str = response.oauth_scope().c_str();
  152. GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
  153. gpr_log(GPR_INFO, "Unary with oauth2 access token credentials done.");
  154. }
  155. void InteropClient::DoJwtTokenCreds(const grpc::string& username) {
  156. gpr_log(GPR_INFO, "Sending a large unary rpc with JWT token credentials ...");
  157. SimpleRequest request;
  158. SimpleResponse response;
  159. request.set_fill_username(true);
  160. PerformLargeUnary(&request, &response);
  161. GPR_ASSERT(!response.username().empty());
  162. GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
  163. gpr_log(GPR_INFO, "Large unary with JWT token creds done.");
  164. }
  165. void InteropClient::DoLargeUnary() {
  166. gpr_log(GPR_INFO, "Sending a large unary rpc...");
  167. SimpleRequest request;
  168. request.set_response_compression(grpc::testing::GZIP);
  169. SimpleResponse response;
  170. PerformLargeUnary(&request, &response);
  171. gpr_log(GPR_INFO, "Large unary done.");
  172. }
  173. void InteropClient::DoRequestStreaming() {
  174. gpr_log(GPR_INFO, "Sending request steaming rpc ...");
  175. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  176. ClientContext context;
  177. StreamingInputCallRequest request;
  178. StreamingInputCallResponse response;
  179. std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
  180. stub->StreamingInputCall(&context, &response));
  181. int aggregated_payload_size = 0;
  182. for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
  183. Payload* payload = request.mutable_payload();
  184. payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
  185. GPR_ASSERT(stream->Write(request));
  186. aggregated_payload_size += request_stream_sizes[i];
  187. }
  188. stream->WritesDone();
  189. Status s = stream->Finish();
  190. GPR_ASSERT(response.aggregated_payload_size() == aggregated_payload_size);
  191. AssertOkOrPrintErrorStatus(s);
  192. gpr_log(GPR_INFO, "Request streaming done.");
  193. }
  194. void InteropClient::DoResponseStreaming() {
  195. gpr_log(GPR_INFO, "Receiving response steaming rpc ...");
  196. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  197. ClientContext context;
  198. StreamingOutputCallRequest request;
  199. for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
  200. ResponseParameters* response_parameter = request.add_response_parameters();
  201. response_parameter->set_size(response_stream_sizes[i]);
  202. }
  203. StreamingOutputCallResponse response;
  204. std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
  205. stub->StreamingOutputCall(&context, request));
  206. unsigned int i = 0;
  207. while (stream->Read(&response)) {
  208. GPR_ASSERT(response.payload().body() ==
  209. grpc::string(response_stream_sizes[i], '\0'));
  210. ++i;
  211. }
  212. GPR_ASSERT(response_stream_sizes.size() == i);
  213. Status s = stream->Finish();
  214. AssertOkOrPrintErrorStatus(s);
  215. gpr_log(GPR_INFO, "Response streaming done.");
  216. }
  217. void InteropClient::DoResponseStreamingWithSlowConsumer() {
  218. gpr_log(GPR_INFO, "Receiving response steaming rpc with slow consumer ...");
  219. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  220. ClientContext context;
  221. StreamingOutputCallRequest request;
  222. for (int i = 0; i < kNumResponseMessages; ++i) {
  223. ResponseParameters* response_parameter = request.add_response_parameters();
  224. response_parameter->set_size(kResponseMessageSize);
  225. }
  226. StreamingOutputCallResponse response;
  227. std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
  228. stub->StreamingOutputCall(&context, request));
  229. int i = 0;
  230. while (stream->Read(&response)) {
  231. GPR_ASSERT(response.payload().body() ==
  232. grpc::string(kResponseMessageSize, '\0'));
  233. gpr_log(GPR_INFO, "received message %d", i);
  234. usleep(kReceiveDelayMilliSeconds * 1000);
  235. ++i;
  236. }
  237. GPR_ASSERT(kNumResponseMessages == i);
  238. Status s = stream->Finish();
  239. AssertOkOrPrintErrorStatus(s);
  240. gpr_log(GPR_INFO, "Response streaming done.");
  241. }
  242. void InteropClient::DoHalfDuplex() {
  243. gpr_log(GPR_INFO, "Sending half-duplex streaming rpc ...");
  244. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  245. ClientContext context;
  246. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  247. StreamingOutputCallResponse>>
  248. stream(stub->HalfDuplexCall(&context));
  249. StreamingOutputCallRequest request;
  250. ResponseParameters* response_parameter = request.add_response_parameters();
  251. for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
  252. response_parameter->set_size(response_stream_sizes[i]);
  253. GPR_ASSERT(stream->Write(request));
  254. }
  255. stream->WritesDone();
  256. unsigned int i = 0;
  257. StreamingOutputCallResponse response;
  258. while (stream->Read(&response)) {
  259. GPR_ASSERT(response.payload().has_body());
  260. GPR_ASSERT(response.payload().body() ==
  261. grpc::string(response_stream_sizes[i], '\0'));
  262. ++i;
  263. }
  264. GPR_ASSERT(response_stream_sizes.size() == i);
  265. Status s = stream->Finish();
  266. AssertOkOrPrintErrorStatus(s);
  267. gpr_log(GPR_INFO, "Half-duplex streaming rpc done.");
  268. }
  269. void InteropClient::DoPingPong() {
  270. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
  271. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  272. ClientContext context;
  273. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  274. StreamingOutputCallResponse>>
  275. stream(stub->FullDuplexCall(&context));
  276. StreamingOutputCallRequest request;
  277. request.set_response_type(PayloadType::COMPRESSABLE);
  278. ResponseParameters* response_parameter = request.add_response_parameters();
  279. Payload* payload = request.mutable_payload();
  280. StreamingOutputCallResponse response;
  281. for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
  282. response_parameter->set_size(response_stream_sizes[i]);
  283. payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
  284. GPR_ASSERT(stream->Write(request));
  285. GPR_ASSERT(stream->Read(&response));
  286. GPR_ASSERT(response.payload().has_body());
  287. GPR_ASSERT(response.payload().body() ==
  288. grpc::string(response_stream_sizes[i], '\0'));
  289. }
  290. stream->WritesDone();
  291. GPR_ASSERT(!stream->Read(&response));
  292. Status s = stream->Finish();
  293. AssertOkOrPrintErrorStatus(s);
  294. gpr_log(GPR_INFO, "Ping pong streaming done.");
  295. }
  296. void InteropClient::DoCancelAfterBegin() {
  297. gpr_log(GPR_INFO, "Sending request steaming rpc ...");
  298. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  299. ClientContext context;
  300. StreamingInputCallRequest request;
  301. StreamingInputCallResponse response;
  302. std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
  303. stub->StreamingInputCall(&context, &response));
  304. gpr_log(GPR_INFO, "Trying to cancel...");
  305. context.TryCancel();
  306. Status s = stream->Finish();
  307. GPR_ASSERT(s.error_code() == StatusCode::CANCELLED);
  308. gpr_log(GPR_INFO, "Canceling streaming done.");
  309. }
  310. void InteropClient::DoCancelAfterFirstResponse() {
  311. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
  312. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  313. ClientContext context;
  314. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  315. StreamingOutputCallResponse>>
  316. stream(stub->FullDuplexCall(&context));
  317. StreamingOutputCallRequest request;
  318. request.set_response_type(PayloadType::COMPRESSABLE);
  319. ResponseParameters* response_parameter = request.add_response_parameters();
  320. response_parameter->set_size(31415);
  321. request.mutable_payload()->set_body(grpc::string(27182, '\0'));
  322. StreamingOutputCallResponse response;
  323. GPR_ASSERT(stream->Write(request));
  324. GPR_ASSERT(stream->Read(&response));
  325. GPR_ASSERT(response.payload().has_body());
  326. GPR_ASSERT(response.payload().body() == grpc::string(31415, '\0'));
  327. gpr_log(GPR_INFO, "Trying to cancel...");
  328. context.TryCancel();
  329. Status s = stream->Finish();
  330. gpr_log(GPR_INFO, "Canceling pingpong streaming done.");
  331. }
  332. void InteropClient::DoTimeoutOnSleepingServer() {
  333. gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc with a short deadline...");
  334. std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
  335. ClientContext context;
  336. std::chrono::system_clock::time_point deadline =
  337. std::chrono::system_clock::now() + std::chrono::milliseconds(1);
  338. context.set_deadline(deadline);
  339. std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
  340. StreamingOutputCallResponse>>
  341. stream(stub->FullDuplexCall(&context));
  342. StreamingOutputCallRequest request;
  343. request.mutable_payload()->set_body(grpc::string(27182, '\0'));
  344. stream->Write(request);
  345. Status s = stream->Finish();
  346. GPR_ASSERT(s.error_code() == StatusCode::DEADLINE_EXCEEDED);
  347. gpr_log(GPR_INFO, "Pingpong streaming timeout done.");
  348. }
  349. } // namespace testing
  350. } // namespace grpc