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