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