xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/client_fork_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2022 The gRPC Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <grpc/support/port_platform.h>
16 
17 #ifndef GRPC_ENABLE_FORK_SUPPORT
18 // No-op for builds without fork support.
main(int,char **)19 int main(int /* argc */, char** /* argv */) { return 0; }
20 #else  // GRPC_ENABLE_FORK_SUPPORT
21 
22 #include <signal.h>
23 
24 #include <gtest/gtest.h>
25 
26 #include "absl/strings/str_cat.h"
27 
28 #include <grpc/fork.h>
29 #include <grpc/grpc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/time.h>
32 #include <grpcpp/channel.h>
33 #include <grpcpp/client_context.h>
34 #include <grpcpp/create_channel.h>
35 #include <grpcpp/server.h>
36 #include <grpcpp/server_builder.h>
37 #include <grpcpp/server_context.h>
38 
39 #include "src/core/lib/gprpp/fork.h"
40 #include "src/proto/grpc/testing/echo.grpc.pb.h"
41 #include "test/core/util/port.h"
42 #include "test/core/util/test_config.h"
43 #include "test/cpp/util/test_config.h"
44 
45 namespace grpc {
46 namespace testing {
47 namespace {
48 
49 class ServiceImpl final : public EchoTestService::Service {
BidiStream(ServerContext *,ServerReaderWriter<EchoResponse,EchoRequest> * stream)50   Status BidiStream(
51       ServerContext* /*context*/,
52       ServerReaderWriter<EchoResponse, EchoRequest>* stream) override {
53     EchoRequest request;
54     EchoResponse response;
55     while (stream->Read(&request)) {
56       gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
57       response.set_message(request.message());
58       stream->Write(response);
59       gpr_log(GPR_INFO, "wrote msg %s", response.message().c_str());
60     }
61     return Status::OK;
62   }
63 };
64 
MakeStub(const std::string & addr)65 std::unique_ptr<EchoTestService::Stub> MakeStub(const std::string& addr) {
66   return EchoTestService::NewStub(
67       grpc::CreateChannel(addr, InsecureChannelCredentials()));
68 }
69 
TEST(ClientForkTest,ClientCallsBeforeAndAfterForkSucceed)70 TEST(ClientForkTest, ClientCallsBeforeAndAfterForkSucceed) {
71   grpc_core::Fork::Enable(true);
72 
73   int port = grpc_pick_unused_port_or_die();
74   std::string addr = absl::StrCat("localhost:", port);
75 
76   pid_t server_pid = fork();
77   switch (server_pid) {
78     case -1:  // fork failed
79       GTEST_FAIL() << "failure forking";
80     case 0:  // post-fork child
81     {
82       ServiceImpl impl;
83       grpc::ServerBuilder builder;
84       builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
85       builder.RegisterService(&impl);
86       std::unique_ptr<Server> server(builder.BuildAndStart());
87       server->Wait();
88       return;
89     }
90     default:  // post-fork parent
91       break;
92   }
93 
94   // Do a round trip before we fork.
95   // NOTE: without this scope, test running with the epoll1 poller will fail.
96   {
97     std::unique_ptr<EchoTestService::Stub> stub = MakeStub(addr);
98     EchoRequest request;
99     EchoResponse response;
100     ClientContext context;
101     context.set_wait_for_ready(true);
102 
103     auto stream = stub->BidiStream(&context);
104 
105     request.set_message("Hello");
106     ASSERT_TRUE(stream->Write(request));
107     ASSERT_TRUE(stream->Read(&response));
108     ASSERT_EQ(response.message(), request.message());
109   }
110   // Fork and do round trips in the post-fork parent and child.
111   pid_t child_client_pid = fork();
112   switch (child_client_pid) {
113     case -1:  // fork failed
114       GTEST_FAIL() << "fork failed";
115     case 0:  // post-fork child
116     {
117       gpr_log(GPR_DEBUG, "In post-fork child");
118       EchoRequest request;
119       EchoResponse response;
120       ClientContext context;
121       context.set_wait_for_ready(true);
122 
123       std::unique_ptr<EchoTestService::Stub> stub = MakeStub(addr);
124       auto stream = stub->BidiStream(&context);
125 
126       request.set_message("Hello again from child");
127       ASSERT_TRUE(stream->Write(request));
128       ASSERT_TRUE(stream->Read(&response));
129       ASSERT_EQ(response.message(), request.message());
130       exit(0);
131     }
132     default:  // post-fork parent
133     {
134       gpr_log(GPR_DEBUG, "In post-fork parent");
135       EchoRequest request;
136       EchoResponse response;
137       ClientContext context;
138       context.set_wait_for_ready(true);
139 
140       std::unique_ptr<EchoTestService::Stub> stub = MakeStub(addr);
141       auto stream = stub->BidiStream(&context);
142 
143       request.set_message("Hello again from parent");
144       EXPECT_TRUE(stream->Write(request));
145       EXPECT_TRUE(stream->Read(&response));
146       EXPECT_EQ(response.message(), request.message());
147 
148       // Wait for the post-fork child to exit; ensure it exited cleanly.
149       int child_status;
150       ASSERT_EQ(waitpid(child_client_pid, &child_status, 0), child_client_pid)
151           << "failed to get status of child client";
152       ASSERT_EQ(WEXITSTATUS(child_status), 0) << "child did not exit cleanly";
153     }
154   }
155 
156   kill(server_pid, SIGINT);
157 }
158 
159 }  // namespace
160 }  // namespace testing
161 }  // namespace grpc
162 
main(int argc,char ** argv)163 int main(int argc, char** argv) {
164   testing::InitGoogleTest(&argc, argv);
165   grpc::testing::InitTest(&argc, &argv, true);
166   grpc::testing::TestEnvironment env(&argc, argv);
167   grpc_init();
168   int res = RUN_ALL_TESTS();
169   grpc_shutdown();
170   return res;
171 }
172 #endif  // GRPC_ENABLE_FORK_SUPPORT
173