1 //
2 //
3 // Copyright 2016 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 <grpc/grpc.h>
20 #include <grpcpp/channel.h>
21 #include <grpcpp/client_context.h>
22 #include <grpcpp/create_channel.h>
23 #include <grpcpp/ext/health_check_service_server_builder_option.h>
24 #include <grpcpp/health_check_service_interface.h>
25 #include <grpcpp/server.h>
26 #include <grpcpp/server_builder.h>
27 #include <grpcpp/server_context.h>
28 #include <gtest/gtest.h>
29
30 #include <memory>
31 #include <mutex>
32 #include <thread>
33 #include <vector>
34
35 #include "src/core/util/crash.h"
36 #include "src/proto/grpc/health/v1/health.grpc.pb.h"
37 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
38 #include "src/proto/grpc/testing/echo.grpc.pb.h"
39 #include "test/core/test_util/port.h"
40 #include "test/core/test_util/test_config.h"
41 #include "test/cpp/end2end/test_health_check_service_impl.h"
42 #include "test/cpp/end2end/test_service_impl.h"
43
44 using grpc::health::v1::Health;
45 using grpc::health::v1::HealthCheckRequest;
46 using grpc::health::v1::HealthCheckResponse;
47
48 namespace grpc {
49 namespace testing {
50 namespace {
51
52 // A custom implementation of the health checking service interface. This is
53 // used to test that it prevents the server from creating a default service and
54 // also serves as an example of how to override the default service.
55 class CustomHealthCheckService : public HealthCheckServiceInterface {
56 public:
CustomHealthCheckService(HealthCheckServiceImpl * impl)57 explicit CustomHealthCheckService(HealthCheckServiceImpl* impl)
58 : impl_(impl) {
59 impl_->SetStatus("", HealthCheckResponse::SERVING);
60 }
SetServingStatus(const std::string & service_name,bool serving)61 void SetServingStatus(const std::string& service_name,
62 bool serving) override {
63 impl_->SetStatus(service_name, serving ? HealthCheckResponse::SERVING
64 : HealthCheckResponse::NOT_SERVING);
65 }
66
SetServingStatus(bool serving)67 void SetServingStatus(bool serving) override {
68 impl_->SetAll(serving ? HealthCheckResponse::SERVING
69 : HealthCheckResponse::NOT_SERVING);
70 }
71
Shutdown()72 void Shutdown() override { impl_->Shutdown(); }
73
74 private:
75 HealthCheckServiceImpl* impl_; // not owned
76 };
77
78 class HealthServiceEnd2endTest : public ::testing::Test {
79 protected:
HealthServiceEnd2endTest()80 HealthServiceEnd2endTest() {}
81
SetUpServer(bool register_sync_test_service,bool add_async_cq,bool explicit_health_service,std::unique_ptr<HealthCheckServiceInterface> service)82 void SetUpServer(bool register_sync_test_service, bool add_async_cq,
83 bool explicit_health_service,
84 std::unique_ptr<HealthCheckServiceInterface> service) {
85 int port = grpc_pick_unused_port_or_die();
86 server_address_ << "localhost:" << port;
87
88 bool register_sync_health_service_impl =
89 explicit_health_service && service != nullptr;
90
91 // Setup server
92 ServerBuilder builder;
93 if (explicit_health_service) {
94 std::unique_ptr<ServerBuilderOption> option(
95 new HealthCheckServiceServerBuilderOption(std::move(service)));
96 builder.SetOption(std::move(option));
97 }
98 builder.AddListeningPort(server_address_.str(),
99 grpc::InsecureServerCredentials());
100 if (register_sync_test_service) {
101 // Register a sync service.
102 builder.RegisterService(&echo_test_service_);
103 }
104 if (register_sync_health_service_impl) {
105 builder.RegisterService(&health_check_service_impl_);
106 }
107 if (add_async_cq) {
108 cq_ = builder.AddCompletionQueue();
109 }
110 server_ = builder.BuildAndStart();
111 }
112
TearDown()113 void TearDown() override {
114 if (server_) {
115 server_->Shutdown();
116 if (cq_ != nullptr) {
117 cq_->Shutdown();
118 }
119 if (cq_thread_.joinable()) {
120 cq_thread_.join();
121 }
122 }
123 }
124
ResetStubs()125 void ResetStubs() {
126 std::shared_ptr<Channel> channel = grpc::CreateChannel(
127 server_address_.str(), InsecureChannelCredentials());
128 hc_stub_ = grpc::health::v1::Health::NewStub(channel);
129 }
130
131 // When the expected_status is NOT OK, we do not care about the response.
SendHealthCheckRpc(const std::string & service_name,const Status & expected_status)132 void SendHealthCheckRpc(const std::string& service_name,
133 const Status& expected_status) {
134 EXPECT_FALSE(expected_status.ok());
135 SendHealthCheckRpc(service_name, expected_status,
136 HealthCheckResponse::UNKNOWN);
137 }
138
SendHealthCheckRpc(const std::string & service_name,const Status & expected_status,HealthCheckResponse::ServingStatus expected_serving_status)139 void SendHealthCheckRpc(
140 const std::string& service_name, const Status& expected_status,
141 HealthCheckResponse::ServingStatus expected_serving_status) {
142 HealthCheckRequest request;
143 request.set_service(service_name);
144 HealthCheckResponse response;
145 ClientContext context;
146 Status s = hc_stub_->Check(&context, request, &response);
147 EXPECT_EQ(expected_status.error_code(), s.error_code());
148 if (s.ok()) {
149 EXPECT_EQ(expected_serving_status, response.status());
150 }
151 }
152
VerifyHealthCheckService()153 void VerifyHealthCheckService() {
154 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
155 EXPECT_TRUE(service != nullptr);
156 const std::string kHealthyService("healthy_service");
157 const std::string kUnhealthyService("unhealthy_service");
158 const std::string kNotRegisteredService("not_registered");
159 service->SetServingStatus(kHealthyService, true);
160 service->SetServingStatus(kUnhealthyService, false);
161
162 ResetStubs();
163
164 SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING);
165 SendHealthCheckRpc(kHealthyService, Status::OK,
166 HealthCheckResponse::SERVING);
167 SendHealthCheckRpc(kUnhealthyService, Status::OK,
168 HealthCheckResponse::NOT_SERVING);
169 SendHealthCheckRpc(kNotRegisteredService,
170 Status(StatusCode::NOT_FOUND, ""));
171
172 service->SetServingStatus(false);
173 SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING);
174 SendHealthCheckRpc(kHealthyService, Status::OK,
175 HealthCheckResponse::NOT_SERVING);
176 SendHealthCheckRpc(kUnhealthyService, Status::OK,
177 HealthCheckResponse::NOT_SERVING);
178 SendHealthCheckRpc(kNotRegisteredService,
179 Status(StatusCode::NOT_FOUND, ""));
180 }
181
VerifyHealthCheckServiceStreaming()182 void VerifyHealthCheckServiceStreaming() {
183 const std::string kServiceName("service_name");
184 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
185 // Start Watch for service.
186 ClientContext context;
187 HealthCheckRequest request;
188 request.set_service(kServiceName);
189 std::unique_ptr<grpc::ClientReaderInterface<HealthCheckResponse>> reader =
190 hc_stub_->Watch(&context, request);
191 // Initial response will be SERVICE_UNKNOWN.
192 HealthCheckResponse response;
193 EXPECT_TRUE(reader->Read(&response));
194 EXPECT_EQ(response.SERVICE_UNKNOWN, response.status());
195 response.Clear();
196 // Now set service to NOT_SERVING and make sure we get an update.
197 service->SetServingStatus(kServiceName, false);
198 EXPECT_TRUE(reader->Read(&response));
199 EXPECT_EQ(response.NOT_SERVING, response.status());
200 response.Clear();
201 // Now set service to SERVING and make sure we get another update.
202 service->SetServingStatus(kServiceName, true);
203 EXPECT_TRUE(reader->Read(&response));
204 EXPECT_EQ(response.SERVING, response.status());
205 // Finish call.
206 context.TryCancel();
207 }
208
209 // Verify that after HealthCheckServiceInterface::Shutdown is called
210 // 1. unary client will see NOT_SERVING.
211 // 2. unary client still sees NOT_SERVING after a SetServing(true) is called.
212 // 3. streaming (Watch) client will see an update.
213 // 4. setting a new service to serving after shutdown will add the service
214 // name but return NOT_SERVING to client.
215 // This has to be called last.
VerifyHealthCheckServiceShutdown()216 void VerifyHealthCheckServiceShutdown() {
217 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
218 EXPECT_TRUE(service != nullptr);
219 const std::string kHealthyService("healthy_service");
220 const std::string kUnhealthyService("unhealthy_service");
221 const std::string kNotRegisteredService("not_registered");
222 const std::string kNewService("add_after_shutdown");
223 service->SetServingStatus(kHealthyService, true);
224 service->SetServingStatus(kUnhealthyService, false);
225
226 ResetStubs();
227
228 // Start Watch for service.
229 ClientContext context;
230 HealthCheckRequest request;
231 request.set_service(kHealthyService);
232 std::unique_ptr<grpc::ClientReaderInterface<HealthCheckResponse>> reader =
233 hc_stub_->Watch(&context, request);
234
235 HealthCheckResponse response;
236 EXPECT_TRUE(reader->Read(&response));
237 EXPECT_EQ(response.SERVING, response.status());
238
239 SendHealthCheckRpc("", Status::OK, HealthCheckResponse::SERVING);
240 SendHealthCheckRpc(kHealthyService, Status::OK,
241 HealthCheckResponse::SERVING);
242 SendHealthCheckRpc(kUnhealthyService, Status::OK,
243 HealthCheckResponse::NOT_SERVING);
244 SendHealthCheckRpc(kNotRegisteredService,
245 Status(StatusCode::NOT_FOUND, ""));
246 SendHealthCheckRpc(kNewService, Status(StatusCode::NOT_FOUND, ""));
247
248 // Shutdown health check service.
249 service->Shutdown();
250
251 // Watch client gets another update.
252 EXPECT_TRUE(reader->Read(&response));
253 EXPECT_EQ(response.NOT_SERVING, response.status());
254 // Finish Watch call.
255 context.TryCancel();
256
257 SendHealthCheckRpc("", Status::OK, HealthCheckResponse::NOT_SERVING);
258 SendHealthCheckRpc(kHealthyService, Status::OK,
259 HealthCheckResponse::NOT_SERVING);
260 SendHealthCheckRpc(kUnhealthyService, Status::OK,
261 HealthCheckResponse::NOT_SERVING);
262 SendHealthCheckRpc(kNotRegisteredService,
263 Status(StatusCode::NOT_FOUND, ""));
264
265 // Setting status after Shutdown has no effect.
266 service->SetServingStatus(kHealthyService, true);
267 SendHealthCheckRpc(kHealthyService, Status::OK,
268 HealthCheckResponse::NOT_SERVING);
269
270 // Adding serving status for a new service after shutdown will return
271 // NOT_SERVING.
272 service->SetServingStatus(kNewService, true);
273 SendHealthCheckRpc(kNewService, Status::OK,
274 HealthCheckResponse::NOT_SERVING);
275 }
276
277 TestServiceImpl echo_test_service_;
278 HealthCheckServiceImpl health_check_service_impl_;
279 std::unique_ptr<Health::Stub> hc_stub_;
280 std::unique_ptr<ServerCompletionQueue> cq_;
281 std::unique_ptr<Server> server_;
282 std::ostringstream server_address_;
283 std::thread cq_thread_;
284 };
285
TEST_F(HealthServiceEnd2endTest,DefaultHealthServiceDisabled)286 TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) {
287 EnableDefaultHealthCheckService(false);
288 EXPECT_FALSE(DefaultHealthCheckServiceEnabled());
289 SetUpServer(true, false, false, nullptr);
290 HealthCheckServiceInterface* default_service =
291 server_->GetHealthCheckService();
292 EXPECT_TRUE(default_service == nullptr);
293
294 ResetStubs();
295
296 SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
297 }
298
TEST_F(HealthServiceEnd2endTest,DefaultHealthService)299 TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
300 EnableDefaultHealthCheckService(true);
301 EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
302 SetUpServer(true, false, false, nullptr);
303 VerifyHealthCheckService();
304 VerifyHealthCheckServiceStreaming();
305
306 // The default service has a size limit of the service name.
307 const std::string kTooLongServiceName(201, 'x');
308 SendHealthCheckRpc(kTooLongServiceName,
309 Status(StatusCode::INVALID_ARGUMENT, ""));
310 }
311
TEST_F(HealthServiceEnd2endTest,DefaultHealthServiceShutdown)312 TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) {
313 EnableDefaultHealthCheckService(true);
314 EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
315 SetUpServer(true, false, false, nullptr);
316 VerifyHealthCheckServiceShutdown();
317 }
318
319 // Provide an empty service to disable the default service.
TEST_F(HealthServiceEnd2endTest,ExplicitlyDisableViaOverride)320 TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) {
321 EnableDefaultHealthCheckService(true);
322 EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
323 std::unique_ptr<HealthCheckServiceInterface> empty_service;
324 SetUpServer(true, false, true, std::move(empty_service));
325 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
326 EXPECT_TRUE(service == nullptr);
327
328 ResetStubs();
329
330 SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
331 }
332
333 // Provide an explicit override of health checking service interface.
TEST_F(HealthServiceEnd2endTest,ExplicitlyOverride)334 TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) {
335 EnableDefaultHealthCheckService(true);
336 EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
337 std::unique_ptr<HealthCheckServiceInterface> override_service(
338 new CustomHealthCheckService(&health_check_service_impl_));
339 HealthCheckServiceInterface* underlying_service = override_service.get();
340 SetUpServer(false, false, true, std::move(override_service));
341 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
342 EXPECT_TRUE(service == underlying_service);
343
344 ResetStubs();
345
346 VerifyHealthCheckService();
347 VerifyHealthCheckServiceStreaming();
348 }
349
TEST_F(HealthServiceEnd2endTest,ExplicitlyHealthServiceShutdown)350 TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) {
351 EnableDefaultHealthCheckService(true);
352 EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
353 std::unique_ptr<HealthCheckServiceInterface> override_service(
354 new CustomHealthCheckService(&health_check_service_impl_));
355 HealthCheckServiceInterface* underlying_service = override_service.get();
356 SetUpServer(false, false, true, std::move(override_service));
357 HealthCheckServiceInterface* service = server_->GetHealthCheckService();
358 EXPECT_TRUE(service == underlying_service);
359
360 ResetStubs();
361
362 VerifyHealthCheckServiceShutdown();
363 }
364
365 } // namespace
366 } // namespace testing
367 } // namespace grpc
368
main(int argc,char ** argv)369 int main(int argc, char** argv) {
370 grpc::testing::TestEnvironment env(&argc, argv);
371 ::testing::InitGoogleTest(&argc, argv);
372 return RUN_ALL_TESTS();
373 }
374