1 /*
2 *
3 * Copyright 2015 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 <climits>
20
21 #include <grpc/grpc.h>
22 #include <grpc/support/log.h>
23 #include <grpc/support/time.h>
24 #include <grpcpp/channel.h>
25 #include <grpcpp/client_context.h>
26 #include <grpcpp/create_channel.h>
27 #include <grpcpp/server.h>
28 #include <grpcpp/server_builder.h>
29 #include <grpcpp/server_context.h>
30 #include <grpcpp/test/default_reactor_test_peer.h>
31
32 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
33 #include "src/proto/grpc/testing/echo.grpc.pb.h"
34 #include "src/proto/grpc/testing/echo_mock.grpc.pb.h"
35 #include "test/core/util/port.h"
36 #include "test/core/util/test_config.h"
37
38 #include <grpcpp/test/mock_stream.h>
39
40 #include <gmock/gmock.h>
41 #include <gtest/gtest.h>
42
43 #include <iostream>
44
45 using grpc::testing::DefaultReactorTestPeer;
46 using grpc::testing::EchoRequest;
47 using grpc::testing::EchoResponse;
48 using grpc::testing::EchoTestService;
49 using grpc::testing::MockClientReaderWriter;
50 using std::vector;
51 using std::chrono::system_clock;
52 using ::testing::_;
53 using ::testing::AtLeast;
54 using ::testing::DoAll;
55 using ::testing::Invoke;
56 using ::testing::Return;
57 using ::testing::SaveArg;
58 using ::testing::SetArgPointee;
59 using ::testing::WithArg;
60
61 namespace grpc {
62 namespace testing {
63
64 namespace {
65 class FakeClient {
66 public:
FakeClient(EchoTestService::StubInterface * stub)67 explicit FakeClient(EchoTestService::StubInterface* stub) : stub_(stub) {}
68
DoEcho()69 void DoEcho() {
70 ClientContext context;
71 EchoRequest request;
72 EchoResponse response;
73 request.set_message("hello world");
74 Status s = stub_->Echo(&context, request, &response);
75 EXPECT_EQ(request.message(), response.message());
76 EXPECT_TRUE(s.ok());
77 }
78
DoRequestStream()79 void DoRequestStream() {
80 EchoRequest request;
81 EchoResponse response;
82
83 ClientContext context;
84 std::string msg("hello");
85 std::string exp(msg);
86
87 std::unique_ptr<ClientWriterInterface<EchoRequest>> cstream =
88 stub_->RequestStream(&context, &response);
89
90 request.set_message(msg);
91 EXPECT_TRUE(cstream->Write(request));
92
93 msg = ", world";
94 request.set_message(msg);
95 exp.append(msg);
96 EXPECT_TRUE(cstream->Write(request));
97
98 cstream->WritesDone();
99 Status s = cstream->Finish();
100
101 EXPECT_EQ(exp, response.message());
102 EXPECT_TRUE(s.ok());
103 }
104
DoResponseStream()105 void DoResponseStream() {
106 EchoRequest request;
107 EchoResponse response;
108 request.set_message("hello world");
109
110 ClientContext context;
111 std::unique_ptr<ClientReaderInterface<EchoResponse>> cstream =
112 stub_->ResponseStream(&context, request);
113
114 std::string exp = "";
115 EXPECT_TRUE(cstream->Read(&response));
116 exp.append(response.message() + " ");
117
118 EXPECT_TRUE(cstream->Read(&response));
119 exp.append(response.message());
120
121 EXPECT_FALSE(cstream->Read(&response));
122 EXPECT_EQ(request.message(), exp);
123
124 Status s = cstream->Finish();
125 EXPECT_TRUE(s.ok());
126 }
127
DoBidiStream()128 void DoBidiStream() {
129 EchoRequest request;
130 EchoResponse response;
131 ClientContext context;
132 std::string msg("hello");
133
134 std::unique_ptr<ClientReaderWriterInterface<EchoRequest, EchoResponse>>
135 stream = stub_->BidiStream(&context);
136
137 request.set_message(msg + "0");
138 EXPECT_TRUE(stream->Write(request));
139 EXPECT_TRUE(stream->Read(&response));
140 EXPECT_EQ(response.message(), request.message());
141
142 request.set_message(msg + "1");
143 EXPECT_TRUE(stream->Write(request));
144 EXPECT_TRUE(stream->Read(&response));
145 EXPECT_EQ(response.message(), request.message());
146
147 request.set_message(msg + "2");
148 EXPECT_TRUE(stream->Write(request));
149 EXPECT_TRUE(stream->Read(&response));
150 EXPECT_EQ(response.message(), request.message());
151
152 stream->WritesDone();
153 EXPECT_FALSE(stream->Read(&response));
154
155 Status s = stream->Finish();
156 EXPECT_TRUE(s.ok());
157 }
158
ResetStub(EchoTestService::StubInterface * stub)159 void ResetStub(EchoTestService::StubInterface* stub) { stub_ = stub; }
160
161 private:
162 EchoTestService::StubInterface* stub_;
163 };
164
165 class CallbackTestServiceImpl
166 : public EchoTestService::ExperimentalCallbackService {
167 public:
Echo(experimental::CallbackServerContext * context,const EchoRequest * request,EchoResponse * response)168 experimental::ServerUnaryReactor* Echo(
169 experimental::CallbackServerContext* context, const EchoRequest* request,
170 EchoResponse* response) override {
171 // Make the mock service explicitly treat empty input messages as invalid
172 // arguments so that we can test various results of status. In general, a
173 // mocked service should just use the original service methods, but we are
174 // adding this variance in Status return value just to improve coverage in
175 // this test.
176 auto* reactor = context->DefaultReactor();
177 if (request->message().length() > 0) {
178 response->set_message(request->message());
179 reactor->Finish(Status::OK);
180 } else {
181 reactor->Finish(Status(StatusCode::INVALID_ARGUMENT, "Invalid request"));
182 }
183 return reactor;
184 }
185 };
186
187 class MockCallbackTest : public ::testing::Test {
188 protected:
189 CallbackTestServiceImpl service_;
190 ServerContext context_;
191 };
192
TEST_F(MockCallbackTest,MockedCallSucceedsWithWait)193 TEST_F(MockCallbackTest, MockedCallSucceedsWithWait) {
194 experimental::CallbackServerContext ctx;
195 EchoRequest req;
196 EchoResponse resp;
197 grpc::internal::Mutex mu;
198 grpc::internal::CondVar cv;
199 grpc::Status status;
200 bool status_set = false;
201 DefaultReactorTestPeer peer(&ctx, [&](::grpc::Status s) {
202 grpc::internal::MutexLock l(&mu);
203 status_set = true;
204 status = std::move(s);
205 cv.Signal();
206 });
207
208 req.set_message("mock 1");
209 auto* reactor = service_.Echo(&ctx, &req, &resp);
210 cv.WaitUntil(&mu, [&] {
211 grpc::internal::MutexLock l(&mu);
212 return status_set;
213 });
214 EXPECT_EQ(reactor, peer.reactor());
215 EXPECT_TRUE(peer.test_status_set());
216 EXPECT_TRUE(peer.test_status().ok());
217 EXPECT_TRUE(status_set);
218 EXPECT_TRUE(status.ok());
219 EXPECT_EQ(req.message(), resp.message());
220 }
221
TEST_F(MockCallbackTest,MockedCallSucceeds)222 TEST_F(MockCallbackTest, MockedCallSucceeds) {
223 experimental::CallbackServerContext ctx;
224 EchoRequest req;
225 EchoResponse resp;
226 DefaultReactorTestPeer peer(&ctx);
227
228 req.set_message("ha ha, consider yourself mocked.");
229 auto* reactor = service_.Echo(&ctx, &req, &resp);
230 EXPECT_EQ(reactor, peer.reactor());
231 EXPECT_TRUE(peer.test_status_set());
232 EXPECT_TRUE(peer.test_status().ok());
233 }
234
TEST_F(MockCallbackTest,MockedCallFails)235 TEST_F(MockCallbackTest, MockedCallFails) {
236 experimental::CallbackServerContext ctx;
237 EchoRequest req;
238 EchoResponse resp;
239 DefaultReactorTestPeer peer(&ctx);
240
241 auto* reactor = service_.Echo(&ctx, &req, &resp);
242 EXPECT_EQ(reactor, peer.reactor());
243 EXPECT_TRUE(peer.test_status_set());
244 EXPECT_EQ(peer.test_status().error_code(), StatusCode::INVALID_ARGUMENT);
245 }
246
247 class TestServiceImpl : public EchoTestService::Service {
248 public:
Echo(ServerContext *,const EchoRequest * request,EchoResponse * response)249 Status Echo(ServerContext* /*context*/, const EchoRequest* request,
250 EchoResponse* response) override {
251 response->set_message(request->message());
252 return Status::OK;
253 }
254
RequestStream(ServerContext *,ServerReader<EchoRequest> * reader,EchoResponse * response)255 Status RequestStream(ServerContext* /*context*/,
256 ServerReader<EchoRequest>* reader,
257 EchoResponse* response) override {
258 EchoRequest request;
259 std::string resp("");
260 while (reader->Read(&request)) {
261 gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
262 resp.append(request.message());
263 }
264 response->set_message(resp);
265 return Status::OK;
266 }
267
ResponseStream(ServerContext *,const EchoRequest * request,ServerWriter<EchoResponse> * writer)268 Status ResponseStream(ServerContext* /*context*/, const EchoRequest* request,
269 ServerWriter<EchoResponse>* writer) override {
270 EchoResponse response;
271 vector<std::string> tokens = split(request->message());
272 for (const std::string& token : tokens) {
273 response.set_message(token);
274 writer->Write(response);
275 }
276 return Status::OK;
277 }
278
BidiStream(ServerContext *,ServerReaderWriter<EchoResponse,EchoRequest> * stream)279 Status BidiStream(
280 ServerContext* /*context*/,
281 ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
282 EchoRequest request;
283 EchoResponse response;
284 while (stream->Read(&request)) {
285 gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
286 response.set_message(request.message());
287 stream->Write(response);
288 }
289 return Status::OK;
290 }
291
292 private:
split(const std::string & input)293 const vector<std::string> split(const std::string& input) {
294 std::string buff("");
295 vector<std::string> result;
296
297 for (auto n : input) {
298 if (n != ' ') {
299 buff += n;
300 continue;
301 }
302 if (buff == "") continue;
303 result.push_back(buff);
304 buff = "";
305 }
306 if (buff != "") result.push_back(buff);
307
308 return result;
309 }
310 };
311
312 class MockTest : public ::testing::Test {
313 protected:
MockTest()314 MockTest() {}
315
SetUp()316 void SetUp() override {
317 int port = grpc_pick_unused_port_or_die();
318 server_address_ << "localhost:" << port;
319 // Setup server
320 ServerBuilder builder;
321 builder.AddListeningPort(server_address_.str(),
322 InsecureServerCredentials());
323 builder.RegisterService(&service_);
324 server_ = builder.BuildAndStart();
325 }
326
TearDown()327 void TearDown() override { server_->Shutdown(); }
328
ResetStub()329 void ResetStub() {
330 std::shared_ptr<Channel> channel = grpc::CreateChannel(
331 server_address_.str(), InsecureChannelCredentials());
332 stub_ = grpc::testing::EchoTestService::NewStub(channel);
333 }
334
335 std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
336 std::unique_ptr<Server> server_;
337 std::ostringstream server_address_;
338 TestServiceImpl service_;
339 };
340
341 // Do one real rpc and one mocked one
TEST_F(MockTest,SimpleRpc)342 TEST_F(MockTest, SimpleRpc) {
343 ResetStub();
344 FakeClient client(stub_.get());
345 client.DoEcho();
346 MockEchoTestServiceStub stub;
347 EchoResponse resp;
348 resp.set_message("hello world");
349 EXPECT_CALL(stub, Echo(_, _, _))
350 .Times(AtLeast(1))
351 .WillOnce(DoAll(SetArgPointee<2>(resp), Return(Status::OK)));
352 client.ResetStub(&stub);
353 client.DoEcho();
354 }
355
TEST_F(MockTest,ClientStream)356 TEST_F(MockTest, ClientStream) {
357 ResetStub();
358 FakeClient client(stub_.get());
359 client.DoRequestStream();
360
361 MockEchoTestServiceStub stub;
362 auto w = new MockClientWriter<EchoRequest>();
363 EchoResponse resp;
364 resp.set_message("hello, world");
365
366 EXPECT_CALL(*w, Write(_, _)).Times(2).WillRepeatedly(Return(true));
367 EXPECT_CALL(*w, WritesDone());
368 EXPECT_CALL(*w, Finish()).WillOnce(Return(Status::OK));
369
370 EXPECT_CALL(stub, RequestStreamRaw(_, _))
371 .WillOnce(DoAll(SetArgPointee<1>(resp), Return(w)));
372 client.ResetStub(&stub);
373 client.DoRequestStream();
374 }
375
TEST_F(MockTest,ServerStream)376 TEST_F(MockTest, ServerStream) {
377 ResetStub();
378 FakeClient client(stub_.get());
379 client.DoResponseStream();
380
381 MockEchoTestServiceStub stub;
382 auto r = new MockClientReader<EchoResponse>();
383 EchoResponse resp1;
384 resp1.set_message("hello");
385 EchoResponse resp2;
386 resp2.set_message("world");
387
388 EXPECT_CALL(*r, Read(_))
389 .WillOnce(DoAll(SetArgPointee<0>(resp1), Return(true)))
390 .WillOnce(DoAll(SetArgPointee<0>(resp2), Return(true)))
391 .WillOnce(Return(false));
392 EXPECT_CALL(*r, Finish()).WillOnce(Return(Status::OK));
393
394 EXPECT_CALL(stub, ResponseStreamRaw(_, _)).WillOnce(Return(r));
395
396 client.ResetStub(&stub);
397 client.DoResponseStream();
398 }
399
ACTION_P(copy,msg)400 ACTION_P(copy, msg) { arg0->set_message(msg->message()); }
401
TEST_F(MockTest,BidiStream)402 TEST_F(MockTest, BidiStream) {
403 ResetStub();
404 FakeClient client(stub_.get());
405 client.DoBidiStream();
406 MockEchoTestServiceStub stub;
407 auto rw = new MockClientReaderWriter<EchoRequest, EchoResponse>();
408 EchoRequest msg;
409
410 EXPECT_CALL(*rw, Write(_, _))
411 .Times(3)
412 .WillRepeatedly(DoAll(SaveArg<0>(&msg), Return(true)));
413 EXPECT_CALL(*rw, Read(_))
414 .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true)))
415 .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true)))
416 .WillOnce(DoAll(WithArg<0>(copy(&msg)), Return(true)))
417 .WillOnce(Return(false));
418 EXPECT_CALL(*rw, WritesDone());
419 EXPECT_CALL(*rw, Finish()).WillOnce(Return(Status::OK));
420
421 EXPECT_CALL(stub, BidiStreamRaw(_)).WillOnce(Return(rw));
422 client.ResetStub(&stub);
423 client.DoBidiStream();
424 }
425
426 } // namespace
427 } // namespace testing
428 } // namespace grpc
429
main(int argc,char ** argv)430 int main(int argc, char** argv) {
431 grpc::testing::TestEnvironment env(argc, argv);
432 ::testing::InitGoogleTest(&argc, argv);
433 return RUN_ALL_TESTS();
434 }
435