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