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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:01