1
#include <spdlog/common.h>
2

            
3
#include <string>
4

            
5
#include "envoy/data/core/v3/health_check_event.pb.h"
6
#include "envoy/registry/registry.h"
7
#include "envoy/upstream/health_check_event_sink.h"
8

            
9
#include "source/common/common/base_logger.h"
10
#include "source/common/common/logger.h"
11
#include "source/common/protobuf/protobuf.h" // IWYU pragma: keep
12

            
13
#include "test/mocks/server/admin.h"
14
#include "test/mocks/server/health_checker_factory_context.h"
15
#include "test/test_common/utility.h"
16

            
17
#include "cilium/api/health_check_sink.pb.h"
18
#include "cilium/api/health_check_sink.pb.validate.h" // IWYU pragma: keep
19
#include "gtest/gtest.h"
20
#include "tests/health_check_sink_server.h"
21

            
22
namespace Envoy {
23
namespace Cilium {
24

            
25
1
TEST(HealthCheckEventPipeSinkFactory, createEmptyHealthCheckEventSink) {
26
1
  auto factory =
27
1
      Envoy::Registry::FactoryRegistry<Upstream::HealthCheckEventSinkFactory>::getFactory(
28
1
          "cilium.health_check.event_sink.pipe");
29
1
  EXPECT_NE(factory, nullptr);
30
1
  auto empty_proto = factory->createEmptyConfigProto();
31
1
  auto config = *dynamic_cast<cilium::HealthCheckEventPipeSink*>(empty_proto.get());
32
1
  EXPECT_TRUE(config.path().empty());
33
1
}
34

            
35
1
TEST(HealthCheckEventPipeSinkFactory, createHealthCheckEventSink) {
36
1
  auto factory =
37
1
      Envoy::Registry::FactoryRegistry<Upstream::HealthCheckEventSinkFactory>::getFactory(
38
1
          "cilium.health_check.event_sink.pipe");
39
1
  EXPECT_NE(factory, nullptr);
40

            
41
1
  cilium::HealthCheckEventPipeSink config;
42
1
  config.set_path("test_path");
43
1
  Envoy::ProtobufWkt::Any typed_config;
44
1
  typed_config.PackFrom(config);
45

            
46
1
  NiceMock<Server::Configuration::MockHealthCheckerFactoryContext> context;
47
1
  EXPECT_NE(factory->createHealthCheckEventSink(typed_config, context), nullptr);
48
1
}
49

            
50
1
TEST(HealthCheckEventPipeSink, logTest) {
51
66
  for (Logger::Logger& logger : Logger::Registry::loggers()) {
52
66
    logger.setLevel(spdlog::level::trace);
53
66
  }
54

            
55
  // Set up server
56
1
  std::string normal_path("test_path");
57
1
  HealthCheckSinkServer event_sink(normal_path);
58

            
59
  // Set up client factory
60
1
  auto factory =
61
1
      Envoy::Registry::FactoryRegistry<Upstream::HealthCheckEventSinkFactory>::getFactory(
62
1
          "cilium.health_check.event_sink.pipe");
63
1
  EXPECT_NE(factory, nullptr);
64

            
65
  // Set up client
66
1
  auto empty_proto = factory->createEmptyConfigProto();
67
1
  auto config = *dynamic_cast<cilium::HealthCheckEventPipeSink*>(empty_proto.get());
68
1
  EXPECT_TRUE(config.path().empty());
69
1
  config.set_path(normal_path);
70
1
  Envoy::ProtobufWkt::Any typed_config;
71
1
  typed_config.PackFrom(config);
72
1
  NiceMock<Server::Configuration::MockHealthCheckerFactoryContext> context;
73
1
  auto pipe_sink = factory->createHealthCheckEventSink(typed_config, context);
74
1
  EXPECT_NE(pipe_sink, nullptr);
75

            
76
1
  envoy::data::core::v3::HealthCheckEvent eject_event;
77
1
  TestUtility::loadFromYaml(R"EOF(
78
1
  health_checker_type: HTTP
79
1
  host:
80
1
    socket_address:
81
1
      protocol: TCP
82
1
      address: 10.0.0.1
83
1
      resolver_name: ''
84
1
      ipv4_compat: false
85
1
      port_value: 443
86
1
  cluster_name: fake_cluster
87
1
  eject_unhealthy_event:
88
1
    failure_type: ACTIVE
89
1
  timestamp: '2009-02-13T23:31:31.234Z'
90
1
  )EOF",
91
1
                            eject_event);
92

            
93
1
  pipe_sink->log(eject_event);
94
1
  EXPECT_TRUE(
95
1
      event_sink.expectEventTo([&](const envoy::data::core::v3::HealthCheckEvent& observed_event) {
96
1
        return Protobuf::util::MessageDifferencer::Equals(observed_event, eject_event);
97
1
      }));
98

            
99
  // Set up 2nd client on the same socket
100
1
  auto pipe_sink2 = factory->createHealthCheckEventSink(typed_config, context);
101
1
  EXPECT_NE(pipe_sink2, nullptr);
102

            
103
1
  envoy::data::core::v3::HealthCheckEvent add_event;
104
1
  TestUtility::loadFromYaml(R"EOF(
105
1
  health_checker_type: HTTP
106
1
  host:
107
1
    socket_address:
108
1
      protocol: TCP
109
1
      address: 10.0.0.1
110
1
      resolver_name: ''
111
1
      ipv4_compat: false
112
1
      port_value: 443
113
1
  cluster_name: fake_cluster
114
1
  add_healthy_event:
115
1
    first_check: false
116
1
  timestamp: '2009-02-13T23:31:31.234Z'
117
1
  )EOF",
118
1
                            add_event);
119

            
120
1
  pipe_sink2->log(add_event);
121
1
  EXPECT_TRUE(
122
1
      event_sink.expectEventTo([&](const envoy::data::core::v3::HealthCheckEvent& observed_event) {
123
1
        return Protobuf::util::MessageDifferencer::Equals(observed_event, add_event);
124
1
      }));
125

            
126
  // Set up another server on a different socket in an abstract namespace
127
  // Set up server
128
2
#define ABSTRACT_PATH "@another\0test_path"
129
1
  std::string abstract_name(ABSTRACT_PATH, sizeof(ABSTRACT_PATH) - 1);
130
1
  HealthCheckSinkServer event_sink3(abstract_name);
131

            
132
  // Set up 3rd client on a different socket
133
1
  cilium::HealthCheckEventPipeSink config3;
134
1
  config3.set_path(abstract_name);
135
1
  typed_config.PackFrom(config3);
136
1
  auto pipe_sink3 = factory->createHealthCheckEventSink(typed_config, context);
137
1
  EXPECT_NE(pipe_sink3, nullptr);
138

            
139
1
  pipe_sink3->log(eject_event);
140
1
  EXPECT_TRUE(
141
1
      event_sink3.expectEventTo([&](const envoy::data::core::v3::HealthCheckEvent& observed_event) {
142
1
        return Protobuf::util::MessageDifferencer::Equals(observed_event, eject_event);
143
1
      }));
144
1
}
145

            
146
} // namespace Cilium
147
} // namespace Envoy