forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecho_integration_test.cc
140 lines (125 loc) · 4.91 KB
/
echo_integration_test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "test/integration/integration.h"
#include "test/integration/utility.h"
#include "test/server/utility.h"
#include "test/test_common/utility.h"
namespace Envoy {
std::string echo_config;
class EchoIntegrationTest : public testing::TestWithParam<Network::Address::IpVersion>,
public BaseIntegrationTest {
public:
EchoIntegrationTest() : BaseIntegrationTest(GetParam(), echo_config) {}
// Called once by the gtest framework before any EchoIntegrationTests are run.
static void SetUpTestSuite() { // NOLINT(readability-identifier-naming)
echo_config = absl::StrCat(ConfigHelper::baseConfig(), R"EOF(
filter_chains:
filters:
name: ratelimit
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.rate_limit.v2.RateLimit
domain: foo
stats_prefix: name
descriptors: [{"key": "foo", "value": "bar"}]
filters:
name: envoy.filters.network.echo
)EOF");
}
/**
* Initializer for an individual test.
*/
void SetUp() override { BaseIntegrationTest::initialize(); }
/**
* Destructor for an individual test.
*/
void TearDown() override {
test_server_.reset();
fake_upstreams_.clear();
}
};
INSTANTIATE_TEST_SUITE_P(IpVersions, EchoIntegrationTest,
testing::ValuesIn(TestEnvironment::getIpVersionsForTest()),
TestUtility::ipTestParamsToString);
TEST_P(EchoIntegrationTest, Hello) {
std::string response;
auto connection = createConnectionDriver(
lookupPort("listener_0"), "hello",
[&response](Network::ClientConnection& conn, const Buffer::Instance& data) -> void {
response.append(data.toString());
conn.close(Network::ConnectionCloseType::FlushWrite);
});
connection->run();
EXPECT_EQ("hello", response);
}
TEST_P(EchoIntegrationTest, AddRemoveListener) {
const std::string json = TestEnvironment::substitute(R"EOF(
name: new_listener
address:
socket_address:
address: "{{ ip_loopback_address }}"
port_value: 0
filter_chains:
- filters:
- name: envoy.filters.network.echo
)EOF",
GetParam());
// Add the listener.
ConditionalInitializer listener_added_by_worker;
ConditionalInitializer listener_added_by_manager;
test_server_->setOnWorkerListenerAddedCb(
[&listener_added_by_worker]() -> void { listener_added_by_worker.setReady(); });
test_server_->server().dispatcher().post([this, json, &listener_added_by_manager]() -> void {
EXPECT_TRUE(test_server_->server().listenerManager().addOrUpdateListener(
Server::parseListenerFromV2Yaml(json), "", true));
listener_added_by_manager.setReady();
});
listener_added_by_worker.waitReady();
listener_added_by_manager.waitReady();
EXPECT_EQ(2UL, test_server_->server().listenerManager().listeners().size());
uint32_t new_listener_port = test_server_->server()
.listenerManager()
.listeners()[1]
.get()
.listenSocketFactory()
.localAddress()
->ip()
->port();
std::string response;
auto connection = createConnectionDriver(
lookupPort("listener_0"), "hello",
[&response](Network::ClientConnection& conn, const Buffer::Instance& data) -> void {
response.append(data.toString());
conn.close(Network::ConnectionCloseType::FlushWrite);
});
connection->run();
EXPECT_EQ("hello", response);
// Remove the listener.
ConditionalInitializer listener_removed;
test_server_->setOnWorkerListenerRemovedCb(
[&listener_removed]() -> void { listener_removed.setReady(); });
test_server_->server().dispatcher().post([this]() -> void {
EXPECT_TRUE(test_server_->server().listenerManager().removeListener("new_listener"));
});
listener_removed.waitReady();
// Now connect. This should fail.
// Allow for a few attempts, in order to handle a race (likely due to lack of
// LEV_OPT_CLOSE_ON_FREE, which would break listener reuse)
//
// In order for this test to work, it must be tagged as "exclusive" in its
// build file. Otherwise, it's possible that when the listener is destroyed
// above, another test would start listening on the released port, and this
// connect would unexpectedly succeed.
bool connect_fail = false;
for (int i = 0; i < 10; ++i) {
auto connection2 = createConnectionDriver(
new_listener_port, "hello",
[](Network::ClientConnection&, const Buffer::Instance&) -> void { FAIL(); });
connection2->waitForConnection();
if (connection2->connection().state() == Network::Connection::State::Closed) {
connect_fail = true;
break;
} else {
connection2->close();
}
}
ASSERT_TRUE(connect_fail);
}
} // namespace Envoy