Change MockDNS to DNSCache.
This commit is contained in:
parent
ebe928e7e1
commit
ff934ca2ad
|
@ -67,97 +67,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool MockDNS::findMockTCPEndpoint(const std::string& host, const std::string& service) {
|
||||
std::string hostname = host + ":" + service;
|
||||
return hostnameToAddresses.find(hostname) != hostnameToAddresses.end();
|
||||
}
|
||||
|
||||
void MockDNS::addMockTCPEndpoint(const std::string& host,
|
||||
const std::string& service,
|
||||
const std::vector<NetworkAddress>& addresses) {
|
||||
if (findMockTCPEndpoint(host, service)) {
|
||||
throw operation_failed();
|
||||
}
|
||||
hostnameToAddresses[host + ":" + service] = addresses;
|
||||
}
|
||||
|
||||
void MockDNS::updateMockTCPEndpoint(const std::string& host,
|
||||
const std::string& service,
|
||||
const std::vector<NetworkAddress>& addresses) {
|
||||
if (!findMockTCPEndpoint(host, service)) {
|
||||
throw operation_failed();
|
||||
}
|
||||
hostnameToAddresses[host + ":" + service] = addresses;
|
||||
}
|
||||
|
||||
void MockDNS::removeMockTCPEndpoint(const std::string& host, const std::string& service) {
|
||||
if (!findMockTCPEndpoint(host, service)) {
|
||||
throw operation_failed();
|
||||
}
|
||||
hostnameToAddresses.erase(host + ":" + service);
|
||||
}
|
||||
|
||||
std::vector<NetworkAddress> MockDNS::getTCPEndpoint(const std::string& host, const std::string& service) {
|
||||
if (!findMockTCPEndpoint(host, service)) {
|
||||
throw operation_failed();
|
||||
}
|
||||
return hostnameToAddresses[host + ":" + service];
|
||||
}
|
||||
|
||||
void MockDNS::clearMockTCPEndpoints() {
|
||||
hostnameToAddresses.clear();
|
||||
}
|
||||
|
||||
std::string MockDNS::toString() {
|
||||
std::string ret;
|
||||
for (auto it = hostnameToAddresses.begin(); it != hostnameToAddresses.end(); ++it) {
|
||||
if (it != hostnameToAddresses.begin()) {
|
||||
ret += ';';
|
||||
}
|
||||
ret += it->first + ',';
|
||||
const std::vector<NetworkAddress>& addresses = it->second;
|
||||
for (int i = 0; i < addresses.size(); ++i) {
|
||||
ret += addresses[i].toString();
|
||||
if (i != addresses.size() - 1) {
|
||||
ret += ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MockDNS MockDNS::parseFromString(const std::string& s) {
|
||||
std::map<std::string, std::vector<NetworkAddress>> mockDNS;
|
||||
|
||||
for (int p = 0; p < s.length();) {
|
||||
int pSemiColumn = s.find_first_of(';', p);
|
||||
if (pSemiColumn == s.npos) {
|
||||
pSemiColumn = s.length();
|
||||
}
|
||||
std::string oneMapping = s.substr(p, pSemiColumn - p);
|
||||
|
||||
std::string hostname;
|
||||
std::vector<NetworkAddress> addresses;
|
||||
for (int i = 0; i < oneMapping.length();) {
|
||||
int pComma = oneMapping.find_first_of(',', i);
|
||||
if (pComma == oneMapping.npos) {
|
||||
pComma = oneMapping.length();
|
||||
}
|
||||
if (!i) {
|
||||
// The first part is hostname
|
||||
hostname = oneMapping.substr(i, pComma - i);
|
||||
} else {
|
||||
addresses.push_back(NetworkAddress::parse(oneMapping.substr(i, pComma - i)));
|
||||
}
|
||||
i = pComma + 1;
|
||||
}
|
||||
mockDNS[hostname] = addresses;
|
||||
p = pSemiColumn + 1;
|
||||
}
|
||||
|
||||
return MockDNS(mockDNS);
|
||||
}
|
||||
|
||||
void SimExternalConnection::close() {
|
||||
socket.close();
|
||||
}
|
||||
|
@ -312,51 +221,6 @@ TEST_CASE("fdbrpc/SimExternalClient") {
|
|||
}
|
||||
|
||||
TEST_CASE("fdbrpc/MockDNS") {
|
||||
state MockDNS mockDNS;
|
||||
state std::vector<NetworkAddress> networkAddresses;
|
||||
state NetworkAddress address1(IPAddress(0x13131313), 1);
|
||||
state NetworkAddress address2(IPAddress(0x14141414), 2);
|
||||
networkAddresses.push_back(address1);
|
||||
networkAddresses.push_back(address2);
|
||||
mockDNS.addMockTCPEndpoint("testhost1", "port1", networkAddresses);
|
||||
ASSERT(mockDNS.findMockTCPEndpoint("testhost1", "port1"));
|
||||
ASSERT(!mockDNS.findMockTCPEndpoint("testhost1", "port2"));
|
||||
std::vector<NetworkAddress> resolvedNetworkAddresses = mockDNS.getTCPEndpoint("testhost1", "port1");
|
||||
ASSERT(resolvedNetworkAddresses.size() == 2);
|
||||
ASSERT(std::find(resolvedNetworkAddresses.begin(), resolvedNetworkAddresses.end(), address1) !=
|
||||
resolvedNetworkAddresses.end());
|
||||
ASSERT(std::find(resolvedNetworkAddresses.begin(), resolvedNetworkAddresses.end(), address2) !=
|
||||
resolvedNetworkAddresses.end());
|
||||
// Adding a hostname twice should fail.
|
||||
try {
|
||||
mockDNS.addMockTCPEndpoint("testhost1", "port1", networkAddresses);
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
// Updating an unexisted hostname should fail.
|
||||
try {
|
||||
mockDNS.updateMockTCPEndpoint("testhost2", "port2", networkAddresses);
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
// Removing an unexisted hostname should fail.
|
||||
try {
|
||||
mockDNS.removeMockTCPEndpoint("testhost2", "port2");
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
mockDNS.clearMockTCPEndpoints();
|
||||
// Updating any hostname right after clearing endpoints should fail.
|
||||
try {
|
||||
mockDNS.updateMockTCPEndpoint("testhost1", "port1", networkAddresses);
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("fdbrpc/MockTCPEndpoints") {
|
||||
state std::vector<NetworkAddress> networkAddresses;
|
||||
state NetworkAddress address1(IPAddress(0x13131313), 1);
|
||||
networkAddresses.push_back(address1);
|
||||
|
@ -366,18 +230,6 @@ TEST_CASE("fdbrpc/MockTCPEndpoints") {
|
|||
ASSERT(resolvedNetworkAddresses.size() == 1);
|
||||
ASSERT(std::find(resolvedNetworkAddresses.begin(), resolvedNetworkAddresses.end(), address1) !=
|
||||
resolvedNetworkAddresses.end());
|
||||
// Adding a hostname twice should fail.
|
||||
try {
|
||||
INetworkConnections::net()->addMockTCPEndpoint("testhost1", "port1", networkAddresses);
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
// Removing an unexisted hostname should fail.
|
||||
try {
|
||||
INetworkConnections::net()->removeMockTCPEndpoint("testhost2", "port2");
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_operation_failed);
|
||||
}
|
||||
INetworkConnections::net()->removeMockTCPEndpoint("testhost1", "port1");
|
||||
state NetworkAddress address2(IPAddress(0x14141414), 2);
|
||||
networkAddresses.push_back(address2);
|
||||
|
@ -390,21 +242,4 @@ TEST_CASE("fdbrpc/MockTCPEndpoints") {
|
|||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("fdbrpc/MockDNSParsing") {
|
||||
std::string mockDNSString;
|
||||
INetworkConnections::net()->parseMockDNSFromString(mockDNSString);
|
||||
ASSERT(INetworkConnections::net()->convertMockDNSToString() == mockDNSString);
|
||||
|
||||
mockDNSString = "testhost1:port1,[::1]:4800:tls(fromHostname)";
|
||||
INetworkConnections::net()->parseMockDNSFromString(mockDNSString);
|
||||
ASSERT(INetworkConnections::net()->convertMockDNSToString() == mockDNSString);
|
||||
|
||||
mockDNSString = "testhost1:port1,[::1]:4800,[2001:db8:85a3::8a2e:370:7334]:4800;testhost2:port2,[2001:"
|
||||
"db8:85a3::8a2e:370:7334]:4800:tls(fromHostname),8.8.8.8:12";
|
||||
INetworkConnections::net()->parseMockDNSFromString(mockDNSString);
|
||||
ASSERT(INetworkConnections::net()->convertMockDNSToString() == mockDNSString);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
void forceLinkSimExternalConnectionTests() {}
|
||||
|
|
|
@ -28,34 +28,6 @@
|
|||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
// MockDNS is a class maintaining a <hostname, vector<NetworkAddress>> mapping, mocking a DNS in simulation.
|
||||
class MockDNS {
|
||||
public:
|
||||
MockDNS() {}
|
||||
explicit MockDNS(const std::map<std::string, std::vector<NetworkAddress>>& mockDNS)
|
||||
: hostnameToAddresses(mockDNS) {}
|
||||
|
||||
bool findMockTCPEndpoint(const std::string& host, const std::string& service);
|
||||
void addMockTCPEndpoint(const std::string& host,
|
||||
const std::string& service,
|
||||
const std::vector<NetworkAddress>& addresses);
|
||||
void updateMockTCPEndpoint(const std::string& host,
|
||||
const std::string& service,
|
||||
const std::vector<NetworkAddress>& addresses);
|
||||
void removeMockTCPEndpoint(const std::string& host, const std::string& service);
|
||||
void clearMockTCPEndpoints();
|
||||
std::vector<NetworkAddress> getTCPEndpoint(const std::string& host, const std::string& service);
|
||||
|
||||
void operator=(MockDNS const& rhs) { hostnameToAddresses = rhs.hostnameToAddresses; }
|
||||
// Convert hostnameToAddresses to string. The format is:
|
||||
// hostname1,host1Address1,host1Address2;hostname2,host2Address1,host2Address2...
|
||||
std::string toString();
|
||||
static MockDNS parseFromString(const std::string& s);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<NetworkAddress>> hostnameToAddresses;
|
||||
};
|
||||
|
||||
class SimExternalConnection final : public IConnection, public ReferenceCounted<SimExternalConnection> {
|
||||
boost::asio::ip::tcp::socket socket;
|
||||
SimExternalConnection(boost::asio::ip::tcp::socket&& socket);
|
||||
|
|
|
@ -965,28 +965,30 @@ public:
|
|||
void addMockTCPEndpoint(const std::string& host,
|
||||
const std::string& service,
|
||||
const std::vector<NetworkAddress>& addresses) override {
|
||||
mockDNS.addMockTCPEndpoint(host, service, addresses);
|
||||
mockDNS.add(host, service, addresses);
|
||||
}
|
||||
void removeMockTCPEndpoint(const std::string& host, const std::string& service) override {
|
||||
mockDNS.removeMockTCPEndpoint(host, service);
|
||||
mockDNS.remove(host, service);
|
||||
}
|
||||
// Convert hostnameToAddresses from/to string. The format is:
|
||||
// hostname1,host1Address1,host1Address2;hostname2,host2Address1,host2Address2...
|
||||
void parseMockDNSFromString(const std::string& s) override { mockDNS = MockDNS::parseFromString(s); }
|
||||
void parseMockDNSFromString(const std::string& s) override { mockDNS = DNSCache::parseFromString(s); }
|
||||
std::string convertMockDNSToString() override { return mockDNS.toString(); }
|
||||
Future<std::vector<NetworkAddress>> resolveTCPEndpoint(const std::string& host,
|
||||
const std::string& service) override {
|
||||
// If a <hostname, vector<NetworkAddress>> pair was injected to mock DNS, use it.
|
||||
if (mockDNS.findMockTCPEndpoint(host, service)) {
|
||||
return mockDNS.getTCPEndpoint(host, service);
|
||||
Optional<std::vector<NetworkAddress>> mock = mockDNS.find(host, service);
|
||||
if (mock.present()) {
|
||||
return mock.get();
|
||||
}
|
||||
return SimExternalConnection::resolveTCPEndpoint(host, service);
|
||||
}
|
||||
std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host,
|
||||
const std::string& service) override {
|
||||
// If a <hostname, vector<NetworkAddress>> pair was injected to mock DNS, use it.
|
||||
if (mockDNS.findMockTCPEndpoint(host, service)) {
|
||||
return mockDNS.getTCPEndpoint(host, service);
|
||||
Optional<std::vector<NetworkAddress>> mock = mockDNS.find(host, service);
|
||||
if (mock.present()) {
|
||||
return mock.get();
|
||||
}
|
||||
return SimExternalConnection::resolveTCPEndpointBlocking(host, service);
|
||||
}
|
||||
|
@ -2193,7 +2195,7 @@ public:
|
|||
bool printSimTime;
|
||||
|
||||
private:
|
||||
MockDNS mockDNS;
|
||||
DNSCache mockDNS;
|
||||
|
||||
#ifdef ENABLE_SAMPLING
|
||||
ActorLineageSet actorLineageSet;
|
||||
|
|
111
flow/network.cpp
111
flow/network.cpp
|
@ -178,6 +178,117 @@ std::string formatIpPort(const IPAddress& ip, uint16_t port) {
|
|||
return format(patt, ip.toString().c_str(), port);
|
||||
}
|
||||
|
||||
Optional<std::vector<NetworkAddress>> DNSCache::find(const std::string& host, const std::string& service) {
|
||||
std::string hostname = host + ":" + service;
|
||||
if (hostnameToAddresses.find(hostname) != hostnameToAddresses.end()) {
|
||||
return hostnameToAddresses[host + ":" + service];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void DNSCache::add(const std::string& host, const std::string& service, const std::vector<NetworkAddress>& addresses) {
|
||||
hostnameToAddresses[host + ":" + service] = addresses;
|
||||
}
|
||||
|
||||
void DNSCache::remove(const std::string& host, const std::string& service) {
|
||||
if (find(host, service).present()) {
|
||||
hostnameToAddresses.erase(host + ":" + service);
|
||||
}
|
||||
}
|
||||
|
||||
void DNSCache::clear() {
|
||||
hostnameToAddresses.clear();
|
||||
}
|
||||
|
||||
std::string DNSCache::toString() {
|
||||
std::string ret;
|
||||
for (auto it = hostnameToAddresses.begin(); it != hostnameToAddresses.end(); ++it) {
|
||||
if (it != hostnameToAddresses.begin()) {
|
||||
ret += ';';
|
||||
}
|
||||
ret += it->first + ',';
|
||||
const std::vector<NetworkAddress>& addresses = it->second;
|
||||
for (int i = 0; i < addresses.size(); ++i) {
|
||||
ret += addresses[i].toString();
|
||||
if (i != addresses.size() - 1) {
|
||||
ret += ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DNSCache DNSCache::parseFromString(const std::string& s) {
|
||||
std::map<std::string, std::vector<NetworkAddress>> dnsCache;
|
||||
|
||||
for (int p = 0; p < s.length();) {
|
||||
int pSemiColumn = s.find_first_of(';', p);
|
||||
if (pSemiColumn == s.npos) {
|
||||
pSemiColumn = s.length();
|
||||
}
|
||||
std::string oneMapping = s.substr(p, pSemiColumn - p);
|
||||
|
||||
std::string hostname;
|
||||
std::vector<NetworkAddress> addresses;
|
||||
for (int i = 0; i < oneMapping.length();) {
|
||||
int pComma = oneMapping.find_first_of(',', i);
|
||||
if (pComma == oneMapping.npos) {
|
||||
pComma = oneMapping.length();
|
||||
}
|
||||
if (!i) {
|
||||
// The first part is hostname
|
||||
hostname = oneMapping.substr(i, pComma - i);
|
||||
} else {
|
||||
addresses.push_back(NetworkAddress::parse(oneMapping.substr(i, pComma - i)));
|
||||
}
|
||||
i = pComma + 1;
|
||||
}
|
||||
dnsCache[hostname] = addresses;
|
||||
p = pSemiColumn + 1;
|
||||
}
|
||||
|
||||
return DNSCache(dnsCache);
|
||||
}
|
||||
|
||||
TEST_CASE("/flow/DNSCache") {
|
||||
DNSCache dnsCache;
|
||||
std::vector<NetworkAddress> networkAddresses;
|
||||
NetworkAddress address1(IPAddress(0x13131313), 1), address2(IPAddress(0x14141414), 2);
|
||||
networkAddresses.push_back(address1);
|
||||
networkAddresses.push_back(address2);
|
||||
dnsCache.add("testhost1", "port1", networkAddresses);
|
||||
ASSERT(dnsCache.find("testhost1", "port1").present());
|
||||
ASSERT(!dnsCache.find("testhost1", "port2").present());
|
||||
std::vector<NetworkAddress> resolvedNetworkAddresses = dnsCache.find("testhost1", "port1").get();
|
||||
ASSERT(resolvedNetworkAddresses.size() == 2);
|
||||
ASSERT(std::find(resolvedNetworkAddresses.begin(), resolvedNetworkAddresses.end(), address1) !=
|
||||
resolvedNetworkAddresses.end());
|
||||
ASSERT(std::find(resolvedNetworkAddresses.begin(), resolvedNetworkAddresses.end(), address2) !=
|
||||
resolvedNetworkAddresses.end());
|
||||
dnsCache.remove("testhost1", "port1");
|
||||
ASSERT(!dnsCache.find("testhost1", "port1").present());
|
||||
dnsCache.add("testhost1", "port2", networkAddresses);
|
||||
ASSERT(dnsCache.find("testhost1", "port2").present());
|
||||
dnsCache.clear();
|
||||
ASSERT(!dnsCache.find("testhost1", "port2").present());
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("/flow/DNSCacheParsing") {
|
||||
std::string dnsCacheString;
|
||||
ASSERT(DNSCache::parseFromString(dnsCacheString).toString() == dnsCacheString);
|
||||
|
||||
dnsCacheString = "testhost1:port1,[::1]:4800:tls(fromHostname)";
|
||||
ASSERT(DNSCache::parseFromString(dnsCacheString).toString() == dnsCacheString);
|
||||
|
||||
dnsCacheString = "testhost1:port1,[::1]:4800,[2001:db8:85a3::8a2e:370:7334]:4800;testhost2:port2,[2001:db8:85a3::"
|
||||
"8a2e:370:7334]:4800:tls(fromHostname),8.8.8.8:12";
|
||||
ASSERT(DNSCache::parseFromString(dnsCacheString).toString() == dnsCacheString);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Future<Reference<IConnection>> INetworkConnections::connect(const std::string& host,
|
||||
const std::string& service,
|
||||
bool isTLS) {
|
||||
|
|
|
@ -697,6 +697,27 @@ public:
|
|||
virtual boost::asio::ip::udp::socket::native_handle_type native_handle() = 0;
|
||||
};
|
||||
|
||||
// DNSCache is a class maintaining a <hostname, vector<NetworkAddress>> mapping.
|
||||
class DNSCache {
|
||||
public:
|
||||
DNSCache() {}
|
||||
explicit DNSCache(const std::map<std::string, std::vector<NetworkAddress>>& dnsCache)
|
||||
: hostnameToAddresses(dnsCache) {}
|
||||
|
||||
Optional<std::vector<NetworkAddress>> find(const std::string& host, const std::string& service);
|
||||
void add(const std::string& host, const std::string& service, const std::vector<NetworkAddress>& addresses);
|
||||
void remove(const std::string& host, const std::string& service);
|
||||
void clear();
|
||||
|
||||
// Convert hostnameToAddresses to string. The format is:
|
||||
// hostname1,host1Address1,host1Address2;hostname2,host2Address1,host2Address2...
|
||||
std::string toString();
|
||||
static DNSCache parseFromString(const std::string& s);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<NetworkAddress>> hostnameToAddresses;
|
||||
};
|
||||
|
||||
class INetworkConnections {
|
||||
public:
|
||||
// Methods for making and accepting network connections. Logically this is part of the INetwork abstraction
|
||||
|
|
Loading…
Reference in New Issue