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