Tests should use dynamic system-assigned ports rather than static port (#346)

The c-ares test suite was hardcoded to use port 5300 (and possibly 5301, 5302) for the test suite.  Especially in containers, there may be no guarantee these ports are available and cause tests to fail when they could otherwise succeed.  Instead, request the system to assign a port to use dynamically.  This is now the default.  To override, the test suite still takes the "-p <port>" option as it always has and will honor that.

Fix By: Anthony Penniston (@apenn-msft)
pull/94/head^2
apenn-msft 4 years ago committed by GitHub
parent bd215c43a9
commit 5b246d2077
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ares__sortaddrinfo.c
  2. 44
      test/ares-test.cc
  3. 2
      test/ares-test.h

@ -427,7 +427,7 @@ static int find_src_addr(ares_channel channel,
return 0; return 0;
} }
if (getsockname(sock, src_addr, &len) == -1) if (getsockname(sock, src_addr, &len) != 0)
{ {
ares__close_socket(channel, sock); ares__close_socket(channel, sock);
return -1; return -1;

@ -30,7 +30,8 @@ namespace ares {
namespace test { namespace test {
bool verbose = false; bool verbose = false;
int mock_port = 5300; static constexpr int dynamic_port = 0;
int mock_port = dynamic_port;
const std::vector<int> both_families = {AF_INET, AF_INET6}; const std::vector<int> both_families = {AF_INET, AF_INET6};
const std::vector<int> ipv4_family = {AF_INET}; const std::vector<int> ipv4_family = {AF_INET};
@ -169,8 +170,8 @@ void DefaultChannelModeTest::Process() {
ProcessWork(channel_, NoExtraFDs, nullptr); ProcessWork(channel_, NoExtraFDs, nullptr);
} }
MockServer::MockServer(int family, int port, int tcpport) MockServer::MockServer(int family, int port)
: udpport_(port), tcpport_(tcpport ? tcpport : udpport_), qid_(-1) { : udpport_(port), tcpport_(port), qid_(-1) {
// Create a TCP socket to receive data on. // Create a TCP socket to receive data on.
tcpfd_ = socket(family, SOCK_STREAM, 0); tcpfd_ = socket(family, SOCK_STREAM, 0);
EXPECT_NE(-1, tcpfd_); EXPECT_NE(-1, tcpfd_);
@ -197,6 +198,21 @@ MockServer::MockServer(int family, int port, int tcpport)
addr.sin_port = htons(udpport_); addr.sin_port = htons(udpport_);
int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr)); int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
EXPECT_EQ(0, udprc) << "Failed to bind AF_INET to UDP port " << udpport_; EXPECT_EQ(0, udprc) << "Failed to bind AF_INET to UDP port " << udpport_;
// retrieve system-assigned port
if (udpport_ == dynamic_port) {
ares_socklen_t len = sizeof(addr);
auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
EXPECT_EQ(0, result);
udpport_ = ntohs(addr.sin_port);
EXPECT_NE(dynamic_port, udpport_);
}
if (tcpport_ == dynamic_port) {
ares_socklen_t len = sizeof(addr);
auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
EXPECT_EQ(0, result);
tcpport_ = ntohs(addr.sin_port);
EXPECT_NE(dynamic_port, tcpport_);
}
} else { } else {
EXPECT_EQ(AF_INET6, family); EXPECT_EQ(AF_INET6, family);
struct sockaddr_in6 addr; struct sockaddr_in6 addr;
@ -209,6 +225,21 @@ MockServer::MockServer(int family, int port, int tcpport)
addr.sin6_port = htons(udpport_); addr.sin6_port = htons(udpport_);
int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr)); int udprc = bind(udpfd_, (struct sockaddr*)&addr, sizeof(addr));
EXPECT_EQ(0, udprc) << "Failed to bind AF_INET6 to UDP port " << udpport_; EXPECT_EQ(0, udprc) << "Failed to bind AF_INET6 to UDP port " << udpport_;
// retrieve system-assigned port
if (udpport_ == dynamic_port) {
ares_socklen_t len = sizeof(addr);
auto result = getsockname(udpfd_, (struct sockaddr*)&addr, &len);
EXPECT_EQ(0, result);
udpport_ = ntohs(addr.sin6_port);
EXPECT_NE(dynamic_port, udpport_);
}
if (tcpport_ == dynamic_port) {
ares_socklen_t len = sizeof(addr);
auto result = getsockname(tcpfd_, (struct sockaddr*)&addr, &len);
EXPECT_EQ(0, result);
tcpport_ = ntohs(addr.sin6_port);
EXPECT_NE(dynamic_port, tcpport_);
}
} }
if (verbose) std::cerr << "Configured " if (verbose) std::cerr << "Configured "
<< (family == AF_INET ? "IPv4" : "IPv6") << (family == AF_INET ? "IPv4" : "IPv6")
@ -381,7 +412,8 @@ MockChannelOptsTest::NiceMockServers MockChannelOptsTest::BuildServers(int count
NiceMockServers servers; NiceMockServers servers;
assert(count > 0); assert(count > 0);
for (int ii = 0; ii < count; ii++) { for (int ii = 0; ii < count; ii++) {
std::unique_ptr<NiceMockServer> server(new NiceMockServer(family, base_port + ii)); int port = base_port == dynamic_port ? dynamic_port : base_port + ii;
std::unique_ptr<NiceMockServer> server(new NiceMockServer(family, port));
servers.push_back(std::move(server)); servers.push_back(std::move(server));
} }
return servers; return servers;
@ -403,9 +435,9 @@ MockChannelOptsTest::MockChannelOptsTest(int count,
} }
// Point the library at the first mock server by default (overridden below). // Point the library at the first mock server by default (overridden below).
opts.udp_port = mock_port; opts.udp_port = server_.udpport();
optmask |= ARES_OPT_UDP_PORT; optmask |= ARES_OPT_UDP_PORT;
opts.tcp_port = mock_port; opts.tcp_port = server_.tcpport();
optmask |= ARES_OPT_TCP_PORT; optmask |= ARES_OPT_TCP_PORT;
// If not already overridden, set short-ish timeouts. // If not already overridden, set short-ish timeouts.

@ -136,7 +136,7 @@ class DefaultChannelModeTest
// Mock DNS server to allow responses to be scripted by tests. // Mock DNS server to allow responses to be scripted by tests.
class MockServer { class MockServer {
public: public:
MockServer(int family, int port, int tcpport = 0); MockServer(int family, int port);
~MockServer(); ~MockServer();
// Mock method indicating the processing of a particular <name, RRtype> // Mock method indicating the processing of a particular <name, RRtype>

Loading…
Cancel
Save