xref: /aosp_15_r20/external/grpc-grpc/test/cpp/util/grpc_tool_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2016 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 
19 #include "test/cpp/util/grpc_tool.h"
20 
21 #include <chrono>
22 #include <sstream>
23 
24 #include <gmock/gmock-matchers.h>
25 #include <gtest/gtest.h>
26 
27 #include "absl/flags/declare.h"
28 #include "absl/flags/flag.h"
29 #include "absl/strings/str_split.h"
30 
31 #include <grpc/grpc.h>
32 #include <grpc/support/alloc.h>
33 #include <grpcpp/channel.h>
34 #include <grpcpp/client_context.h>
35 #include <grpcpp/create_channel.h>
36 #include <grpcpp/ext/proto_server_reflection_plugin.h>
37 #include <grpcpp/server.h>
38 #include <grpcpp/server_builder.h>
39 #include <grpcpp/server_context.h>
40 
41 #include "src/core/lib/gprpp/env.h"
42 #include "src/proto/grpc/testing/echo.grpc.pb.h"
43 #include "src/proto/grpc/testing/echo.pb.h"
44 #include "test/core/util/port.h"
45 #include "test/core/util/test_config.h"
46 #include "test/core/util/tls_utils.h"
47 #include "test/cpp/util/cli_credentials.h"
48 #include "test/cpp/util/string_ref_helper.h"
49 #include "test/cpp/util/test_config.h"
50 
51 #define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem"
52 #define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem"
53 #define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key"
54 
55 using grpc::testing::EchoRequest;
56 using grpc::testing::EchoResponse;
57 
58 #define USAGE_REGEX "(  grpc_cli .+\n){2,10}"
59 
60 #define ECHO_TEST_SERVICE_SUMMARY \
61   "Echo\n"                        \
62   "Echo1\n"                       \
63   "Echo2\n"                       \
64   "CheckDeadlineUpperBound\n"     \
65   "CheckDeadlineSet\n"            \
66   "CheckClientInitialMetadata\n"  \
67   "RequestStream\n"               \
68   "ResponseStream\n"              \
69   "BidiStream\n"                  \
70   "Unimplemented\n"               \
71   "UnimplementedBidi\n"
72 
73 #define ECHO_TEST_SERVICE_DESCRIPTION                                          \
74   "filename: src/proto/grpc/testing/echo.proto\n"                              \
75   "package: grpc.testing;\n"                                                   \
76   "service EchoTestService {\n"                                                \
77   "  rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) "  \
78   "{}\n"                                                                       \
79   "  rpc Echo1(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
80   "{}\n"                                                                       \
81   "  rpc Echo2(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
82   "{}\n"                                                                       \
83   "  rpc CheckDeadlineUpperBound(grpc.testing.SimpleRequest) returns "         \
84   "(grpc.testing.StringValue) {}\n"                                            \
85   "  rpc CheckDeadlineSet(grpc.testing.SimpleRequest) returns "                \
86   "(grpc.testing.StringValue) {}\n"                                            \
87   "  rpc CheckClientInitialMetadata(grpc.testing.SimpleRequest) returns "      \
88   "(grpc.testing.SimpleResponse) {}\n"                                         \
89   "  rpc RequestStream(stream grpc.testing.EchoRequest) returns "              \
90   "(grpc.testing.EchoResponse) {}\n"                                           \
91   "  rpc ResponseStream(grpc.testing.EchoRequest) returns (stream "            \
92   "grpc.testing.EchoResponse) {}\n"                                            \
93   "  rpc BidiStream(stream grpc.testing.EchoRequest) returns (stream "         \
94   "grpc.testing.EchoResponse) {}\n"                                            \
95   "  rpc Unimplemented(grpc.testing.EchoRequest) returns "                     \
96   "(grpc.testing.EchoResponse) {}\n"                                           \
97   "  rpc UnimplementedBidi(stream grpc.testing.EchoRequest) returns (stream "  \
98   "grpc.testing.EchoResponse) {}\n"                                            \
99   "}\n"                                                                        \
100   "\n"
101 
102 #define ECHO_METHOD_DESCRIPTION                                               \
103   "  rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
104   "{}\n"
105 
106 #define ECHO_RESPONSE_MESSAGE_TEXT_FORMAT \
107   "message: \"echo\"\n"                   \
108   "param {\n"                             \
109   "  host: \"localhost\"\n"               \
110   "  peer: \"peer\"\n"                    \
111   "}\n\n"
112 
113 #define ECHO_RESPONSE_MESSAGE_JSON_FORMAT \
114   "{\n"                                   \
115   " \"message\": \"echo\",\n"             \
116   " \"param\": {\n"                       \
117   "  \"host\": \"localhost\",\n"          \
118   "  \"peer\": \"peer\"\n"                \
119   " }\n"                                  \
120   "}\n\n"
121 
122 ABSL_DECLARE_FLAG(std::string, channel_creds_type);
123 ABSL_DECLARE_FLAG(std::string, ssl_target);
124 ABSL_DECLARE_FLAG(bool, binary_input);
125 ABSL_DECLARE_FLAG(bool, binary_output);
126 ABSL_DECLARE_FLAG(bool, json_input);
127 ABSL_DECLARE_FLAG(bool, json_output);
128 ABSL_DECLARE_FLAG(bool, l);
129 ABSL_DECLARE_FLAG(bool, batch);
130 ABSL_DECLARE_FLAG(std::string, metadata);
131 ABSL_DECLARE_FLAG(std::string, protofiles);
132 ABSL_DECLARE_FLAG(std::string, proto_path);
133 ABSL_DECLARE_FLAG(std::string, default_service_config);
134 ABSL_DECLARE_FLAG(double, timeout);
135 ABSL_DECLARE_FLAG(int, max_recv_msg_size);
136 
137 namespace grpc {
138 namespace testing {
139 namespace {
140 
141 const int kServerDefaultResponseStreamsToSend = 3;
142 
143 class TestCliCredentials final : public grpc::testing::CliCredentials {
144  public:
TestCliCredentials(bool secure=false)145   explicit TestCliCredentials(bool secure = false) : secure_(secure) {}
GetChannelCredentials() const146   std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials()
147       const override {
148     if (!secure_) {
149       return InsecureChannelCredentials();
150     }
151     std::string test_root_cert =
152         grpc_core::testing::GetFileContents(CA_CERT_PATH);
153     SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
154     return grpc::SslCredentials(grpc::SslCredentialsOptions(ssl_opts));
155   }
GetCredentialUsage() const156   std::string GetCredentialUsage() const override { return ""; }
157 
158  private:
159   const bool secure_;
160 };
161 
PrintStream(std::stringstream * ss,const std::string & output)162 bool PrintStream(std::stringstream* ss, const std::string& output) {
163   (*ss) << output;
164   return true;
165 }
166 
167 template <typename T>
ArraySize(T & a)168 size_t ArraySize(T& a) {
169   return ((sizeof(a) / sizeof(*(a))) /
170           static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
171 }
172 
173 class TestServiceImpl : public grpc::testing::EchoTestService::Service {
174  public:
Echo(ServerContext * context,const EchoRequest * request,EchoResponse * response)175   Status Echo(ServerContext* context, const EchoRequest* request,
176               EchoResponse* response) override {
177     if (!context->client_metadata().empty()) {
178       for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
179                iter = context->client_metadata().begin();
180            iter != context->client_metadata().end(); ++iter) {
181         context->AddInitialMetadata(ToString(iter->first),
182                                     ToString(iter->second));
183       }
184     }
185     context->AddTrailingMetadata("trailing_key", "trailing_value");
186     response->set_message(request->message());
187     return Status::OK;
188   }
189 
CheckDeadlineSet(ServerContext * context,const SimpleRequest *,StringValue * response)190   Status CheckDeadlineSet(ServerContext* context,
191                           const SimpleRequest* /*request*/,
192                           StringValue* response) override {
193     response->set_message(context->deadline() !=
194                                   std::chrono::system_clock::time_point::max()
195                               ? "true"
196                               : "false");
197     return Status::OK;
198   }
199 
200   // Check if deadline - current time <= timeout
201   // If deadline set, timeout + current time should be an upper bound for it
CheckDeadlineUpperBound(ServerContext * context,const SimpleRequest *,StringValue * response)202   Status CheckDeadlineUpperBound(ServerContext* context,
203                                  const SimpleRequest* /*request*/,
204                                  StringValue* response) override {
205     auto seconds = std::chrono::duration_cast<std::chrono::seconds>(
206         context->deadline() - std::chrono::system_clock::now());
207 
208     // Returning string instead of bool to avoid using embedded messages in
209     // proto3
210     response->set_message(
211         seconds.count() <= absl::GetFlag(FLAGS_timeout) ? "true" : "false");
212     return Status::OK;
213   }
214 
RequestStream(ServerContext * context,ServerReader<EchoRequest> * reader,EchoResponse * response)215   Status RequestStream(ServerContext* context,
216                        ServerReader<EchoRequest>* reader,
217                        EchoResponse* response) override {
218     EchoRequest request;
219     response->set_message("");
220     if (!context->client_metadata().empty()) {
221       for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
222                iter = context->client_metadata().begin();
223            iter != context->client_metadata().end(); ++iter) {
224         context->AddInitialMetadata(ToString(iter->first),
225                                     ToString(iter->second));
226       }
227     }
228     context->AddTrailingMetadata("trailing_key", "trailing_value");
229     while (reader->Read(&request)) {
230       response->mutable_message()->append(request.message());
231     }
232 
233     return Status::OK;
234   }
235 
ResponseStream(ServerContext * context,const EchoRequest * request,ServerWriter<EchoResponse> * writer)236   Status ResponseStream(ServerContext* context, const EchoRequest* request,
237                         ServerWriter<EchoResponse>* writer) override {
238     if (!context->client_metadata().empty()) {
239       for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
240                iter = context->client_metadata().begin();
241            iter != context->client_metadata().end(); ++iter) {
242         context->AddInitialMetadata(ToString(iter->first),
243                                     ToString(iter->second));
244       }
245     }
246     context->AddTrailingMetadata("trailing_key", "trailing_value");
247 
248     EchoResponse response;
249     for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
250       response.set_message(request->message() + std::to_string(i));
251       writer->Write(response);
252     }
253 
254     return Status::OK;
255   }
256 
BidiStream(ServerContext * context,ServerReaderWriter<EchoResponse,EchoRequest> * stream)257   Status BidiStream(
258       ServerContext* context,
259       ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
260     EchoRequest request;
261     EchoResponse response;
262     if (!context->client_metadata().empty()) {
263       for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
264                iter = context->client_metadata().begin();
265            iter != context->client_metadata().end(); ++iter) {
266         context->AddInitialMetadata(ToString(iter->first),
267                                     ToString(iter->second));
268       }
269     }
270     context->AddTrailingMetadata("trailing_key", "trailing_value");
271 
272     while (stream->Read(&request)) {
273       response.set_message(request.message());
274       stream->Write(response);
275     }
276 
277     return Status::OK;
278   }
279 };
280 
281 }  // namespace
282 
283 class GrpcToolTest : public ::testing::Test {
284  protected:
GrpcToolTest()285   GrpcToolTest() {}
286 
287   // SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
288   // uses atexit() to free chosen ports, and it will spawn a new thread in
289   // resolve_address_posix.c:192 at exit time.
SetUpServer(bool secure=false)290   std::string SetUpServer(bool secure = false) {
291     std::ostringstream server_address;
292     int port = grpc_pick_unused_port_or_die();
293     server_address << "localhost:" << port;
294     // Setup server
295     ServerBuilder builder;
296     std::shared_ptr<grpc::ServerCredentials> creds;
297     std::string server_cert =
298         grpc_core::testing::GetFileContents(SERVER_CERT_PATH);
299     std::string server_key =
300         grpc_core::testing::GetFileContents(SERVER_KEY_PATH);
301     SslServerCredentialsOptions::PemKeyCertPair pkcp = {server_key,
302                                                         server_cert};
303     if (secure) {
304       SslServerCredentialsOptions ssl_opts;
305       ssl_opts.pem_root_certs = "";
306       ssl_opts.pem_key_cert_pairs.push_back(pkcp);
307       creds = SslServerCredentials(ssl_opts);
308     } else {
309       creds = InsecureServerCredentials();
310     }
311     builder.AddListeningPort(server_address.str(), creds);
312     builder.RegisterService(&service_);
313     server_ = builder.BuildAndStart();
314     return server_address.str();
315   }
316 
ShutdownServer()317   void ShutdownServer() { server_->Shutdown(); }
318 
319   std::unique_ptr<Server> server_;
320   TestServiceImpl service_;
321   reflection::ProtoServerReflectionPlugin plugin_;
322 };
323 
TEST_F(GrpcToolTest,NoCommand)324 TEST_F(GrpcToolTest, NoCommand) {
325   // Test input "grpc_cli"
326   std::stringstream output_stream;
327   const char* argv[] = {"grpc_cli"};
328   // Exit with 1, print usage instruction in stderr
329   EXPECT_EXIT(
330       GrpcToolMainLib(
331           ArraySize(argv), argv, TestCliCredentials(),
332           std::bind(PrintStream, &output_stream, std::placeholders::_1)),
333       ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
334   // No output
335   EXPECT_TRUE(0 == output_stream.tellp());
336 }
337 
TEST_F(GrpcToolTest,InvalidCommand)338 TEST_F(GrpcToolTest, InvalidCommand) {
339   // Test input "grpc_cli"
340   std::stringstream output_stream;
341   const char* argv[] = {"grpc_cli", "abc"};
342   // Exit with 1, print usage instruction in stderr
343   EXPECT_EXIT(
344       GrpcToolMainLib(
345           ArraySize(argv), argv, TestCliCredentials(),
346           std::bind(PrintStream, &output_stream, std::placeholders::_1)),
347       ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
348   // No output
349   EXPECT_TRUE(0 == output_stream.tellp());
350 }
351 
TEST_F(GrpcToolTest,HelpCommand)352 TEST_F(GrpcToolTest, HelpCommand) {
353   // Test input "grpc_cli help"
354   std::stringstream output_stream;
355   const char* argv[] = {"grpc_cli", "help"};
356   // Exit with 1, print usage instruction in stderr
357   EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
358                               std::bind(PrintStream, &output_stream,
359                                         std::placeholders::_1)),
360               ::testing::ExitedWithCode(1), USAGE_REGEX);
361   // No output
362   EXPECT_TRUE(0 == output_stream.tellp());
363 }
364 
TEST_F(GrpcToolTest,ListCommand)365 TEST_F(GrpcToolTest, ListCommand) {
366   // Test input "grpc_cli list localhost:<port>"
367   std::stringstream output_stream;
368 
369   const std::string server_address = SetUpServer();
370   const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
371 
372   absl::SetFlag(&FLAGS_l, false);
373   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
374                                    std::bind(PrintStream, &output_stream,
375                                              std::placeholders::_1)));
376   EXPECT_THAT(absl::StrSplit(output_stream.str(), "\n"),
377               ::testing::UnorderedElementsAre(
378                   "grpc.testing.EchoTestService",
379                   "grpc.reflection.v1alpha.ServerReflection",
380                   "grpc.reflection.v1.ServerReflection", ""));
381 
382   ShutdownServer();
383 }
384 
TEST_F(GrpcToolTest,ListOneService)385 TEST_F(GrpcToolTest, ListOneService) {
386   // Test input "grpc_cli list localhost:<port> grpc.testing.EchoTestService"
387   std::stringstream output_stream;
388 
389   const std::string server_address = SetUpServer();
390   const char* argv[] = {"grpc_cli", "ls", server_address.c_str(),
391                         "grpc.testing.EchoTestService"};
392   // without -l flag
393   absl::SetFlag(&FLAGS_l, false);
394   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
395                                    std::bind(PrintStream, &output_stream,
396                                              std::placeholders::_1)));
397   // Expected output: ECHO_TEST_SERVICE_SUMMARY
398   EXPECT_TRUE(0 ==
399               strcmp(output_stream.str().c_str(), ECHO_TEST_SERVICE_SUMMARY));
400 
401   // with -l flag
402   output_stream.str(std::string());
403   output_stream.clear();
404   absl::SetFlag(&FLAGS_l, true);
405   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
406                                    std::bind(PrintStream, &output_stream,
407                                              std::placeholders::_1)));
408   // Expected output: ECHO_TEST_SERVICE_DESCRIPTION
409   EXPECT_TRUE(
410       0 == strcmp(output_stream.str().c_str(), ECHO_TEST_SERVICE_DESCRIPTION));
411 
412   ShutdownServer();
413 }
414 
TEST_F(GrpcToolTest,TypeCommand)415 TEST_F(GrpcToolTest, TypeCommand) {
416   // Test input "grpc_cli type localhost:<port> grpc.testing.EchoRequest"
417   std::stringstream output_stream;
418 
419   const std::string server_address = SetUpServer();
420   const char* argv[] = {"grpc_cli", "type", server_address.c_str(),
421                         "grpc.testing.EchoRequest"};
422 
423   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
424                                    std::bind(PrintStream, &output_stream,
425                                              std::placeholders::_1)));
426   const grpc::protobuf::Descriptor* desc =
427       grpc::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
428           "grpc.testing.EchoRequest");
429   // Expected output: the DebugString of grpc.testing.EchoRequest
430   EXPECT_TRUE(0 ==
431               strcmp(output_stream.str().c_str(), desc->DebugString().c_str()));
432 
433   ShutdownServer();
434 }
435 
TEST_F(GrpcToolTest,ListOneMethod)436 TEST_F(GrpcToolTest, ListOneMethod) {
437   // Test input "grpc_cli list localhost:<port> grpc.testing.EchoTestService"
438   std::stringstream output_stream;
439 
440   const std::string server_address = SetUpServer();
441   const char* argv[] = {"grpc_cli", "ls", server_address.c_str(),
442                         "grpc.testing.EchoTestService.Echo"};
443   // without -l flag
444   absl::SetFlag(&FLAGS_l, false);
445   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
446                                    std::bind(PrintStream, &output_stream,
447                                              std::placeholders::_1)));
448   // Expected output: "Echo"
449   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), "Echo\n"));
450 
451   // with -l flag
452   output_stream.str(std::string());
453   output_stream.clear();
454   absl::SetFlag(&FLAGS_l, true);
455   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
456                                    std::bind(PrintStream, &output_stream,
457                                              std::placeholders::_1)));
458   // Expected output: ECHO_METHOD_DESCRIPTION
459   EXPECT_TRUE(0 ==
460               strcmp(output_stream.str().c_str(), ECHO_METHOD_DESCRIPTION));
461 
462   ShutdownServer();
463 }
464 
TEST_F(GrpcToolTest,TypeNotFound)465 TEST_F(GrpcToolTest, TypeNotFound) {
466   // Test input "grpc_cli type localhost:<port> grpc.testing.PhonyRequest"
467   std::stringstream output_stream;
468 
469   const std::string server_address = SetUpServer();
470   const char* argv[] = {"grpc_cli", "type", server_address.c_str(),
471                         "grpc.testing.PhonyRequest"};
472 
473   EXPECT_TRUE(1 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
474                                    std::bind(PrintStream, &output_stream,
475                                              std::placeholders::_1)));
476   ShutdownServer();
477 }
478 
TEST_F(GrpcToolTest,CallCommand)479 TEST_F(GrpcToolTest, CallCommand) {
480   // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
481   std::stringstream output_stream;
482 
483   const std::string server_address = SetUpServer();
484   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
485                         "message: 'Hello'"};
486 
487   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
488                                    std::bind(PrintStream, &output_stream,
489                                              std::placeholders::_1)));
490   // Expected output: "message: \"Hello\""
491   EXPECT_TRUE(nullptr !=
492               strstr(output_stream.str().c_str(), "message: \"Hello\""));
493 
494   // with json_output
495   output_stream.str(std::string());
496   output_stream.clear();
497 
498   // TODO(Capstan): Consider using absl::FlagSaver
499   absl::SetFlag(&FLAGS_json_output, true);
500   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
501                                    std::bind(PrintStream, &output_stream,
502                                              std::placeholders::_1)));
503   absl::SetFlag(&FLAGS_json_output, false);
504 
505   // Expected output:
506   // {
507   //  "message": "Hello"
508   // }
509   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
510                                 "{\n \"message\": \"Hello\"\n}"));
511 
512   ShutdownServer();
513 }
514 
TEST_F(GrpcToolTest,CallCommandJsonInput)515 TEST_F(GrpcToolTest, CallCommandJsonInput) {
516   // Test input "grpc_cli call localhost:<port> Echo "{ \"message\": \"Hello\"}"
517   std::stringstream output_stream;
518 
519   const std::string server_address = SetUpServer();
520   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
521                         "{ \"message\": \"Hello\"}"};
522 
523   absl::SetFlag(&FLAGS_json_input, true);
524   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
525                                    std::bind(PrintStream, &output_stream,
526                                              std::placeholders::_1)));
527   // Expected output: "message: \"Hello\""
528   EXPECT_TRUE(nullptr !=
529               strstr(output_stream.str().c_str(), "message: \"Hello\""));
530 
531   // with json_output
532   output_stream.str(std::string());
533   output_stream.clear();
534 
535   absl::SetFlag(&FLAGS_json_output, true);
536   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
537                                    std::bind(PrintStream, &output_stream,
538                                              std::placeholders::_1)));
539   absl::SetFlag(&FLAGS_json_output, false);
540   absl::SetFlag(&FLAGS_json_input, false);
541 
542   // Expected output:
543   // {
544   //  "message": "Hello"
545   // }
546   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
547                                 "{\n \"message\": \"Hello\"\n}"));
548 
549   ShutdownServer();
550 }
551 
TEST_F(GrpcToolTest,CallCommandBatch)552 TEST_F(GrpcToolTest, CallCommandBatch) {
553   // Test input "grpc_cli call Echo"
554   std::stringstream output_stream;
555 
556   const std::string server_address = SetUpServer();
557   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
558                         "message: 'Hello0'"};
559 
560   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
561   std::streambuf* orig = std::cin.rdbuf();
562   std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
563   std::cin.rdbuf(ss.rdbuf());
564 
565   absl::SetFlag(&FLAGS_batch, true);
566   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
567                                    std::bind(PrintStream, &output_stream,
568                                              std::placeholders::_1)));
569   absl::SetFlag(&FLAGS_batch, false);
570 
571   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
572   // "Hello2"\n"
573   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
574                                 "message: \"Hello0\"\nmessage: "
575                                 "\"Hello1\"\nmessage: \"Hello2\"\n"));
576   // with json_output
577   output_stream.str(std::string());
578   output_stream.clear();
579   ss.clear();
580   ss.seekg(0);
581   std::cin.rdbuf(ss.rdbuf());
582 
583   absl::SetFlag(&FLAGS_batch, true);
584   absl::SetFlag(&FLAGS_json_output, true);
585   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
586                                    std::bind(PrintStream, &output_stream,
587                                              std::placeholders::_1)));
588   absl::SetFlag(&FLAGS_json_output, false);
589   absl::SetFlag(&FLAGS_batch, false);
590 
591   // Expected output:
592   // {
593   //  "message": "Hello0"
594   // }
595   // {
596   //  "message": "Hello1"
597   // }
598   // {
599   //  "message": "Hello2"
600   // }
601   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
602   // "Hello2"\n"
603   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
604                                 "{\n \"message\": \"Hello0\"\n}\n"
605                                 "{\n \"message\": \"Hello1\"\n}\n"
606                                 "{\n \"message\": \"Hello2\"\n}\n"));
607 
608   std::cin.rdbuf(orig);
609   ShutdownServer();
610 }
611 
TEST_F(GrpcToolTest,CallCommandBatchJsonInput)612 TEST_F(GrpcToolTest, CallCommandBatchJsonInput) {
613   // Test input "grpc_cli call Echo"
614   std::stringstream output_stream;
615 
616   const std::string server_address = SetUpServer();
617   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
618                         "{\"message\": \"Hello0\"}"};
619 
620   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
621   std::streambuf* orig = std::cin.rdbuf();
622   std::istringstream ss(
623       "{\"message\": \"Hello1\"}\n\n{\"message\": \"Hello2\" }\n\n");
624   std::cin.rdbuf(ss.rdbuf());
625 
626   absl::SetFlag(&FLAGS_json_input, true);
627   absl::SetFlag(&FLAGS_batch, true);
628   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
629                                    std::bind(PrintStream, &output_stream,
630                                              std::placeholders::_1)));
631   absl::SetFlag(&FLAGS_batch, false);
632 
633   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
634   // "Hello2"\n"
635   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
636                                 "message: \"Hello0\"\nmessage: "
637                                 "\"Hello1\"\nmessage: \"Hello2\"\n"));
638   // with json_output
639   output_stream.str(std::string());
640   output_stream.clear();
641   ss.clear();
642   ss.seekg(0);
643   std::cin.rdbuf(ss.rdbuf());
644 
645   absl::SetFlag(&FLAGS_batch, true);
646   absl::SetFlag(&FLAGS_json_output, true);
647   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
648                                    std::bind(PrintStream, &output_stream,
649                                              std::placeholders::_1)));
650   absl::SetFlag(&FLAGS_json_output, false);
651   absl::SetFlag(&FLAGS_batch, false);
652   absl::SetFlag(&FLAGS_json_input, false);
653 
654   // Expected output:
655   // {
656   //  "message": "Hello0"
657   // }
658   // {
659   //  "message": "Hello1"
660   // }
661   // {
662   //  "message": "Hello2"
663   // }
664   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
665   // "Hello2"\n"
666   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
667                                 "{\n \"message\": \"Hello0\"\n}\n"
668                                 "{\n \"message\": \"Hello1\"\n}\n"
669                                 "{\n \"message\": \"Hello2\"\n}\n"));
670 
671   std::cin.rdbuf(orig);
672   ShutdownServer();
673 }
674 
TEST_F(GrpcToolTest,CallCommandBatchWithBadRequest)675 TEST_F(GrpcToolTest, CallCommandBatchWithBadRequest) {
676   // Test input "grpc_cli call Echo"
677   std::stringstream output_stream;
678 
679   const std::string server_address = SetUpServer();
680   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
681                         "message: 'Hello0'"};
682 
683   // Mock std::cin input "message: 1\n\n message: 'Hello2'\n\n"
684   std::streambuf* orig = std::cin.rdbuf();
685   std::istringstream ss("message: 1\n\n message: 'Hello2'\n\n");
686   std::cin.rdbuf(ss.rdbuf());
687 
688   absl::SetFlag(&FLAGS_batch, true);
689   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
690                                    std::bind(PrintStream, &output_stream,
691                                              std::placeholders::_1)));
692   absl::SetFlag(&FLAGS_batch, false);
693 
694   // Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
695   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
696                                 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
697 
698   // with json_output
699   output_stream.str(std::string());
700   output_stream.clear();
701   ss.clear();
702   ss.seekg(0);
703   std::cin.rdbuf(ss.rdbuf());
704 
705   absl::SetFlag(&FLAGS_batch, true);
706   absl::SetFlag(&FLAGS_json_output, true);
707   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
708                                    std::bind(PrintStream, &output_stream,
709                                              std::placeholders::_1)));
710   absl::SetFlag(&FLAGS_json_output, false);
711   absl::SetFlag(&FLAGS_batch, false);
712 
713   // Expected output:
714   // {
715   //  "message": "Hello0"
716   // }
717   // {
718   //  "message": "Hello2"
719   // }
720   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
721   // "Hello2"\n"
722   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
723                                 "{\n \"message\": \"Hello0\"\n}\n"
724                                 "{\n \"message\": \"Hello2\"\n}\n"));
725 
726   std::cin.rdbuf(orig);
727   ShutdownServer();
728 }
729 
TEST_F(GrpcToolTest,CallCommandBatchJsonInputWithBadRequest)730 TEST_F(GrpcToolTest, CallCommandBatchJsonInputWithBadRequest) {
731   // Test input "grpc_cli call Echo"
732   std::stringstream output_stream;
733 
734   const std::string server_address = SetUpServer();
735   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
736                         "{ \"message\": \"Hello0\"}"};
737 
738   // Mock std::cin input "message: 1\n\n message: 'Hello2'\n\n"
739   std::streambuf* orig = std::cin.rdbuf();
740   std::istringstream ss(
741       "{ \"message\": 1 }\n\n { \"message\": \"Hello2\" }\n\n");
742   std::cin.rdbuf(ss.rdbuf());
743 
744   absl::SetFlag(&FLAGS_batch, true);
745   absl::SetFlag(&FLAGS_json_input, true);
746   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
747                                    std::bind(PrintStream, &output_stream,
748                                              std::placeholders::_1)));
749   absl::SetFlag(&FLAGS_json_input, false);
750   absl::SetFlag(&FLAGS_batch, false);
751 
752   // Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
753   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
754                                 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
755 
756   // with json_output
757   output_stream.str(std::string());
758   output_stream.clear();
759   ss.clear();
760   ss.seekg(0);
761   std::cin.rdbuf(ss.rdbuf());
762 
763   absl::SetFlag(&FLAGS_batch, true);
764   absl::SetFlag(&FLAGS_json_input, true);
765   absl::SetFlag(&FLAGS_json_output, true);
766   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
767                                    std::bind(PrintStream, &output_stream,
768                                              std::placeholders::_1)));
769   absl::SetFlag(&FLAGS_json_output, false);
770   absl::SetFlag(&FLAGS_json_input, false);
771   absl::SetFlag(&FLAGS_batch, false);
772 
773   // Expected output:
774   // {
775   //  "message": "Hello0"
776   // }
777   // {
778   //  "message": "Hello2"
779   // }
780   // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
781   // "Hello2"\n"
782   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
783                                 "{\n \"message\": \"Hello0\"\n}\n"
784                                 "{\n \"message\": \"Hello2\"\n}\n"));
785 
786   std::cin.rdbuf(orig);
787   ShutdownServer();
788 }
789 
TEST_F(GrpcToolTest,CallCommandRequestStream)790 TEST_F(GrpcToolTest, CallCommandRequestStream) {
791   // Test input: grpc_cli call localhost:<port> RequestStream "message:
792   // 'Hello0'"
793   std::stringstream output_stream;
794 
795   const std::string server_address = SetUpServer();
796   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
797                         "RequestStream", "message: 'Hello0'"};
798 
799   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
800   std::streambuf* orig = std::cin.rdbuf();
801   std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
802   std::cin.rdbuf(ss.rdbuf());
803 
804   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
805                                    std::bind(PrintStream, &output_stream,
806                                              std::placeholders::_1)));
807 
808   // Expected output: "message: \"Hello0Hello1Hello2\""
809   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
810                                 "message: \"Hello0Hello1Hello2\""));
811   std::cin.rdbuf(orig);
812   ShutdownServer();
813 }
814 
TEST_F(GrpcToolTest,CallCommandRequestStreamJsonInput)815 TEST_F(GrpcToolTest, CallCommandRequestStreamJsonInput) {
816   // Test input: grpc_cli call localhost:<port> RequestStream "{ \"message\":
817   // \"Hello0\"}"
818   std::stringstream output_stream;
819 
820   const std::string server_address = SetUpServer();
821   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
822                         "RequestStream", "{ \"message\": \"Hello0\" }"};
823 
824   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
825   std::streambuf* orig = std::cin.rdbuf();
826   std::istringstream ss(
827       "{ \"message\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
828   std::cin.rdbuf(ss.rdbuf());
829 
830   absl::SetFlag(&FLAGS_json_input, true);
831   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
832                                    std::bind(PrintStream, &output_stream,
833                                              std::placeholders::_1)));
834   absl::SetFlag(&FLAGS_json_input, false);
835 
836   // Expected output: "message: \"Hello0Hello1Hello2\""
837   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
838                                 "message: \"Hello0Hello1Hello2\""));
839   std::cin.rdbuf(orig);
840   ShutdownServer();
841 }
842 
TEST_F(GrpcToolTest,CallCommandRequestStreamWithBadRequest)843 TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequest) {
844   // Test input: grpc_cli call localhost:<port> RequestStream "message:
845   // 'Hello0'"
846   std::stringstream output_stream;
847 
848   const std::string server_address = SetUpServer();
849   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
850                         "RequestStream", "message: 'Hello0'"};
851 
852   // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
853   std::streambuf* orig = std::cin.rdbuf();
854   std::istringstream ss("bad_field: 'Hello1'\n\n message: 'Hello2'\n\n");
855   std::cin.rdbuf(ss.rdbuf());
856 
857   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
858                                    std::bind(PrintStream, &output_stream,
859                                              std::placeholders::_1)));
860 
861   // Expected output: "message: \"Hello0Hello2\""
862   EXPECT_TRUE(nullptr !=
863               strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
864   std::cin.rdbuf(orig);
865   ShutdownServer();
866 }
867 
TEST_F(GrpcToolTest,CallCommandRequestStreamWithBadRequestJsonInput)868 TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequestJsonInput) {
869   // Test input: grpc_cli call localhost:<port> RequestStream "message:
870   // 'Hello0'"
871   std::stringstream output_stream;
872 
873   const std::string server_address = SetUpServer();
874   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
875                         "RequestStream", "{ \"message\": \"Hello0\" }"};
876 
877   // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
878   std::streambuf* orig = std::cin.rdbuf();
879   std::istringstream ss(
880       "{ \"bad_field\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
881   std::cin.rdbuf(ss.rdbuf());
882 
883   absl::SetFlag(&FLAGS_json_input, true);
884   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
885                                    std::bind(PrintStream, &output_stream,
886                                              std::placeholders::_1)));
887   absl::SetFlag(&FLAGS_json_input, false);
888 
889   // Expected output: "message: \"Hello0Hello2\""
890   EXPECT_TRUE(nullptr !=
891               strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
892   std::cin.rdbuf(orig);
893   ShutdownServer();
894 }
895 
TEST_F(GrpcToolTest,CallCommandWithTimeoutDeadlineSet)896 TEST_F(GrpcToolTest, CallCommandWithTimeoutDeadlineSet) {
897   // Test input "grpc_cli call CheckDeadlineSet --timeout=5000.25"
898   std::stringstream output_stream;
899 
900   const std::string server_address = SetUpServer();
901   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
902                         "CheckDeadlineSet"};
903 
904   // Set timeout to 5000.25 seconds
905   absl::SetFlag(&FLAGS_timeout, 5000.25);
906 
907   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
908                                    std::bind(PrintStream, &output_stream,
909                                              std::placeholders::_1)));
910 
911   // Expected output: "message: "true"", deadline set
912   EXPECT_TRUE(nullptr !=
913               strstr(output_stream.str().c_str(), "message: \"true\""));
914   ShutdownServer();
915 }
916 
TEST_F(GrpcToolTest,CallCommandWithTimeoutDeadlineUpperBound)917 TEST_F(GrpcToolTest, CallCommandWithTimeoutDeadlineUpperBound) {
918   // Test input "grpc_cli call CheckDeadlineUpperBound --timeout=900"
919   std::stringstream output_stream;
920 
921   const std::string server_address = SetUpServer();
922   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
923                         "CheckDeadlineUpperBound"};
924 
925   // Set timeout to 900 seconds
926   absl::SetFlag(&FLAGS_timeout, 900);
927 
928   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
929                                    std::bind(PrintStream, &output_stream,
930                                              std::placeholders::_1)));
931 
932   std::string output = output_stream.str();
933 
934   // Expected output: "message: "true""
935   // deadline not greater than timeout + current time
936   EXPECT_TRUE(nullptr != strstr(output.c_str(), "message: \"true\"")) << output;
937   ShutdownServer();
938 }
939 
TEST_F(GrpcToolTest,CallCommandWithNegativeTimeoutValue)940 TEST_F(GrpcToolTest, CallCommandWithNegativeTimeoutValue) {
941   // Test input "grpc_cli call CheckDeadlineSet --timeout=-5"
942   std::stringstream output_stream;
943 
944   const std::string server_address = SetUpServer();
945   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
946                         "CheckDeadlineSet"};
947 
948   // Set timeout to -5 (deadline not set)
949   absl::SetFlag(&FLAGS_timeout, -5);
950 
951   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
952                                    std::bind(PrintStream, &output_stream,
953                                              std::placeholders::_1)));
954 
955   // Expected output: "message: "false"", deadline not set
956   EXPECT_TRUE(nullptr !=
957               strstr(output_stream.str().c_str(), "message: \"false\""));
958 
959   ShutdownServer();
960 }
961 
TEST_F(GrpcToolTest,CallCommandWithDefaultTimeoutValue)962 TEST_F(GrpcToolTest, CallCommandWithDefaultTimeoutValue) {
963   // Test input "grpc_cli call CheckDeadlineSet --timeout=-1"
964   std::stringstream output_stream;
965 
966   const std::string server_address = SetUpServer();
967   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
968                         "CheckDeadlineSet"};
969 
970   // Set timeout to -1 (default value, deadline not set)
971   absl::SetFlag(&FLAGS_timeout, -1);
972 
973   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
974                                    std::bind(PrintStream, &output_stream,
975                                              std::placeholders::_1)));
976 
977   // Expected output: "message: "false"", deadline not set
978   EXPECT_TRUE(nullptr !=
979               strstr(output_stream.str().c_str(), "message: \"false\""));
980 
981   ShutdownServer();
982 }
983 
TEST_F(GrpcToolTest,CallCommandResponseStream)984 TEST_F(GrpcToolTest, CallCommandResponseStream) {
985   // Test input: grpc_cli call localhost:<port> ResponseStream "message:
986   // 'Hello'"
987   std::stringstream output_stream;
988 
989   const std::string server_address = SetUpServer();
990   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
991                         "ResponseStream", "message: 'Hello'"};
992 
993   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
994                                    std::bind(PrintStream, &output_stream,
995                                              std::placeholders::_1)));
996 
997   // Expected output: "message: \"Hello{n}\""
998   for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
999     std::string expected_response_text =
1000         "message: \"Hello" + std::to_string(i) + "\"\n";
1001     EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
1002                                   expected_response_text.c_str()));
1003   }
1004 
1005   // with json_output
1006   output_stream.str(std::string());
1007   output_stream.clear();
1008 
1009   absl::SetFlag(&FLAGS_json_output, true);
1010   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1011                                    std::bind(PrintStream, &output_stream,
1012                                              std::placeholders::_1)));
1013   absl::SetFlag(&FLAGS_json_output, false);
1014 
1015   // Expected output: "{\n \"message\": \"Hello{n}\"\n}\n"
1016   for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
1017     std::string expected_response_text =
1018         "{\n \"message\": \"Hello" + std::to_string(i) + "\"\n}\n";
1019     EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
1020                                   expected_response_text.c_str()));
1021   }
1022 
1023   ShutdownServer();
1024 }
1025 
TEST_F(GrpcToolTest,CallCommandBidiStream)1026 TEST_F(GrpcToolTest, CallCommandBidiStream) {
1027   // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
1028   std::stringstream output_stream;
1029 
1030   const std::string server_address = SetUpServer();
1031   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1032                         "BidiStream", "message: 'Hello0'"};
1033 
1034   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
1035   std::streambuf* orig = std::cin.rdbuf();
1036   std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
1037   std::cin.rdbuf(ss.rdbuf());
1038 
1039   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1040                                    std::bind(PrintStream, &output_stream,
1041                                              std::placeholders::_1)));
1042 
1043   // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
1044   // \"Hello2\"\n\n"
1045   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
1046                                 "message: \"Hello0\"\nmessage: "
1047                                 "\"Hello1\"\nmessage: \"Hello2\"\n"));
1048   std::cin.rdbuf(orig);
1049   ShutdownServer();
1050 }
1051 
TEST_F(GrpcToolTest,CallCommandBidiStreamWithBadRequest)1052 TEST_F(GrpcToolTest, CallCommandBidiStreamWithBadRequest) {
1053   // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
1054   std::stringstream output_stream;
1055 
1056   const std::string server_address = SetUpServer();
1057   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1058                         "BidiStream", "message: 'Hello0'"};
1059 
1060   // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
1061   std::streambuf* orig = std::cin.rdbuf();
1062   std::istringstream ss("message: 1.0\n\n message: 'Hello2'\n\n");
1063   std::cin.rdbuf(ss.rdbuf());
1064 
1065   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1066                                    std::bind(PrintStream, &output_stream,
1067                                              std::placeholders::_1)));
1068 
1069   // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
1070   // \"Hello2\"\n\n"
1071   EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
1072                                 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
1073   std::cin.rdbuf(orig);
1074 
1075   ShutdownServer();
1076 }
1077 
TEST_F(GrpcToolTest,ParseCommand)1078 TEST_F(GrpcToolTest, ParseCommand) {
1079   // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
1080   // ECHO_RESPONSE_MESSAGE"
1081   std::stringstream output_stream;
1082   std::stringstream binary_output_stream;
1083 
1084   const std::string server_address = SetUpServer();
1085   const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
1086                         "grpc.testing.EchoResponse",
1087                         ECHO_RESPONSE_MESSAGE_TEXT_FORMAT};
1088 
1089   absl::SetFlag(&FLAGS_binary_input, false);
1090   absl::SetFlag(&FLAGS_binary_output, false);
1091   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1092                                    std::bind(PrintStream, &output_stream,
1093                                              std::placeholders::_1)));
1094   // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
1095   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1096                           ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
1097 
1098   // with json_output
1099   output_stream.str(std::string());
1100   output_stream.clear();
1101 
1102   absl::SetFlag(&FLAGS_json_output, true);
1103   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1104                                    std::bind(PrintStream, &output_stream,
1105                                              std::placeholders::_1)));
1106   absl::SetFlag(&FLAGS_json_output, false);
1107 
1108   // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
1109   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1110                           ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
1111 
1112   // Parse text message to binary message and then parse it back to text message
1113   output_stream.str(std::string());
1114   output_stream.clear();
1115   absl::SetFlag(&FLAGS_binary_output, true);
1116   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1117                                    std::bind(PrintStream, &output_stream,
1118                                              std::placeholders::_1)));
1119   std::string binary_data = output_stream.str();
1120   output_stream.str(std::string());
1121   output_stream.clear();
1122   argv[4] = binary_data.c_str();
1123   absl::SetFlag(&FLAGS_binary_input, true);
1124   absl::SetFlag(&FLAGS_binary_output, false);
1125   EXPECT_TRUE(0 == GrpcToolMainLib(5, argv, TestCliCredentials(),
1126                                    std::bind(PrintStream, &output_stream,
1127                                              std::placeholders::_1)));
1128 
1129   // Expected output: ECHO_RESPONSE_MESSAGE
1130   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1131                           ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
1132 
1133   absl::SetFlag(&FLAGS_binary_input, false);
1134   absl::SetFlag(&FLAGS_binary_output, false);
1135   ShutdownServer();
1136 }
1137 
TEST_F(GrpcToolTest,ParseCommandJsonFormat)1138 TEST_F(GrpcToolTest, ParseCommandJsonFormat) {
1139   // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
1140   // ECHO_RESPONSE_MESSAGE_JSON_FORMAT"
1141   std::stringstream output_stream;
1142   std::stringstream binary_output_stream;
1143 
1144   const std::string server_address = SetUpServer();
1145   const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
1146                         "grpc.testing.EchoResponse",
1147                         ECHO_RESPONSE_MESSAGE_JSON_FORMAT};
1148 
1149   absl::SetFlag(&FLAGS_json_input, true);
1150   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1151                                    std::bind(PrintStream, &output_stream,
1152                                              std::placeholders::_1)));
1153 
1154   // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
1155   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1156                           ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
1157 
1158   // with json_output
1159   output_stream.str(std::string());
1160   output_stream.clear();
1161 
1162   absl::SetFlag(&FLAGS_json_output, true);
1163   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1164                                    std::bind(PrintStream, &output_stream,
1165                                              std::placeholders::_1)));
1166   absl::SetFlag(&FLAGS_json_output, false);
1167   absl::SetFlag(&FLAGS_json_input, false);
1168 
1169   // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
1170   EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1171                           ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
1172 
1173   ShutdownServer();
1174 }
1175 
TEST_F(GrpcToolTest,TooFewArguments)1176 TEST_F(GrpcToolTest, TooFewArguments) {
1177   // Test input "grpc_cli call Echo"
1178   std::stringstream output_stream;
1179   const char* argv[] = {"grpc_cli", "call", "Echo"};
1180 
1181   // Exit with 1
1182   EXPECT_EXIT(
1183       GrpcToolMainLib(
1184           ArraySize(argv), argv, TestCliCredentials(),
1185           std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1186       ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
1187   // No output
1188   EXPECT_TRUE(0 == output_stream.tellp());
1189 }
1190 
TEST_F(GrpcToolTest,TooManyArguments)1191 TEST_F(GrpcToolTest, TooManyArguments) {
1192   // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
1193   std::stringstream output_stream;
1194   const char* argv[] = {"grpc_cli", "call", "localhost:10000",
1195                         "Echo",     "Echo", "message: 'Hello'"};
1196 
1197   // Exit with 1
1198   EXPECT_EXIT(
1199       GrpcToolMainLib(
1200           ArraySize(argv), argv, TestCliCredentials(),
1201           std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1202       ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
1203   // No output
1204   EXPECT_TRUE(0 == output_stream.tellp());
1205 }
1206 
TEST_F(GrpcToolTest,CallCommandWithMetadata)1207 TEST_F(GrpcToolTest, CallCommandWithMetadata) {
1208   // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
1209   const std::string server_address = SetUpServer();
1210   const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
1211                         "message: 'Hello'"};
1212 
1213   {
1214     std::stringstream output_stream;
1215     absl::SetFlag(&FLAGS_metadata, "key0:val0:key1:valq:key2:val2");
1216     EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1217                                      TestCliCredentials(),
1218                                      std::bind(PrintStream, &output_stream,
1219                                                std::placeholders::_1)));
1220     // Expected output: "message: \"Hello\""
1221     EXPECT_TRUE(nullptr !=
1222                 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1223   }
1224 
1225   {
1226     std::stringstream output_stream;
1227     absl::SetFlag(&FLAGS_metadata, "key:val\\:val");
1228     EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1229                                      TestCliCredentials(),
1230                                      std::bind(PrintStream, &output_stream,
1231                                                std::placeholders::_1)));
1232     // Expected output: "message: \"Hello\""
1233     EXPECT_TRUE(nullptr !=
1234                 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1235   }
1236 
1237   {
1238     std::stringstream output_stream;
1239     absl::SetFlag(&FLAGS_metadata, "key:val\\\\val");
1240     EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1241                                      TestCliCredentials(),
1242                                      std::bind(PrintStream, &output_stream,
1243                                                std::placeholders::_1)));
1244     // Expected output: "message: \"Hello\""
1245     EXPECT_TRUE(nullptr !=
1246                 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1247   }
1248 
1249   absl::SetFlag(&FLAGS_metadata, "");
1250   ShutdownServer();
1251 }
1252 
TEST_F(GrpcToolTest,CallCommandWithBadMetadata)1253 TEST_F(GrpcToolTest, CallCommandWithBadMetadata) {
1254   // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'"
1255   const char* argv[] = {"grpc_cli", "call", "localhost:10000",
1256                         "grpc.testing.EchoTestService.Echo",
1257                         "message: 'Hello'"};
1258   absl::SetFlag(&FLAGS_protofiles, "src/proto/grpc/testing/echo.proto");
1259   auto test_srcdir = grpc_core::GetEnv("TEST_SRCDIR");
1260   if (test_srcdir.has_value()) {
1261     absl::SetFlag(&FLAGS_proto_path,
1262                   *test_srcdir + std::string("/com_github_grpc_grpc"));
1263   }
1264 
1265   {
1266     std::stringstream output_stream;
1267     absl::SetFlag(&FLAGS_metadata, "key0:val0:key1");
1268     // Exit with 1
1269     EXPECT_EXIT(
1270         GrpcToolMainLib(
1271             ArraySize(argv), argv, TestCliCredentials(),
1272             std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1273         ::testing::ExitedWithCode(1), ".*Failed to parse metadata flag.*");
1274   }
1275 
1276   {
1277     std::stringstream output_stream;
1278     absl::SetFlag(&FLAGS_metadata, "key:val\\val");
1279     // Exit with 1
1280     EXPECT_EXIT(
1281         GrpcToolMainLib(
1282             ArraySize(argv), argv, TestCliCredentials(),
1283             std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1284         ::testing::ExitedWithCode(1), ".*Failed to parse metadata flag.*");
1285   }
1286 
1287   absl::SetFlag(&FLAGS_metadata, "");
1288   absl::SetFlag(&FLAGS_protofiles, "");
1289 }
1290 
TEST_F(GrpcToolTest,CallMaxRecvMessageSizeSmall)1291 TEST_F(GrpcToolTest, CallMaxRecvMessageSizeSmall) {
1292   std::stringstream output_stream;
1293   const std::string server_address = SetUpServer();
1294   // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'
1295   // --max_recv_msg_size=4"
1296   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1297                         "grpc.testing.EchoTestService.Echo",
1298                         "message: 'Hello'"};
1299 
1300   // Set max_recv_msg_size to 4 which is not enough.
1301   absl::SetFlag(&FLAGS_max_recv_msg_size, 4);
1302 
1303   // This should fail.
1304   EXPECT_FALSE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1305                                     std::bind(PrintStream, &output_stream,
1306                                               std::placeholders::_1)));
1307   // No output expected.
1308   EXPECT_TRUE(0 == output_stream.tellp());
1309   ShutdownServer();
1310 }
1311 
TEST_F(GrpcToolTest,CallMaxRecvMessageSizeEnough)1312 TEST_F(GrpcToolTest, CallMaxRecvMessageSizeEnough) {
1313   std::stringstream output_stream;
1314   const std::string server_address = SetUpServer();
1315   // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'
1316   // --max_recv_msg_size=1048576"
1317   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1318                         "grpc.testing.EchoTestService.Echo",
1319                         "message: 'Hello'"};
1320 
1321   // Set max_recv_msg_size to a large enough number.
1322   absl::SetFlag(&FLAGS_max_recv_msg_size, 1024 * 1024);
1323 
1324   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1325                                    std::bind(PrintStream, &output_stream,
1326                                              std::placeholders::_1)));
1327   // Expected output: "message: \"Hello\""
1328   EXPECT_TRUE(nullptr !=
1329               strstr(output_stream.str().c_str(), "message: \"Hello\""));
1330   ShutdownServer();
1331 }
1332 
TEST_F(GrpcToolTest,CallMaxRecvMessageSizeDefault)1333 TEST_F(GrpcToolTest, CallMaxRecvMessageSizeDefault) {
1334   std::stringstream output_stream;
1335   const std::string server_address = SetUpServer();
1336   // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'
1337   // --max_recv_msg_size=0"
1338   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1339                         "grpc.testing.EchoTestService.Echo",
1340                         "message: 'Hello'"};
1341 
1342   // Set max_recv_msg_size to gRPC default, which should suffice.
1343   absl::SetFlag(&FLAGS_max_recv_msg_size, 0);
1344 
1345   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1346                                    std::bind(PrintStream, &output_stream,
1347                                              std::placeholders::_1)));
1348   // Expected output: "message: \"Hello\""
1349   EXPECT_TRUE(nullptr !=
1350               strstr(output_stream.str().c_str(), "message: \"Hello\""));
1351   ShutdownServer();
1352 }
1353 
TEST_F(GrpcToolTest,CallMaxRecvMessageSizeUnlimited)1354 TEST_F(GrpcToolTest, CallMaxRecvMessageSizeUnlimited) {
1355   std::stringstream output_stream;
1356   const std::string server_address = SetUpServer();
1357   // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'
1358   // --max_recv_msg_size=-1"
1359   const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
1360                         "grpc.testing.EchoTestService.Echo",
1361                         "message: 'Hello'"};
1362 
1363   // Set max_recv_msg_size to unlimited (-1), which should work.
1364   absl::SetFlag(&FLAGS_max_recv_msg_size, -1);
1365 
1366   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1367                                    std::bind(PrintStream, &output_stream,
1368                                              std::placeholders::_1)));
1369   // Expected output: "message: \"Hello\""
1370   EXPECT_TRUE(nullptr !=
1371               strstr(output_stream.str().c_str(), "message: \"Hello\""));
1372   ShutdownServer();
1373 }
1374 
TEST_F(GrpcToolTest,ListCommandOverrideSslHostName)1375 TEST_F(GrpcToolTest, ListCommandOverrideSslHostName) {
1376   const std::string server_address = SetUpServer(true);
1377 
1378   // Test input "grpc_cli ls localhost:<port> --channel_creds_type=ssl
1379   // --ssl_target=z.test.google.fr"
1380   std::stringstream output_stream;
1381   const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
1382   absl::SetFlag(&FLAGS_l, false);
1383   absl::SetFlag(&FLAGS_channel_creds_type, "ssl");
1384   absl::SetFlag(&FLAGS_ssl_target, "z.test.google.fr");
1385   EXPECT_TRUE(
1386       0 == GrpcToolMainLib(
1387                ArraySize(argv), argv, TestCliCredentials(true),
1388                std::bind(PrintStream, &output_stream, std::placeholders::_1)));
1389   EXPECT_THAT(
1390       absl::StrSplit(output_stream.str(), '\n'),
1391       ::testing::UnorderedElementsAre(
1392           "grpc.testing.EchoTestService", "grpc.reflection.v1.ServerReflection",
1393           "grpc.reflection.v1alpha.ServerReflection", ""));
1394 
1395   absl::SetFlag(&FLAGS_channel_creds_type, "");
1396   absl::SetFlag(&FLAGS_ssl_target, "");
1397   ShutdownServer();
1398 }
1399 
TEST_F(GrpcToolTest,ConfiguringDefaultServiceConfig)1400 TEST_F(GrpcToolTest, ConfiguringDefaultServiceConfig) {
1401   // Test input "grpc_cli list localhost:<port>
1402   // --default_service_config={\"loadBalancingConfig\":[{\"pick_first\":{}}]}"
1403   std::stringstream output_stream;
1404   const std::string server_address = SetUpServer();
1405   const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
1406   // Just check that the tool is still operational when --default_service_config
1407   // is configured. This particular service config is in reality redundant with
1408   // the channel's default configuration.
1409   absl::SetFlag(&FLAGS_l, false);
1410   absl::SetFlag(&FLAGS_default_service_config,
1411                 "{\"loadBalancingConfig\":[{\"pick_first\":{}}]}");
1412   EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1413                                    std::bind(PrintStream, &output_stream,
1414                                              std::placeholders::_1)));
1415   absl::SetFlag(&FLAGS_default_service_config, "");
1416   EXPECT_THAT(
1417       absl::StrSplit(output_stream.str().c_str(), '\n'),
1418       ::testing::UnorderedElementsAre(
1419           "grpc.testing.EchoTestService", "grpc.reflection.v1.ServerReflection",
1420           "grpc.reflection.v1alpha.ServerReflection", ""));
1421   ShutdownServer();
1422 }
1423 
1424 }  // namespace testing
1425 }  // namespace grpc
1426 
main(int argc,char ** argv)1427 int main(int argc, char** argv) {
1428   grpc::testing::TestEnvironment env(&argc, argv);
1429   ::testing::InitGoogleTest(&argc, argv);
1430   GTEST_FLAG_SET(death_test_style, "threadsafe");
1431   return RUN_ALL_TESTS();
1432 }
1433