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