xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/health_service_end2end_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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