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