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