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