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