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