blob: 57eeed7234ab7b2add4d3ee4b1ede12333d5c7d4 [file] [log] [blame]
Yuchen Zeng29ca79b2016-07-25 12:00:08 -07001/*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "test/cpp/util/grpc_tool.h"
35
36#include <sstream>
37
38#include <grpc++/channel.h>
39#include <grpc++/client_context.h>
40#include <grpc++/create_channel.h>
41#include <grpc++/ext/proto_server_reflection_plugin.h>
42#include <grpc++/server.h>
43#include <grpc++/server_builder.h>
44#include <grpc++/server_context.h>
45#include <grpc/grpc.h>
46#include <gtest/gtest.h>
47
48#include "src/proto/grpc/testing/echo.grpc.pb.h"
49#include "src/proto/grpc/testing/echo.pb.h"
50#include "test/core/util/port.h"
51#include "test/core/util/test_config.h"
52#include "test/cpp/util/string_ref_helper.h"
53
54using grpc::testing::EchoRequest;
55using grpc::testing::EchoResponse;
56
57namespace grpc {
58namespace testing {
59
60class TestServiceImpl : public ::grpc::testing::EchoTestService::Service {
61 public:
62 Status Echo(ServerContext* context, const EchoRequest* request,
63 EchoResponse* response) GRPC_OVERRIDE {
64 if (!context->client_metadata().empty()) {
65 for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
66 iter = context->client_metadata().begin();
67 iter != context->client_metadata().end(); ++iter) {
68 context->AddInitialMetadata(ToString(iter->first),
69 ToString(iter->second));
70 }
71 }
72 context->AddTrailingMetadata("trailing_key", "trailing_value");
73 response->set_message(request->message());
74 return Status::OK;
75 }
76};
77
78class GrpcToolTest : public ::testing::Test {
79 protected:
80 GrpcToolTest() {}
81
Yuchen Zengf4046cd2016-07-26 12:22:42 -070082 // SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
83 // uses atexit() to free chosen ports, and it will spawn a new thread in
84 // resolve_address_posix.c:192 at exit time.
85 const grpc::string SetUpServer() {
86 std::ostringstream server_address;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070087 int port = grpc_pick_unused_port_or_die();
Yuchen Zengf4046cd2016-07-26 12:22:42 -070088 server_address << "localhost:" << port;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070089 // Setup server
90 ServerBuilder builder;
Yuchen Zengf4046cd2016-07-26 12:22:42 -070091 builder.AddListeningPort(server_address.str(),
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070092 InsecureServerCredentials());
93 builder.RegisterService(&service_);
94 server_ = builder.BuildAndStart();
Yuchen Zengf4046cd2016-07-26 12:22:42 -070095 return server_address.str();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070096 }
97
Yuchen Zengf4046cd2016-07-26 12:22:42 -070098 void ShutdownServer() { server_->Shutdown(); }
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070099
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700100 std::unique_ptr<Server> server_;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700101 TestServiceImpl service_;
102 reflection::ProtoServerReflectionPlugin plugin_;
103};
104
105static bool PrintStream(std::stringstream* ss, const grpc::string& output) {
106 (*ss) << output << std::endl;
107 return true;
108}
109
110template <typename T>
111static size_t ArraySize(T& a) {
112 return ((sizeof(a) / sizeof(*(a))) /
113 static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
114}
115
116#define USAGE_REGEX "( grpc_cli .+\n){2,10}"
117
118TEST_F(GrpcToolTest, NoCommand) {
119 // Test input "grpc_cli"
120 std::stringstream output_stream;
121 const char* argv[] = {"grpc_cli"};
122 // Exit with 1, print usage instruction in stderr
123 EXPECT_EXIT(
124 GrpcToolMainLib(
125 ArraySize(argv), argv,
126 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
127 ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
128 // No output
129 EXPECT_TRUE(0 == output_stream.tellp());
130}
131
132TEST_F(GrpcToolTest, InvalidCommand) {
133 // Test input "grpc_cli"
134 std::stringstream output_stream;
135 const char* argv[] = {"grpc_cli", "abc"};
136 // Exit with 1, print usage instruction in stderr
137 EXPECT_EXIT(
138 GrpcToolMainLib(
139 ArraySize(argv), argv,
140 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
141 ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
142 // No output
143 EXPECT_TRUE(0 == output_stream.tellp());
144}
145
146TEST_F(GrpcToolTest, HelpCommand) {
147 // Test input "grpc_cli help"
148 std::stringstream output_stream;
149 const char* argv[] = {"grpc_cli", "help"};
150 // Exit with 1, print usage instruction in stderr
151 EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv,
152 std::bind(PrintStream, &output_stream,
153 std::placeholders::_1)),
154 ::testing::ExitedWithCode(1), USAGE_REGEX);
155 // No output
156 EXPECT_TRUE(0 == output_stream.tellp());
157}
158
159TEST_F(GrpcToolTest, CallCommand) {
160 // Test input "grpc_cli call Echo"
161 std::stringstream output_stream;
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700162
163 const grpc::string server_address = SetUpServer();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700164 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
165 "message: 'Hello'"};
166
167 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
168 std::bind(PrintStream, &output_stream,
169 std::placeholders::_1)));
170 // Expected output: "message: \"Hello\""
171 EXPECT_TRUE(NULL !=
172 strstr(output_stream.str().c_str(), "message: \"Hello\""));
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700173 ShutdownServer();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700174}
175
176TEST_F(GrpcToolTest, TooFewArguments) {
177 // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
178 std::stringstream output_stream;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700179 const char* argv[] = {"grpc_cli", "call", "Echo"};
180
181 // Exit with 1
182 EXPECT_EXIT(
183 GrpcToolMainLib(
184 ArraySize(argv), argv,
185 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
186 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
187 // No output
188 EXPECT_TRUE(0 == output_stream.tellp());
189}
190
191TEST_F(GrpcToolTest, TooManyArguments) {
192 // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
193 std::stringstream output_stream;
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700194 const char* argv[] = {"grpc_cli", "call", "localhost:10000",
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700195 "Echo", "Echo", "message: 'Hello'"};
196
197 // Exit with 1
198 EXPECT_EXIT(
199 GrpcToolMainLib(
200 ArraySize(argv), argv,
201 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
202 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
203 // No output
204 EXPECT_TRUE(0 == output_stream.tellp());
205}
206
207} // namespace testing
208} // namespace grpc
209
210int main(int argc, char** argv) {
211 grpc_test_init(argc, argv);
212 ::testing::InitGoogleTest(&argc, argv);
213 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
214 return RUN_ALL_TESTS();
215}