xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/shutdown_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 <thread>
20 
21 #include <gtest/gtest.h>
22 
23 #include <grpc/grpc.h>
24 #include <grpc/support/log.h>
25 #include <grpc/support/sync.h>
26 #include <grpcpp/channel.h>
27 #include <grpcpp/client_context.h>
28 #include <grpcpp/create_channel.h>
29 #include <grpcpp/server.h>
30 #include <grpcpp/server_builder.h>
31 #include <grpcpp/server_context.h>
32 
33 #include "src/core/lib/gprpp/crash.h"
34 #include "src/core/lib/gprpp/env.h"
35 #include "src/proto/grpc/testing/echo.grpc.pb.h"
36 #include "test/core/util/port.h"
37 #include "test/core/util/test_config.h"
38 #include "test/cpp/util/test_credentials_provider.h"
39 
40 namespace grpc {
41 namespace testing {
42 
43 class TestServiceImpl : public grpc::testing::EchoTestService::Service {
44  public:
TestServiceImpl(gpr_event * ev)45   explicit TestServiceImpl(gpr_event* ev) : ev_(ev) {}
46 
Echo(ServerContext * context,const EchoRequest *,EchoResponse *)47   Status Echo(ServerContext* context, const EchoRequest* /*request*/,
48               EchoResponse* /*response*/) override {
49     gpr_event_set(ev_, reinterpret_cast<void*>(1));
50     while (!context->IsCancelled()) {
51     }
52     return Status::OK;
53   }
54 
55  private:
56   gpr_event* ev_;
57 };
58 
59 class ShutdownTest : public ::testing::TestWithParam<string> {
60  public:
ShutdownTest()61   ShutdownTest() : shutdown_(false), service_(&ev_) { gpr_event_init(&ev_); }
62 
SetUp()63   void SetUp() override {
64     port_ = grpc_pick_unused_port_or_die();
65     server_ = SetUpServer(port_);
66   }
67 
SetUpServer(const int port)68   std::unique_ptr<Server> SetUpServer(const int port) {
69     std::string server_address = "localhost:" + to_string(port);
70 
71     ServerBuilder builder;
72     auto server_creds =
73         GetCredentialsProvider()->GetServerCredentials(GetParam());
74     builder.AddListeningPort(server_address, server_creds);
75     builder.RegisterService(&service_);
76     std::unique_ptr<Server> server = builder.BuildAndStart();
77     return server;
78   }
79 
TearDown()80   void TearDown() override { GPR_ASSERT(shutdown_); }
81 
ResetStub()82   void ResetStub() {
83     string target = "dns:localhost:" + to_string(port_);
84     ChannelArguments args;
85     auto channel_creds =
86         GetCredentialsProvider()->GetChannelCredentials(GetParam(), &args);
87     channel_ = grpc::CreateCustomChannel(target, channel_creds, args);
88     stub_ = grpc::testing::EchoTestService::NewStub(channel_);
89   }
90 
to_string(const int number)91   string to_string(const int number) {
92     std::stringstream strs;
93     strs << number;
94     return strs.str();
95   }
96 
SendRequest()97   void SendRequest() {
98     EchoRequest request;
99     EchoResponse response;
100     request.set_message("Hello");
101     ClientContext context;
102     GPR_ASSERT(!shutdown_);
103     Status s = stub_->Echo(&context, request, &response);
104     GPR_ASSERT(shutdown_);
105   }
106 
107  protected:
108   std::shared_ptr<Channel> channel_;
109   std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
110   std::unique_ptr<Server> server_;
111   bool shutdown_;
112   int port_;
113   gpr_event ev_;
114   TestServiceImpl service_;
115 };
116 
GetAllCredentialsTypeList()117 std::vector<string> GetAllCredentialsTypeList() {
118   std::vector<std::string> credentials_types;
119   if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType,
120                                                       nullptr) != nullptr) {
121     credentials_types.push_back(kInsecureCredentialsType);
122   }
123   auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList();
124   for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) {
125     credentials_types.push_back(*sec);
126   }
127   GPR_ASSERT(!credentials_types.empty());
128 
129   std::string credentials_type_list("credentials types:");
130   for (const string& type : credentials_types) {
131     credentials_type_list.append(" " + type);
132   }
133   gpr_log(GPR_INFO, "%s", credentials_type_list.c_str());
134   return credentials_types;
135 }
136 
137 INSTANTIATE_TEST_SUITE_P(End2EndShutdown, ShutdownTest,
138                          ::testing::ValuesIn(GetAllCredentialsTypeList()));
139 
140 // TODO(ctiller): leaked objects in this test
TEST_P(ShutdownTest,ShutdownTest)141 TEST_P(ShutdownTest, ShutdownTest) {
142   ResetStub();
143 
144   // send the request in a background thread
145   std::thread thr(std::bind(&ShutdownTest::SendRequest, this));
146 
147   // wait for the server to get the event
148   gpr_event_wait(&ev_, gpr_inf_future(GPR_CLOCK_MONOTONIC));
149 
150   shutdown_ = true;
151 
152   // shutdown should trigger cancellation causing everything to shutdown
153   auto deadline =
154       std::chrono::system_clock::now() + std::chrono::microseconds(100);
155   server_->Shutdown(deadline);
156   EXPECT_GE(std::chrono::system_clock::now(), deadline);
157 
158   thr.join();
159 }
160 
161 }  // namespace testing
162 }  // namespace grpc
163 
main(int argc,char ** argv)164 int main(int argc, char** argv) {
165   grpc::testing::TestEnvironment env(&argc, argv);
166   ::testing::InitGoogleTest(&argc, argv);
167   return RUN_ALL_TESTS();
168 }
169