• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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