29 #include <gmock/gmock.h>
31 #include "absl/flags/flag.h"
32 #include "absl/memory/memory.h"
33 #include "absl/strings/str_cat.h"
34 #include "absl/strings/str_format.h"
74 #define BAD_SOCKET_RETURN_VAL INVALID_SOCKET
77 #define BAD_SOCKET_RETURN_VAL (-1)
85 "Whether or not to compare resolved addresses to expected "
86 "addresses using an ordered comparison. This is useful for "
87 "testing certain behaviors that involve sorting of resolved "
88 "addresses. Note it would be better if this argument was a "
89 "bool flag, but it's a string for ease of invocation from "
90 "the generated python test runner.");
92 "List of expected backend or balancer addresses in the form "
93 "'<ip0:port0>,<is_balancer0>;<ip1:port1>,<is_balancer1>;...'. "
94 "'is_balancer' should be bool, i.e. true or false.");
96 "Expected service config json string that gets chosen (no "
97 "whitespace). Empty for none.");
99 "Expected service config error. Empty for none.");
101 "Optional. This address is placed as the uri authority if present.");
105 "Whether or not to enable SRV queries for the ares resolver instance."
106 "It would be better if this arg could be bool, but the way that we "
108 "the python script runner doesn't allow us to pass a gflags bool to this "
113 "Whether or not to enable TXT queries for the ares resolver instance."
114 "It would be better if this arg could be bool, but the way that we "
116 "the python script runner doesn't allow us to pass a gflags bool to this "
121 "Whether or not to configure c-ares to use a broken nameserver list, in "
123 "the first nameserver in the list is non-responsive, but the second one "
125 "serves the expected DNS records; using for testing such a real scenario."
126 "It would be better if this arg could be bool, but the way that we "
128 "the python script runner doesn't allow us to pass a gflags bool to this "
131 "Expected lb policy name that appears in resolver result channel "
132 "arg. Empty for none.");
136 class GrpcLBAddress final {
138 GrpcLBAddress(
std::string address,
bool is_balancer)
139 : is_balancer(is_balancer), address(
std::
move(address)) {}
141 bool operator==(
const GrpcLBAddress& other)
const {
142 return this->is_balancer == other.is_balancer &&
143 this->address == other.address;
146 bool operator!=(
const GrpcLBAddress& other)
const {
147 return !(*
this == other);
154 vector<GrpcLBAddress> ParseExpectedAddrs(
std::string expected_addrs) {
155 std::vector<GrpcLBAddress>
out;
156 while (!expected_addrs.empty()) {
158 size_t next_comma = expected_addrs.find(
',');
159 if (next_comma == std::string::npos) {
161 "Missing ','. Expected_addrs arg should be a semicolon-separated "
162 "list of <ip-port>,<bool> pairs. Left-to-be-parsed arg is |%s|",
163 expected_addrs.c_str());
166 std::string next_addr = expected_addrs.substr(0, next_comma);
167 expected_addrs = expected_addrs.substr(next_comma + 1, std::string::npos);
169 size_t next_semicolon = expected_addrs.find(
';');
170 bool is_balancer =
false;
173 out.emplace_back(GrpcLBAddress(next_addr, is_balancer));
174 if (next_semicolon == std::string::npos) {
178 expected_addrs.substr(next_semicolon + 1, std::string::npos);
182 "expected_addrs arg should be a semicolon-separated list of "
183 "<ip-port>,<bool> pairs");
199 std::shared_ptr<grpc_core::WorkSerializer> lock;
201 vector<GrpcLBAddress> expected_addrs;
207 void ArgsInit(ArgsStruct*
args) {
213 args->lock = std::make_shared<grpc_core::WorkSerializer>();
215 args->channel_args =
nullptr;
220 void ArgsFinish(ArgsStruct*
args) {
226 grpc_schedule_on_exec_ctx);
240 void PollPollsetUntilRequestDone(ArgsStruct*
args) {
268 void CheckServiceConfigResultLocked(
const char* service_config_json,
271 if (!
args->expected_service_config_string.empty()) {
273 EXPECT_EQ(service_config_json,
args->expected_service_config_string);
275 if (
args->expected_service_config_error.empty()) {
287 if (!
args->expected_lb_policy.empty()) {
297 void OpenAndCloseSocketsStressLoop(
int phony_port,
gpr_event* done_ev) {
301 addr.sin6_port = htons(phony_port);
302 ((
char*)&
addr.sin6_addr)[15] = 1;
308 for (
size_t i = 0;
i < 50;
i++) {
309 SOCKET
s = WSASocket(
AF_INET6, SOCK_STREAM, IPPROTO_TCP,
nullptr, 0,
310 WSA_FLAG_OVERLAPPED);
312 <<
"Failed to create TCP ipv6 socket";
315 ASSERT_TRUE(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val,
sizeof(val)) !=
317 <<
"Failed to set socketopt reuseaddr. WSA error: " +
320 <<
"Failed to set socket non-blocking";
335 <<
"Accept on phony socket unexpectedly accepted actual connection.";
337 <<
"OpenAndCloseSocketsStressLoop accept on socket " +
340 "an unexpected way. "
343 ". Socket use-after-close bugs are likely.";
352 void OpenAndCloseSocketsStressLoop(
int phony_port,
gpr_event* done_ev) {
367 addr.sin6_port = htons(phony_port);
368 (
reinterpret_cast<char*
>(&
addr.sin6_addr))[15] = 1;
377 for (
size_t i = 0;
i < 50;
i++) {
380 ASSERT_TRUE(setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val,
sizeof(val)) ==
382 <<
"Failed to set socketopt reuseport";
383 ASSERT_TRUE(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val,
sizeof(val)) ==
385 <<
"Failed to set socket reuseaddr";
387 <<
"Failed to set socket non-blocking";
389 <<
"Failed to create TCP ipv6 socket";
404 if (accept(
sockets[
i],
nullptr,
nullptr)) {
407 ASSERT_TRUE(errno == EAGAIN || errno == EWOULDBLOCK)
408 <<
"OpenAndCloseSocketsStressLoop accept on socket " +
411 "an unexpected way. "
414 ". Socket use-after-close bugs are likely.";
426 static std::unique_ptr<grpc_core::Resolver::ResultHandler> Create(
428 return std::unique_ptr<grpc_core::Resolver::ResultHandler>(
454 static std::unique_ptr<grpc_core::Resolver::ResultHandler> Create(
456 return std::unique_ptr<grpc_core::Resolver::ResultHandler>(
457 new CheckingResultHandler(
args));
465 std::vector<GrpcLBAddress> found_lb_addrs;
466 AddActualAddresses(*
result.addresses,
false,
470 if (balancer_addresses !=
nullptr) {
471 AddActualAddresses(*balancer_addresses,
true,
475 "found %" PRIdPTR
" backend addresses and %" PRIdPTR
476 " balancer addresses",
478 balancer_addresses ==
nullptr ? 0
L : balancer_addresses->size());
479 if (
args->expected_addrs.size() != found_lb_addrs.size()) {
481 "found lb addrs size is: %" PRIdPTR
482 ". expected addrs size is %" PRIdPTR,
483 found_lb_addrs.size(),
args->expected_addrs.size());
486 if (
absl::GetFlag(FLAGS_do_ordered_address_comparison) ==
"True") {
488 }
else if (
absl::GetFlag(FLAGS_do_ordered_address_comparison) ==
"False") {
493 "Invalid for setting for --do_ordered_address_comparison. "
494 "Have %s, want True or False",
498 if (!
result.service_config.ok()) {
499 CheckServiceConfigResultLocked(
nullptr,
result.service_config.status(),
501 }
else if (*
result.service_config ==
nullptr) {
504 CheckServiceConfigResultLocked(
508 if (
args->expected_service_config_string.empty()) {
516 std::vector<GrpcLBAddress>*
out) {
517 for (
size_t i = 0;
i < addresses.size();
i++) {
528 int g_fake_non_responsive_dns_server_port = -1;
536 memset(dns_server_addrs, 0,
sizeof(dns_server_addrs));
541 &local_dns_server_port));
543 "Injecting broken nameserver list. Bad server address:|[::1]:%d|. "
544 "Good server address:%s",
545 g_fake_non_responsive_dns_server_port,
548 dns_server_addrs[0].family =
AF_INET6;
549 (
reinterpret_cast<char*
>(&dns_server_addrs[0].addr.addr6))[15] = 0x1;
550 dns_server_addrs[0].tcp_port = g_fake_non_responsive_dns_server_port;
551 dns_server_addrs[0].udp_port = g_fake_non_responsive_dns_server_port;
552 dns_server_addrs[0].next = &dns_server_addrs[1];
557 dns_server_addrs[1].family = AF_INET;
558 (
reinterpret_cast<char*
>(&dns_server_addrs[1].addr.addr4))[0] = 0x7f;
559 (
reinterpret_cast<char*
>(&dns_server_addrs[1].addr.addr4))[3] = 0x1;
560 dns_server_addrs[1].tcp_port = atoi(local_dns_server_port.c_str());
561 dns_server_addrs[1].udp_port = atoi(local_dns_server_port.c_str());
562 dns_server_addrs[1].next =
nullptr;
568 void RunResolvesRelevantRecordsTest(
569 std::unique_ptr<grpc_core::Resolver::ResultHandler> (*CreateResultHandler)(
575 args.expected_service_config_string =
577 args.expected_service_config_error =
583 "resolver_component_test: --inject_broken_nameserver_list: %s",
585 std::unique_ptr<grpc_core::testing::FakeUdpAndTcpServer>
586 fake_non_responsive_dns_server;
587 if (
absl::GetFlag(FLAGS_inject_broken_nameserver_list) ==
"True") {
593 g_fake_non_responsive_dns_server_port =
594 fake_non_responsive_dns_server->
port();
597 }
else if (
absl::GetFlag(FLAGS_inject_broken_nameserver_list) ==
"False") {
618 }
else if (
absl::GetFlag(FLAGS_enable_srv_queries) !=
"False") {
637 resolver_args = tmp_args;
638 }
else if (
absl::GetFlag(FLAGS_enable_txt_queries) !=
"False") {
645 whole_uri.c_str(), resolver_args,
args.pollset_set,
args.lock,
646 CreateResultHandler(&
args));
648 auto* resolver_ptr = resolver.get();
649 args.lock->Run([resolver_ptr]() { StartResolvingLocked(resolver_ptr); },
652 PollPollsetUntilRequestDone(&
args);
656 TEST(ResolverComponentTest, TestResolvesRelevantRecords) {
657 RunResolvesRelevantRecordsTest(CheckingResultHandler::Create);
660 TEST(ResolverComponentTest, TestResolvesRelevantRecordsWithConcurrentFdStress) {
665 std::thread socket_stress_thread(OpenAndCloseSocketsStressLoop, phony_port,
668 RunResolvesRelevantRecordsTest(ResultHandler::Create);
671 socket_stress_thread.join();
676 int main(
int argc,
char** argv) {