• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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