Commit 2570f273 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1539] test other network parameters than UDP/IPv4.

parent 5cda9e72
......@@ -150,12 +150,16 @@ protected:
void createAndSendRequest(RRType req_type, Opcode opcode = Opcode::QUERY(),
const Name& req_name = Name("example.com"),
RRClass req_class = RRClass::IN(),
int protocol = IPPROTO_UDP)
int protocol = IPPROTO_UDP,
const char* const remote_address =
DEFAULT_REMOTE_ADDRESS,
uint16_t remote_port = DEFAULT_REMOTE_PORT)
{
UnitTestUtil::createRequestMessage(request_message, opcode,
default_qid, req_name,
req_class, req_type);
createRequestPacket(request_message, protocol);
createRequestPacket(request_message, protocol, NULL,
remote_address, remote_port);
parse_message->clear(Message::PARSE);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
......@@ -1421,7 +1425,7 @@ TEST_F(AuthSrvTest, queryWithThrowingInToWire) {
// in practice it should be reliable.
void
checkAddrPort(const struct sockaddr& actual_sa,
const string& expected_addr, const string& expected_port)
const string& expected_addr, uint16_t expected_port)
{
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
const int error = getnameinfo(&actual_sa, actual_sa.sa_len, hbuf,
......@@ -1432,28 +1436,43 @@ checkAddrPort(const struct sockaddr& actual_sa,
gai_strerror(error));
}
EXPECT_EQ(expected_addr, hbuf);
EXPECT_EQ(expected_port, sbuf);
EXPECT_EQ(boost::lexical_cast<string>(expected_port), sbuf);
}
TEST_F(AuthSrvTest, DDNSForward) {
EXPECT_FALSE(ddns_forwarder.isConnected());
// Repeat sending an update request two times. By doing that we'll
// confirm the forwarder connection will be established exactly once,
// and kept established.
for (size_t i = 0; i < 2; ++i) {
// Use different names for each iteration
const Name zone_name = Name(i == 0 ? "example.com" : "example.org");
createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), zone_name);
// Repeat sending an update request 4 times, differing some network
// parameters: UDP/IPv4, TCP/IPv4, UDP/IPv6, TCP/IPv6, in this order.
// By doing that we can also confirm the forwarder connection will be
// established exactly once, and kept established.
for (size_t i = 0; i < 4; ++i) {
// Use different names for some different cases
const Name zone_name = Name(i < 2 ? "example.com" : "example.org");
const socklen_t family = (i < 2) ? AF_INET : AF_INET6;
const char* const remote_addr =
(family == AF_INET) ? "192.0.2.1" : "2001:db8::1";
const uint16_t remote_port =
(family == AF_INET) ? 53214 : 53216;
const int protocol = ((i % 2) == 0) ? IPPROTO_UDP : IPPROTO_TCP;
createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), zone_name,
RRClass::IN(), protocol, remote_addr,
remote_port);
EXPECT_FALSE(dnsserv.hasAnswer());
EXPECT_TRUE(ddns_forwarder.isConnected());
// Examine the pushed data
EXPECT_EQ(AF_INET, ddns_forwarder.getPushedFamily());
EXPECT_EQ(SOCK_DGRAM, ddns_forwarder.getPushedType());
EXPECT_EQ(IPPROTO_UDP, ddns_forwarder.getPushedProtocol());
// Examine the pushed data (note: currently "local end" has a dummy
// value equal to remote)
EXPECT_EQ(family, ddns_forwarder.getPushedFamily());
const int expected_type =
(protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
EXPECT_EQ(expected_type, ddns_forwarder.getPushedType());
EXPECT_EQ(protocol, ddns_forwarder.getPushedProtocol());
checkAddrPort(ddns_forwarder.getPushedRemoteend(),
DEFAULT_REMOTE_ADDRESS, "53210");
remote_addr, remote_port);
checkAddrPort(ddns_forwarder.getPushedLocalend(),
remote_addr, remote_port);
EXPECT_EQ(io_message->getDataSize(),
ddns_forwarder.getPushedData().size());
EXPECT_EQ(0, memcmp(io_message->getData(),
......
......@@ -34,6 +34,7 @@ using namespace isc::asiolink;
namespace isc {
namespace testutils {
const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
const uint16_t DEFAULT_REMOTE_PORT = 53210;
SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
parse_message(new Message(Message::PARSE)),
......@@ -62,7 +63,8 @@ SrvTestBase::createDataFromFile(const char* const datafile,
delete endpoint;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 53210);
IOAddress(DEFAULT_REMOTE_ADDRESS),
DEFAULT_REMOTE_PORT);
UnitTestUtil::readWireData(datafile, data);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
......@@ -71,7 +73,9 @@ SrvTestBase::createDataFromFile(const char* const datafile,
void
SrvTestBase::createRequestPacket(Message& message,
const int protocol, TSIGContext* context)
const int protocol, TSIGContext* context,
const char* const remote_address,
uint16_t remote_port)
{
if (context == NULL) {
message.toWire(request_renderer);
......@@ -81,8 +85,8 @@ SrvTestBase::createRequestPacket(Message& message,
delete io_message;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 53210);
endpoint = IOEndpoint::create(protocol, IOAddress(remote_address),
remote_port);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
......
......@@ -35,6 +35,7 @@ class IOEndpoint;
namespace isc {
namespace testutils {
extern const char* const DEFAULT_REMOTE_ADDRESS;
extern const uint16_t DEFAULT_REMOTE_PORT;
// These are flags to indicate whether the corresponding flag bit of the
// DNS header is to be set in the test cases. (The flag values
......@@ -88,7 +89,9 @@ protected:
/// The existing content of \c io_message, if any, will be deleted.
void createRequestPacket(isc::dns::Message& message,
const int protocol = IPPROTO_UDP,
isc::dns::TSIGContext* context = NULL);
isc::dns::TSIGContext* context = NULL,
const char* const address = DEFAULT_REMOTE_ADDRESS,
uint16_t port = DEFAULT_REMOTE_PORT);
MockSession notify_session;
MockServer dnsserv;
......
......@@ -25,6 +25,7 @@
#include <vector>
#include <sys/socket.h>
#include <stdint.h>
namespace isc {
namespace util {
......@@ -53,6 +54,11 @@ public:
virtual void close() {
is_connected_ = false;
}
// Pushing a socket session. It copies the given session data
// so that the test code can check the values later via the getter
// methods. Complete deep copy will be created, so the caller doesn't
// have to keep the parameters valid after the call to this method.
virtual void push(int sock, int family, int type, int protocol,
const struct sockaddr& local_end,
const struct sockaddr& remote_end,
......@@ -68,7 +74,6 @@ public:
pushed_family_ = family;
pushed_type_ = type;
pushed_protocol_ = protocol;
assert(remote_end.sa_family == AF_INET);
assert(io::internal::getSALength(local_end) <=
sizeof(pushed_local_end_ss_));
std::memcpy(&pushed_local_end_ss_, &local_end,
......@@ -80,7 +85,12 @@ public:
pushed_data_.resize(data_len);
std::memcpy(&pushed_data_[0], data, data_len);
}
// Allow the test code to check if the connection is established.
bool isConnected() const { return (is_connected_); }
// Allow the test code to customize the forwarder behavior wrt whether
// a specific operation should succeed or fail.
void disableConnect() { connect_ok_ = false; }
void enableConnect() { connect_ok_ = true; }
void disableClose() { close_ok_ = false; }
......@@ -100,7 +110,9 @@ public:
const struct sockaddr& getPushedRemoteend() const {
return (*io::internal::convertSockAddr(&pushed_remote_end_ss_));
}
const std::vector<uint8_t> getPushedData() const { return (pushed_data_); }
const std::vector<uint8_t>& getPushedData() const {
return (pushed_data_);
}
private:
bool is_connected_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment