blob: 77c3f3fc24ddd3374b56c28110bfdd7d33dd93c6 [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
82 void SetUp() GRPC_OVERRIDE {
83 int port = grpc_pick_unused_port_or_die();
84 server_address_ << "localhost:" << port;
85 // Setup server
86 ServerBuilder builder;
87 builder.AddListeningPort(server_address_.str(),
88 InsecureServerCredentials());
89 builder.RegisterService(&service_);
90 server_ = builder.BuildAndStart();
91 }
92
93 void TearDown() GRPC_OVERRIDE { server_->Shutdown(); }
94
95 void ResetStub() {
96 channel_ =
97 CreateChannel(server_address_.str(), InsecureChannelCredentials());
98 stub_ = grpc::testing::EchoTestService::NewStub(channel_);
99 }
100
101 std::shared_ptr<Channel> channel_;
102 std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
103 std::unique_ptr<Server> server_;
104 std::ostringstream server_address_;
105 TestServiceImpl service_;
106 reflection::ProtoServerReflectionPlugin plugin_;
107};
108
109static bool PrintStream(std::stringstream* ss, const grpc::string& output) {
110 (*ss) << output << std::endl;
111 return true;
112}
113
114template <typename T>
115static size_t ArraySize(T& a) {
116 return ((sizeof(a) / sizeof(*(a))) /
117 static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
118}
119
120#define USAGE_REGEX "( grpc_cli .+\n){2,10}"
121
122TEST_F(GrpcToolTest, NoCommand) {
123 // Test input "grpc_cli"
124 std::stringstream output_stream;
125 const char* argv[] = {"grpc_cli"};
126 // Exit with 1, print usage instruction in stderr
127 EXPECT_EXIT(
128 GrpcToolMainLib(
129 ArraySize(argv), argv,
130 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
131 ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
132 // No output
133 EXPECT_TRUE(0 == output_stream.tellp());
134}
135
136TEST_F(GrpcToolTest, InvalidCommand) {
137 // Test input "grpc_cli"
138 std::stringstream output_stream;
139 const char* argv[] = {"grpc_cli", "abc"};
140 // Exit with 1, print usage instruction in stderr
141 EXPECT_EXIT(
142 GrpcToolMainLib(
143 ArraySize(argv), argv,
144 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
145 ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
146 // No output
147 EXPECT_TRUE(0 == output_stream.tellp());
148}
149
150TEST_F(GrpcToolTest, HelpCommand) {
151 // Test input "grpc_cli help"
152 std::stringstream output_stream;
153 const char* argv[] = {"grpc_cli", "help"};
154 // Exit with 1, print usage instruction in stderr
155 EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv,
156 std::bind(PrintStream, &output_stream,
157 std::placeholders::_1)),
158 ::testing::ExitedWithCode(1), USAGE_REGEX);
159 // No output
160 EXPECT_TRUE(0 == output_stream.tellp());
161}
162
163TEST_F(GrpcToolTest, CallCommand) {
164 // Test input "grpc_cli call Echo"
165 std::stringstream output_stream;
166 grpc::string server_address = server_address_.str();
167 const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
168 "message: 'Hello'"};
169
170 EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv,
171 std::bind(PrintStream, &output_stream,
172 std::placeholders::_1)));
173 // Expected output: "message: \"Hello\""
174 EXPECT_TRUE(NULL !=
175 strstr(output_stream.str().c_str(), "message: \"Hello\""));
176}
177
178TEST_F(GrpcToolTest, TooFewArguments) {
179 // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
180 std::stringstream output_stream;
181 grpc::string server_address = server_address_.str();
182 const char* argv[] = {"grpc_cli", "call", "Echo"};
183
184 // Exit with 1
185 EXPECT_EXIT(
186 GrpcToolMainLib(
187 ArraySize(argv), argv,
188 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
189 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
190 // No output
191 EXPECT_TRUE(0 == output_stream.tellp());
192}
193
194TEST_F(GrpcToolTest, TooManyArguments) {
195 // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
196 std::stringstream output_stream;
197 grpc::string server_address = server_address_.str();
198 const char* argv[] = {"grpc_cli", "call", server_address.c_str(),
199 "Echo", "Echo", "message: 'Hello'"};
200
201 // Exit with 1
202 EXPECT_EXIT(
203 GrpcToolMainLib(
204 ArraySize(argv), argv,
205 std::bind(PrintStream, &output_stream, std::placeholders::_1)),
206 ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
207 // No output
208 EXPECT_TRUE(0 == output_stream.tellp());
209}
210
211} // namespace testing
212} // namespace grpc
213
214int main(int argc, char** argv) {
215 grpc_test_init(argc, argv);
216 ::testing::InitGoogleTest(&argc, argv);
217 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
218 return RUN_ALL_TESTS();
219}