blob: 0f3086b44288c2ac091701faed286682e4f44bcd [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 Zeng68ca3512016-07-26 16:48:46 -070091 builder.AddListeningPort(server_address.str(), InsecureServerCredentials());
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070092 builder.RegisterService(&service_);
93 server_ = builder.BuildAndStart();
Yuchen Zengf4046cd2016-07-26 12:22:42 -070094 return server_address.str();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070095 }
96
Yuchen Zengf4046cd2016-07-26 12:22:42 -070097 void ShutdownServer() { server_->Shutdown(); }
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070098
Yuchen Zeng29ca79b2016-07-25 12:00:08 -070099 std::unique_ptr<Server> server_;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700100 TestServiceImpl service_;
101 reflection::ProtoServerReflectionPlugin plugin_;
102};
103
104static bool PrintStream(std::stringstream* ss, const grpc::string& output) {
105 (*ss) << output << std::endl;
106 return true;
107}
108
109template <typename T>
110static size_t ArraySize(T& a) {
111 return ((sizeof(a) / sizeof(*(a))) /
112 static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
113}
114
115#define USAGE_REGEX "( grpc_cli .+\n){2,10}"
116
117TEST_F(GrpcToolTest, NoCommand) {
118 // Test input "grpc_cli"
119 std::stringstream output_stream;
120 const char* argv[] = {"grpc_cli"};
121 // Exit with 1, print usage instruction in stderr
122 EXPECT_EXIT(
123 GrpcToolMainLib(
124 ArraySize(argv), argv,
125 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
126 ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
127 // No output
128 EXPECT_TRUE(0 == output_stream.tellp());
129}
130
131TEST_F(GrpcToolTest, InvalidCommand) {
132 // Test input "grpc_cli"
133 std::stringstream output_stream;
134 const char* argv[] = {"grpc_cli", "abc"};
135 // Exit with 1, print usage instruction in stderr
136 EXPECT_EXIT(
137 GrpcToolMainLib(
138 ArraySize(argv), argv,
139 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
140 ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
141 // No output
142 EXPECT_TRUE(0 == output_stream.tellp());
143}
144
145TEST_F(GrpcToolTest, HelpCommand) {
146 // Test input "grpc_cli help"
147 std::stringstream output_stream;
148 const char* argv[] = {"grpc_cli", "help"};
149 // Exit with 1, print usage instruction in stderr
150 EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv,
151 std::bind(PrintStream, &output_stream,
152 std::placeholders::_1)),
153 ::testing::ExitedWithCode(1), USAGE_REGEX);
154 // No output
155 EXPECT_TRUE(0 == output_stream.tellp());
156}
157
158TEST_F(GrpcToolTest, CallCommand) {
159 // Test input "grpc_cli call Echo"
160 std::stringstream output_stream;
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700161
162 const grpc::string server_address = SetUpServer();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700163 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
164 "message: 'Hello'"};
165
166 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
167 std::bind(PrintStream, &output_stream,
168 std::placeholders::_1)));
169 // Expected output: "message: \"Hello\""
170 EXPECT_TRUE(NULL !=
171 strstr(output_stream.str().c_str(), "message: \"Hello\""));
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700172 ShutdownServer();
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700173}
174
175TEST_F(GrpcToolTest, TooFewArguments) {
176 // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
177 std::stringstream output_stream;
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700178 const char* argv[] = {"grpc_cli", "call", "Echo"};
179
180 // Exit with 1
181 EXPECT_EXIT(
182 GrpcToolMainLib(
183 ArraySize(argv), argv,
184 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
185 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
186 // No output
187 EXPECT_TRUE(0 == output_stream.tellp());
188}
189
190TEST_F(GrpcToolTest, TooManyArguments) {
191 // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
192 std::stringstream output_stream;
Yuchen Zengf4046cd2016-07-26 12:22:42 -0700193 const char* argv[] = {"grpc_cli", "call", "localhost:10000",
Yuchen Zeng29ca79b2016-07-25 12:00:08 -0700194 "Echo", "Echo", "message: 'Hello'"};
195
196 // Exit with 1
197 EXPECT_EXIT(
198 GrpcToolMainLib(
199 ArraySize(argv), argv,
200 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
201 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
202 // No output
203 EXPECT_TRUE(0 == output_stream.tellp());
204}
205
206} // namespace testing
207} // namespace grpc
208
209int main(int argc, char** argv) {
210 grpc_test_init(argc, argv);
211 ::testing::InitGoogleTest(&argc, argv);
212 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
213 return RUN_ALL_TESTS();
214}