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