3 * Copyright 2016 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "test/cpp/util/grpc_tool.h"
23 #include <gflags/gflags.h>
24 #include <grpc/grpc.h>
25 #include <grpc/support/alloc.h>
26 #include <grpcpp/channel.h>
27 #include <grpcpp/client_context.h>
28 #include <grpcpp/create_channel.h>
29 #include <grpcpp/ext/proto_server_reflection_plugin.h>
30 #include <grpcpp/server.h>
31 #include <grpcpp/server_builder.h>
32 #include <grpcpp/server_context.h>
33 #include <gtest/gtest.h>
35 #include "src/core/lib/gpr/env.h"
36 #include "src/proto/grpc/testing/echo.grpc.pb.h"
37 #include "src/proto/grpc/testing/echo.pb.h"
38 #include "test/core/end2end/data/ssl_test_data.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"
44 using grpc::testing::EchoRequest;
45 using grpc::testing::EchoResponse;
47 #define USAGE_REGEX "( grpc_cli .+\n){2,10}"
49 #define ECHO_TEST_SERVICE_SUMMARY \
51 "CheckClientInitialMetadata\n" \
57 #define ECHO_TEST_SERVICE_DESCRIPTION \
58 "filename: src/proto/grpc/testing/echo.proto\n" \
59 "package: grpc.testing;\n" \
60 "service EchoTestService {\n" \
61 " rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
63 " rpc CheckClientInitialMetadata(grpc.testing.SimpleRequest) returns " \
64 "(grpc.testing.SimpleResponse) {}\n" \
65 " rpc RequestStream(stream grpc.testing.EchoRequest) returns " \
66 "(grpc.testing.EchoResponse) {}\n" \
67 " rpc ResponseStream(grpc.testing.EchoRequest) returns (stream " \
68 "grpc.testing.EchoResponse) {}\n" \
69 " rpc BidiStream(stream grpc.testing.EchoRequest) returns (stream " \
70 "grpc.testing.EchoResponse) {}\n" \
71 " rpc Unimplemented(grpc.testing.EchoRequest) returns " \
72 "(grpc.testing.EchoResponse) {}\n" \
76 #define ECHO_METHOD_DESCRIPTION \
77 " rpc Echo(grpc.testing.EchoRequest) returns (grpc.testing.EchoResponse) " \
80 #define ECHO_RESPONSE_MESSAGE_TEXT_FORMAT \
81 "message: \"echo\"\n" \
83 " host: \"localhost\"\n" \
87 #define ECHO_RESPONSE_MESSAGE_JSON_FORMAT \
89 " \"message\": \"echo\",\n" \
91 " \"host\": \"localhost\",\n" \
92 " \"peer\": \"peer\"\n" \
96 DECLARE_string(channel_creds_type);
97 DECLARE_string(ssl_target);
102 DECLARE_bool(binary_input);
103 DECLARE_bool(binary_output);
104 DECLARE_bool(json_input);
105 DECLARE_bool(json_output);
108 DECLARE_string(metadata);
109 DECLARE_string(protofiles);
110 DECLARE_string(proto_path);
114 const int kServerDefaultResponseStreamsToSend = 3;
116 class TestCliCredentials final : public grpc::testing::CliCredentials {
118 TestCliCredentials(bool secure = false) : secure_(secure) {}
119 std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials()
122 return InsecureChannelCredentials();
124 SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
125 return SslCredentials(grpc::SslCredentialsOptions(ssl_opts));
127 const grpc::string GetCredentialUsage() const override { return ""; }
133 bool PrintStream(std::stringstream* ss, const grpc::string& output) {
138 template <typename T>
139 size_t ArraySize(T& a) {
140 return ((sizeof(a) / sizeof(*(a))) /
141 static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
144 class TestServiceImpl : public ::grpc::testing::EchoTestService::Service {
146 Status Echo(ServerContext* context, const EchoRequest* request,
147 EchoResponse* response) override {
148 if (!context->client_metadata().empty()) {
149 for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
150 iter = context->client_metadata().begin();
151 iter != context->client_metadata().end(); ++iter) {
152 context->AddInitialMetadata(ToString(iter->first),
153 ToString(iter->second));
156 context->AddTrailingMetadata("trailing_key", "trailing_value");
157 response->set_message(request->message());
161 Status RequestStream(ServerContext* context,
162 ServerReader<EchoRequest>* reader,
163 EchoResponse* response) override {
165 response->set_message("");
166 if (!context->client_metadata().empty()) {
167 for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
168 iter = context->client_metadata().begin();
169 iter != context->client_metadata().end(); ++iter) {
170 context->AddInitialMetadata(ToString(iter->first),
171 ToString(iter->second));
174 context->AddTrailingMetadata("trailing_key", "trailing_value");
175 while (reader->Read(&request)) {
176 response->mutable_message()->append(request.message());
182 Status ResponseStream(ServerContext* context, const EchoRequest* request,
183 ServerWriter<EchoResponse>* writer) override {
184 if (!context->client_metadata().empty()) {
185 for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
186 iter = context->client_metadata().begin();
187 iter != context->client_metadata().end(); ++iter) {
188 context->AddInitialMetadata(ToString(iter->first),
189 ToString(iter->second));
192 context->AddTrailingMetadata("trailing_key", "trailing_value");
194 EchoResponse response;
195 for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
196 response.set_message(request->message() + grpc::to_string(i));
197 writer->Write(response);
204 ServerContext* context,
205 ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
207 EchoResponse response;
208 if (!context->client_metadata().empty()) {
209 for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
210 iter = context->client_metadata().begin();
211 iter != context->client_metadata().end(); ++iter) {
212 context->AddInitialMetadata(ToString(iter->first),
213 ToString(iter->second));
216 context->AddTrailingMetadata("trailing_key", "trailing_value");
218 while (stream->Read(&request)) {
219 response.set_message(request.message());
220 stream->Write(response);
229 class GrpcToolTest : public ::testing::Test {
233 // SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
234 // uses atexit() to free chosen ports, and it will spawn a new thread in
235 // resolve_address_posix.c:192 at exit time.
236 const grpc::string SetUpServer(bool secure = false) {
237 std::ostringstream server_address;
238 int port = grpc_pick_unused_port_or_die();
239 server_address << "localhost:" << port;
241 ServerBuilder builder;
242 std::shared_ptr<grpc::ServerCredentials> creds;
244 SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
246 SslServerCredentialsOptions ssl_opts;
247 ssl_opts.pem_root_certs = "";
248 ssl_opts.pem_key_cert_pairs.push_back(pkcp);
249 creds = SslServerCredentials(ssl_opts);
251 creds = InsecureServerCredentials();
253 builder.AddListeningPort(server_address.str(), creds);
254 builder.RegisterService(&service_);
255 server_ = builder.BuildAndStart();
256 return server_address.str();
259 void ShutdownServer() { server_->Shutdown(); }
261 std::unique_ptr<Server> server_;
262 TestServiceImpl service_;
263 reflection::ProtoServerReflectionPlugin plugin_;
266 TEST_F(GrpcToolTest, NoCommand) {
267 // Test input "grpc_cli"
268 std::stringstream output_stream;
269 const char* argv[] = {"grpc_cli"};
270 // Exit with 1, print usage instruction in stderr
273 ArraySize(argv), argv, TestCliCredentials(),
274 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
275 ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
277 EXPECT_TRUE(0 == output_stream.tellp());
280 TEST_F(GrpcToolTest, InvalidCommand) {
281 // Test input "grpc_cli"
282 std::stringstream output_stream;
283 const char* argv[] = {"grpc_cli", "abc"};
284 // Exit with 1, print usage instruction in stderr
287 ArraySize(argv), argv, TestCliCredentials(),
288 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
289 ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
291 EXPECT_TRUE(0 == output_stream.tellp());
294 TEST_F(GrpcToolTest, HelpCommand) {
295 // Test input "grpc_cli help"
296 std::stringstream output_stream;
297 const char* argv[] = {"grpc_cli", "help"};
298 // Exit with 1, print usage instruction in stderr
299 EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
300 std::bind(PrintStream, &output_stream,
301 std::placeholders::_1)),
302 ::testing::ExitedWithCode(1), USAGE_REGEX);
304 EXPECT_TRUE(0 == output_stream.tellp());
307 TEST_F(GrpcToolTest, ListCommand) {
308 // Test input "grpc_cli list localhost:<port>"
309 std::stringstream output_stream;
311 const grpc::string server_address = SetUpServer();
312 const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
315 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
316 std::bind(PrintStream, &output_stream,
317 std::placeholders::_1)));
318 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
319 "grpc.testing.EchoTestService\n"
320 "grpc.reflection.v1alpha.ServerReflection\n"));
325 TEST_F(GrpcToolTest, ListOneService) {
326 // Test input "grpc_cli list localhost:<port> grpc.testing.EchoTestService"
327 std::stringstream output_stream;
329 const grpc::string server_address = SetUpServer();
330 const char* argv[] = {"grpc_cli", "ls", server_address.c_str(),
331 "grpc.testing.EchoTestService"};
334 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
335 std::bind(PrintStream, &output_stream,
336 std::placeholders::_1)));
337 // Expected output: ECHO_TEST_SERVICE_SUMMARY
339 strcmp(output_stream.str().c_str(), ECHO_TEST_SERVICE_SUMMARY));
342 output_stream.str(grpc::string());
343 output_stream.clear();
345 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
346 std::bind(PrintStream, &output_stream,
347 std::placeholders::_1)));
348 // Expected output: ECHO_TEST_SERVICE_DESCRIPTION
350 0 == strcmp(output_stream.str().c_str(), ECHO_TEST_SERVICE_DESCRIPTION));
355 TEST_F(GrpcToolTest, TypeCommand) {
356 // Test input "grpc_cli type localhost:<port> grpc.testing.EchoRequest"
357 std::stringstream output_stream;
359 const grpc::string server_address = SetUpServer();
360 const char* argv[] = {"grpc_cli", "type", server_address.c_str(),
361 "grpc.testing.EchoRequest"};
363 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
364 std::bind(PrintStream, &output_stream,
365 std::placeholders::_1)));
366 const grpc::protobuf::Descriptor* desc =
367 grpc::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
368 "grpc.testing.EchoRequest");
369 // Expected output: the DebugString of grpc.testing.EchoRequest
371 strcmp(output_stream.str().c_str(), desc->DebugString().c_str()));
376 TEST_F(GrpcToolTest, ListOneMethod) {
377 // Test input "grpc_cli list localhost:<port> grpc.testing.EchoTestService"
378 std::stringstream output_stream;
380 const grpc::string server_address = SetUpServer();
381 const char* argv[] = {"grpc_cli", "ls", server_address.c_str(),
382 "grpc.testing.EchoTestService.Echo"};
385 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
386 std::bind(PrintStream, &output_stream,
387 std::placeholders::_1)));
388 // Expected output: "Echo"
389 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(), "Echo\n"));
392 output_stream.str(grpc::string());
393 output_stream.clear();
395 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
396 std::bind(PrintStream, &output_stream,
397 std::placeholders::_1)));
398 // Expected output: ECHO_METHOD_DESCRIPTION
400 strcmp(output_stream.str().c_str(), ECHO_METHOD_DESCRIPTION));
405 TEST_F(GrpcToolTest, TypeNotFound) {
406 // Test input "grpc_cli type localhost:<port> grpc.testing.DummyRequest"
407 std::stringstream output_stream;
409 const grpc::string server_address = SetUpServer();
410 const char* argv[] = {"grpc_cli", "type", server_address.c_str(),
411 "grpc.testing.DummyRequest"};
413 EXPECT_TRUE(1 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
414 std::bind(PrintStream, &output_stream,
415 std::placeholders::_1)));
419 TEST_F(GrpcToolTest, CallCommand) {
420 // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
421 std::stringstream output_stream;
423 const grpc::string server_address = SetUpServer();
424 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
427 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
428 std::bind(PrintStream, &output_stream,
429 std::placeholders::_1)));
430 // Expected output: "message: \"Hello\""
431 EXPECT_TRUE(nullptr !=
432 strstr(output_stream.str().c_str(), "message: \"Hello\""));
435 output_stream.str(grpc::string());
436 output_stream.clear();
438 FLAGS_json_output = true;
439 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
440 std::bind(PrintStream, &output_stream,
441 std::placeholders::_1)));
442 FLAGS_json_output = false;
446 // "message": "Hello"
448 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
449 "{\n \"message\": \"Hello\"\n}"));
454 TEST_F(GrpcToolTest, CallCommandJsonInput) {
455 // Test input "grpc_cli call localhost:<port> Echo "{ \"message\": \"Hello\"}"
456 std::stringstream output_stream;
458 const grpc::string server_address = SetUpServer();
459 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
460 "{ \"message\": \"Hello\"}"};
462 FLAGS_json_input = true;
463 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
464 std::bind(PrintStream, &output_stream,
465 std::placeholders::_1)));
466 // Expected output: "message: \"Hello\""
467 EXPECT_TRUE(nullptr !=
468 strstr(output_stream.str().c_str(), "message: \"Hello\""));
471 output_stream.str(grpc::string());
472 output_stream.clear();
474 FLAGS_json_output = true;
475 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
476 std::bind(PrintStream, &output_stream,
477 std::placeholders::_1)));
478 FLAGS_json_output = false;
479 FLAGS_json_input = false;
483 // "message": "Hello"
485 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
486 "{\n \"message\": \"Hello\"\n}"));
491 TEST_F(GrpcToolTest, CallCommandBatch) {
492 // Test input "grpc_cli call Echo"
493 std::stringstream output_stream;
495 const grpc::string server_address = SetUpServer();
496 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
497 "message: 'Hello0'"};
499 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
500 std::streambuf* orig = std::cin.rdbuf();
501 std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
502 std::cin.rdbuf(ss.rdbuf());
505 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
506 std::bind(PrintStream, &output_stream,
507 std::placeholders::_1)));
510 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
512 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
513 "message: \"Hello0\"\nmessage: "
514 "\"Hello1\"\nmessage: \"Hello2\"\n"));
516 output_stream.str(grpc::string());
517 output_stream.clear();
520 std::cin.rdbuf(ss.rdbuf());
523 FLAGS_json_output = true;
524 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
525 std::bind(PrintStream, &output_stream,
526 std::placeholders::_1)));
527 FLAGS_json_output = false;
532 // "message": "Hello0"
535 // "message": "Hello1"
538 // "message": "Hello2"
540 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
542 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
543 "{\n \"message\": \"Hello0\"\n}\n"
544 "{\n \"message\": \"Hello1\"\n}\n"
545 "{\n \"message\": \"Hello2\"\n}\n"));
547 std::cin.rdbuf(orig);
551 TEST_F(GrpcToolTest, CallCommandBatchJsonInput) {
552 // Test input "grpc_cli call Echo"
553 std::stringstream output_stream;
555 const grpc::string server_address = SetUpServer();
556 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
557 "{\"message\": \"Hello0\"}"};
559 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
560 std::streambuf* orig = std::cin.rdbuf();
561 std::istringstream ss(
562 "{\"message\": \"Hello1\"}\n\n{\"message\": \"Hello2\" }\n\n");
563 std::cin.rdbuf(ss.rdbuf());
565 FLAGS_json_input = true;
567 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
568 std::bind(PrintStream, &output_stream,
569 std::placeholders::_1)));
572 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
574 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
575 "message: \"Hello0\"\nmessage: "
576 "\"Hello1\"\nmessage: \"Hello2\"\n"));
578 output_stream.str(grpc::string());
579 output_stream.clear();
582 std::cin.rdbuf(ss.rdbuf());
585 FLAGS_json_output = true;
586 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
587 std::bind(PrintStream, &output_stream,
588 std::placeholders::_1)));
589 FLAGS_json_output = false;
591 FLAGS_json_input = false;
595 // "message": "Hello0"
598 // "message": "Hello1"
601 // "message": "Hello2"
603 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
605 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
606 "{\n \"message\": \"Hello0\"\n}\n"
607 "{\n \"message\": \"Hello1\"\n}\n"
608 "{\n \"message\": \"Hello2\"\n}\n"));
610 std::cin.rdbuf(orig);
614 TEST_F(GrpcToolTest, CallCommandBatchWithBadRequest) {
615 // Test input "grpc_cli call Echo"
616 std::stringstream output_stream;
618 const grpc::string server_address = SetUpServer();
619 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
620 "message: 'Hello0'"};
622 // Mock std::cin input "message: 1\n\n message: 'Hello2'\n\n"
623 std::streambuf* orig = std::cin.rdbuf();
624 std::istringstream ss("message: 1\n\n message: 'Hello2'\n\n");
625 std::cin.rdbuf(ss.rdbuf());
628 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
629 std::bind(PrintStream, &output_stream,
630 std::placeholders::_1)));
633 // Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
634 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
635 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
638 output_stream.str(grpc::string());
639 output_stream.clear();
642 std::cin.rdbuf(ss.rdbuf());
645 FLAGS_json_output = true;
646 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
647 std::bind(PrintStream, &output_stream,
648 std::placeholders::_1)));
649 FLAGS_json_output = false;
654 // "message": "Hello0"
657 // "message": "Hello2"
659 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
661 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
662 "{\n \"message\": \"Hello0\"\n}\n"
663 "{\n \"message\": \"Hello2\"\n}\n"));
665 std::cin.rdbuf(orig);
669 TEST_F(GrpcToolTest, CallCommandBatchJsonInputWithBadRequest) {
670 // Test input "grpc_cli call Echo"
671 std::stringstream output_stream;
673 const grpc::string server_address = SetUpServer();
674 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
675 "{ \"message\": \"Hello0\"}"};
677 // Mock std::cin input "message: 1\n\n message: 'Hello2'\n\n"
678 std::streambuf* orig = std::cin.rdbuf();
679 std::istringstream ss(
680 "{ \"message\": 1 }\n\n { \"message\": \"Hello2\" }\n\n");
681 std::cin.rdbuf(ss.rdbuf());
684 FLAGS_json_input = true;
685 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
686 std::bind(PrintStream, &output_stream,
687 std::placeholders::_1)));
688 FLAGS_json_input = false;
691 // Expected output: "message: "Hello0"\nmessage: "Hello2"\n"
692 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
693 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
696 output_stream.str(grpc::string());
697 output_stream.clear();
700 std::cin.rdbuf(ss.rdbuf());
703 FLAGS_json_input = true;
704 FLAGS_json_output = true;
705 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
706 std::bind(PrintStream, &output_stream,
707 std::placeholders::_1)));
708 FLAGS_json_output = false;
709 FLAGS_json_input = false;
714 // "message": "Hello0"
717 // "message": "Hello2"
719 // Expected output: "message: "Hello0"\nmessage: "Hello1"\nmessage:
721 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
722 "{\n \"message\": \"Hello0\"\n}\n"
723 "{\n \"message\": \"Hello2\"\n}\n"));
725 std::cin.rdbuf(orig);
729 TEST_F(GrpcToolTest, CallCommandRequestStream) {
730 // Test input: grpc_cli call localhost:<port> RequestStream "message:
732 std::stringstream output_stream;
734 const grpc::string server_address = SetUpServer();
735 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
736 "RequestStream", "message: 'Hello0'"};
738 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
739 std::streambuf* orig = std::cin.rdbuf();
740 std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
741 std::cin.rdbuf(ss.rdbuf());
743 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
744 std::bind(PrintStream, &output_stream,
745 std::placeholders::_1)));
747 // Expected output: "message: \"Hello0Hello1Hello2\""
748 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
749 "message: \"Hello0Hello1Hello2\""));
750 std::cin.rdbuf(orig);
754 TEST_F(GrpcToolTest, CallCommandRequestStreamJsonInput) {
755 // Test input: grpc_cli call localhost:<port> RequestStream "{ \"message\":
757 std::stringstream output_stream;
759 const grpc::string server_address = SetUpServer();
760 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
761 "RequestStream", "{ \"message\": \"Hello0\" }"};
763 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
764 std::streambuf* orig = std::cin.rdbuf();
765 std::istringstream ss(
766 "{ \"message\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
767 std::cin.rdbuf(ss.rdbuf());
769 FLAGS_json_input = true;
770 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
771 std::bind(PrintStream, &output_stream,
772 std::placeholders::_1)));
773 FLAGS_json_input = false;
775 // Expected output: "message: \"Hello0Hello1Hello2\""
776 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
777 "message: \"Hello0Hello1Hello2\""));
778 std::cin.rdbuf(orig);
782 TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequest) {
783 // Test input: grpc_cli call localhost:<port> RequestStream "message:
785 std::stringstream output_stream;
787 const grpc::string server_address = SetUpServer();
788 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
789 "RequestStream", "message: 'Hello0'"};
791 // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
792 std::streambuf* orig = std::cin.rdbuf();
793 std::istringstream ss("bad_field: 'Hello1'\n\n message: 'Hello2'\n\n");
794 std::cin.rdbuf(ss.rdbuf());
796 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
797 std::bind(PrintStream, &output_stream,
798 std::placeholders::_1)));
800 // Expected output: "message: \"Hello0Hello2\""
801 EXPECT_TRUE(nullptr !=
802 strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
803 std::cin.rdbuf(orig);
807 TEST_F(GrpcToolTest, CallCommandRequestStreamWithBadRequestJsonInput) {
808 // Test input: grpc_cli call localhost:<port> RequestStream "message:
810 std::stringstream output_stream;
812 const grpc::string server_address = SetUpServer();
813 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
814 "RequestStream", "{ \"message\": \"Hello0\" }"};
816 // Mock std::cin input "bad_field: 'Hello1'\n\n message: 'Hello2'\n\n"
817 std::streambuf* orig = std::cin.rdbuf();
818 std::istringstream ss(
819 "{ \"bad_field\": \"Hello1\" }\n\n{ \"message\": \"Hello2\" }\n\n");
820 std::cin.rdbuf(ss.rdbuf());
822 FLAGS_json_input = true;
823 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
824 std::bind(PrintStream, &output_stream,
825 std::placeholders::_1)));
826 FLAGS_json_input = false;
828 // Expected output: "message: \"Hello0Hello2\""
829 EXPECT_TRUE(nullptr !=
830 strstr(output_stream.str().c_str(), "message: \"Hello0Hello2\""));
831 std::cin.rdbuf(orig);
835 TEST_F(GrpcToolTest, CallCommandResponseStream) {
836 // Test input: grpc_cli call localhost:<port> ResponseStream "message:
838 std::stringstream output_stream;
840 const grpc::string server_address = SetUpServer();
841 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
842 "ResponseStream", "message: 'Hello'"};
844 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
845 std::bind(PrintStream, &output_stream,
846 std::placeholders::_1)));
848 // Expected output: "message: \"Hello{n}\""
849 for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
850 grpc::string expected_response_text =
851 "message: \"Hello" + grpc::to_string(i) + "\"\n";
852 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
853 expected_response_text.c_str()));
857 output_stream.str(grpc::string());
858 output_stream.clear();
860 FLAGS_json_output = true;
861 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
862 std::bind(PrintStream, &output_stream,
863 std::placeholders::_1)));
864 FLAGS_json_output = false;
866 // Expected output: "{\n \"message\": \"Hello{n}\"\n}\n"
867 for (int i = 0; i < kServerDefaultResponseStreamsToSend; i++) {
868 grpc::string expected_response_text =
869 "{\n \"message\": \"Hello" + grpc::to_string(i) + "\"\n}\n";
870 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
871 expected_response_text.c_str()));
877 TEST_F(GrpcToolTest, CallCommandBidiStream) {
878 // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
879 std::stringstream output_stream;
881 const grpc::string server_address = SetUpServer();
882 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
883 "BidiStream", "message: 'Hello0'"};
885 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
886 std::streambuf* orig = std::cin.rdbuf();
887 std::istringstream ss("message: 'Hello1'\n\n message: 'Hello2'\n\n");
888 std::cin.rdbuf(ss.rdbuf());
890 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
891 std::bind(PrintStream, &output_stream,
892 std::placeholders::_1)));
894 // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
896 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
897 "message: \"Hello0\"\nmessage: "
898 "\"Hello1\"\nmessage: \"Hello2\"\n"));
899 std::cin.rdbuf(orig);
903 TEST_F(GrpcToolTest, CallCommandBidiStreamWithBadRequest) {
904 // Test input: grpc_cli call localhost:<port> BidiStream "message: 'Hello0'"
905 std::stringstream output_stream;
907 const grpc::string server_address = SetUpServer();
908 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
909 "BidiStream", "message: 'Hello0'"};
911 // Mock std::cin input "message: 'Hello1'\n\n message: 'Hello2'\n\n"
912 std::streambuf* orig = std::cin.rdbuf();
913 std::istringstream ss("message: 1.0\n\n message: 'Hello2'\n\n");
914 std::cin.rdbuf(ss.rdbuf());
916 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
917 std::bind(PrintStream, &output_stream,
918 std::placeholders::_1)));
920 // Expected output: "message: \"Hello0\"\nmessage: \"Hello1\"\nmessage:
922 EXPECT_TRUE(nullptr != strstr(output_stream.str().c_str(),
923 "message: \"Hello0\"\nmessage: \"Hello2\"\n"));
924 std::cin.rdbuf(orig);
929 TEST_F(GrpcToolTest, ParseCommand) {
930 // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
931 // ECHO_RESPONSE_MESSAGE"
932 std::stringstream output_stream;
933 std::stringstream binary_output_stream;
935 const grpc::string server_address = SetUpServer();
936 const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
937 "grpc.testing.EchoResponse",
938 ECHO_RESPONSE_MESSAGE_TEXT_FORMAT};
940 FLAGS_binary_input = false;
941 FLAGS_binary_output = false;
942 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
943 std::bind(PrintStream, &output_stream,
944 std::placeholders::_1)));
945 // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
946 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
947 ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
950 output_stream.str(grpc::string());
951 output_stream.clear();
953 FLAGS_json_output = true;
954 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
955 std::bind(PrintStream, &output_stream,
956 std::placeholders::_1)));
957 FLAGS_json_output = false;
959 // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
960 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
961 ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
963 // Parse text message to binary message and then parse it back to text message
964 output_stream.str(grpc::string());
965 output_stream.clear();
966 FLAGS_binary_output = true;
967 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
968 std::bind(PrintStream, &output_stream,
969 std::placeholders::_1)));
970 grpc::string binary_data = output_stream.str();
971 output_stream.str(grpc::string());
972 output_stream.clear();
973 argv[4] = binary_data.c_str();
974 FLAGS_binary_input = true;
975 FLAGS_binary_output = false;
976 EXPECT_TRUE(0 == GrpcToolMainLib(5, argv, TestCliCredentials(),
977 std::bind(PrintStream, &output_stream,
978 std::placeholders::_1)));
980 // Expected output: ECHO_RESPONSE_MESSAGE
981 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
982 ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
984 FLAGS_binary_input = false;
985 FLAGS_binary_output = false;
989 TEST_F(GrpcToolTest, ParseCommandJsonFormat) {
990 // Test input "grpc_cli parse localhost:<port> grpc.testing.EchoResponse
991 // ECHO_RESPONSE_MESSAGE_JSON_FORMAT"
992 std::stringstream output_stream;
993 std::stringstream binary_output_stream;
995 const grpc::string server_address = SetUpServer();
996 const char* argv[] = {"grpc_cli", "parse", server_address.c_str(),
997 "grpc.testing.EchoResponse",
998 ECHO_RESPONSE_MESSAGE_JSON_FORMAT};
1000 FLAGS_json_input = true;
1001 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1002 std::bind(PrintStream, &output_stream,
1003 std::placeholders::_1)));
1005 // Expected output: ECHO_RESPONSE_MESSAGE_TEXT_FORMAT
1006 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1007 ECHO_RESPONSE_MESSAGE_TEXT_FORMAT));
1010 output_stream.str(grpc::string());
1011 output_stream.clear();
1013 FLAGS_json_output = true;
1014 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
1015 std::bind(PrintStream, &output_stream,
1016 std::placeholders::_1)));
1017 FLAGS_json_output = false;
1018 FLAGS_json_input = false;
1020 // Expected output: ECHO_RESPONSE_MESSAGE_JSON_FORMAT
1021 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1022 ECHO_RESPONSE_MESSAGE_JSON_FORMAT));
1027 TEST_F(GrpcToolTest, TooFewArguments) {
1028 // Test input "grpc_cli call Echo"
1029 std::stringstream output_stream;
1030 const char* argv[] = {"grpc_cli", "call", "Echo"};
1035 ArraySize(argv), argv, TestCliCredentials(),
1036 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1037 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
1039 EXPECT_TRUE(0 == output_stream.tellp());
1042 TEST_F(GrpcToolTest, TooManyArguments) {
1043 // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
1044 std::stringstream output_stream;
1045 const char* argv[] = {"grpc_cli", "call", "localhost:10000",
1046 "Echo", "Echo", "message: 'Hello'"};
1051 ArraySize(argv), argv, TestCliCredentials(),
1052 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1053 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
1055 EXPECT_TRUE(0 == output_stream.tellp());
1058 TEST_F(GrpcToolTest, CallCommandWithMetadata) {
1059 // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
1060 const grpc::string server_address = SetUpServer();
1061 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
1062 "message: 'Hello'"};
1065 std::stringstream output_stream;
1066 FLAGS_metadata = "key0:val0:key1:valq:key2:val2";
1067 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1068 TestCliCredentials(),
1069 std::bind(PrintStream, &output_stream,
1070 std::placeholders::_1)));
1071 // Expected output: "message: \"Hello\""
1072 EXPECT_TRUE(nullptr !=
1073 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1077 std::stringstream output_stream;
1078 FLAGS_metadata = "key:val\\:val";
1079 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1080 TestCliCredentials(),
1081 std::bind(PrintStream, &output_stream,
1082 std::placeholders::_1)));
1083 // Expected output: "message: \"Hello\""
1084 EXPECT_TRUE(nullptr !=
1085 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1089 std::stringstream output_stream;
1090 FLAGS_metadata = "key:val\\\\val";
1091 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
1092 TestCliCredentials(),
1093 std::bind(PrintStream, &output_stream,
1094 std::placeholders::_1)));
1095 // Expected output: "message: \"Hello\""
1096 EXPECT_TRUE(nullptr !=
1097 strstr(output_stream.str().c_str(), "message: \"Hello\""));
1100 FLAGS_metadata = "";
1104 TEST_F(GrpcToolTest, CallCommandWithBadMetadata) {
1105 // Test input "grpc_cli call localhost:10000 Echo "message: 'Hello'"
1106 const char* argv[] = {"grpc_cli", "call", "localhost:10000", "Echo",
1107 "message: 'Hello'"};
1108 FLAGS_protofiles = "src/proto/grpc/testing/echo.proto";
1109 char* test_srcdir = gpr_getenv("TEST_SRCDIR");
1110 if (test_srcdir != nullptr) {
1111 FLAGS_proto_path = test_srcdir + std::string("/com_github_grpc_grpc");
1115 std::stringstream output_stream;
1116 FLAGS_metadata = "key0:val0:key1";
1120 ArraySize(argv), argv, TestCliCredentials(),
1121 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1122 ::testing::ExitedWithCode(1), ".*Failed to parse metadata flag.*");
1126 std::stringstream output_stream;
1127 FLAGS_metadata = "key:val\\val";
1131 ArraySize(argv), argv, TestCliCredentials(),
1132 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
1133 ::testing::ExitedWithCode(1), ".*Failed to parse metadata flag.*");
1136 FLAGS_metadata = "";
1137 FLAGS_protofiles = "";
1139 gpr_free(test_srcdir);
1142 TEST_F(GrpcToolTest, ListCommand_OverrideSslHostName) {
1143 const grpc::string server_address = SetUpServer(true);
1145 // Test input "grpc_cli ls localhost:<port> --channel_creds_type=ssl
1146 // --ssl_target=z.test.google.fr"
1147 std::stringstream output_stream;
1148 const char* argv[] = {"grpc_cli", "ls", server_address.c_str()};
1150 FLAGS_channel_creds_type = "ssl";
1151 FLAGS_ssl_target = "z.test.google.fr";
1153 0 == GrpcToolMainLib(
1154 ArraySize(argv), argv, TestCliCredentials(true),
1155 std::bind(PrintStream, &output_stream, std::placeholders::_1)));
1156 EXPECT_TRUE(0 == strcmp(output_stream.str().c_str(),
1157 "grpc.testing.EchoTestService\n"
1158 "grpc.reflection.v1alpha.ServerReflection\n"));
1160 FLAGS_channel_creds_type = "";
1161 FLAGS_ssl_target = "";
1165 } // namespace testing
1168 int main(int argc, char** argv) {
1169 grpc::testing::TestEnvironment env(argc, argv);
1170 ::testing::InitGoogleTest(&argc, argv);
1171 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
1172 return RUN_ALL_TESTS();