xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/mock_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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