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