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