[svn] commit: r2474 - in /branches/trac221b/src/bin/auth: asio_link.cc asio_link.h tests/asio_link_unittest.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Jul 10 06:37:23 UTC 2010
Author: jinmei
Date: Sat Jul 10 06:37:23 2010
New Revision: 2474
Log:
added tests for specific addresses and "-4/-6" cases.
the tests identified bugs in my previous refactoring, which were fixed.
Modified:
branches/trac221b/src/bin/auth/asio_link.cc
branches/trac221b/src/bin/auth/asio_link.h
branches/trac221b/src/bin/auth/tests/asio_link_unittest.cc
Modified: branches/trac221b/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac221b/src/bin/auth/asio_link.cc (original)
+++ branches/trac221b/src/bin/auth/asio_link.cc Sat Jul 10 06:37:23 2010
@@ -453,7 +453,7 @@
class IOServiceImpl {
public:
IOServiceImpl(AuthSrv* auth_server, const char& port,
- const ip::address& v4addr, const ip::address& v6addr);
+ const ip::address* v4addr, const ip::address* v6addr);
asio::io_service io_service_;
AuthSrv* auth_server_;
@@ -469,8 +469,8 @@
};
IOServiceImpl::IOServiceImpl(AuthSrv* auth_server, const char& port,
- const ip::address& v4addr,
- const ip::address& v6addr) :
+ const ip::address* const v4addr,
+ const ip::address* const v6addr) :
auth_server_(auth_server),
udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
tcp4_server_(TCPServerPtr()), tcp6_server_(TCPServerPtr())
@@ -485,17 +485,17 @@
}
try {
- if (v4addr.is_v4()) {
+ if (v4addr != NULL) {
udp4_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
- v4addr, portnum));
+ *v4addr, portnum));
tcp4_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
- v4addr, portnum));
- }
- if (v6addr.is_v6()) {
+ *v4addr, portnum));
+ }
+ if (v6addr != NULL) {
udp6_server_ = UDPServerPtr(new UDPServer(auth_server, io_service_,
- v6addr, portnum));
+ *v6addr, portnum));
tcp6_server_ = TCPServerPtr(new TCPServer(auth_server, io_service_,
- v6addr, portnum));
+ *v6addr, portnum));
}
} catch (const asio::system_error& err) {
// We need to catch and convert any ASIO level exceptions.
@@ -518,19 +518,19 @@
}
impl_ = new IOServiceImpl(auth_server, port,
- addr.is_v4() ? addr : ip::address::address(),
- addr.is_v6() ? addr : ip::address::address());
+ addr.is_v4() ? &addr : NULL,
+ addr.is_v6() ? &addr : NULL);
}
IOService::IOService(AuthSrv* auth_server, const char& port,
const bool use_ipv4, const bool use_ipv6) :
impl_(NULL)
{
- const ip::address v4addr = use_ipv4 ? ip::address(ip::address_v4::any()) :
- ip::address::address();
- const ip::address v6addr = use_ipv6 ? ip::address(ip::address_v6::any()) :
- ip::address::address();
- impl_ = new IOServiceImpl(auth_server, port, v4addr, v6addr);
+ const ip::address v4addr_any = ip::address(ip::address_v4::any());
+ const ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL;
+ const ip::address v6addr_any = ip::address(ip::address_v6::any());
+ const ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
+ impl_ = new IOServiceImpl(auth_server, port, v4addrp, v6addrp);
}
IOService::~IOService() {
Modified: branches/trac221b/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac221b/src/bin/auth/asio_link.h (original)
+++ branches/trac221b/src/bin/auth/asio_link.h Sat Jul 10 06:37:23 2010
@@ -380,6 +380,9 @@
///
/// \name Constructors and Destructor
///
+ /// These are currently very specific to the authoritative server
+ /// implementation.
+ ///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non-copyable.
//@{
@@ -387,9 +390,15 @@
IOService(const IOService& source);
IOService& operator=(const IOService& source);
public:
- /// \brief The constructor. Currently very specific to the authoritative
- /// server implementation.
- IOService(AuthSrv* auth_server, const char& address, const char& port);
+ /// \brief The constructor with a specific IP address and port on which
+ /// the services listen on.
+ IOService(AuthSrv* auth_server, const char& port, const char& address);
+ /// \brief The constructor with a specific port on which the services
+ /// listen on.
+ ///
+ /// It effectively listens on "any" IPv4 and/or IPv6 addresses.
+ /// IPv4/IPv6 services will be available if and only if \c use_ipv4
+ /// or \c use_ipv6 is \c true, respectively.
IOService(AuthSrv* auth_server, const char& port,
const bool use_ipv4, const bool use_ipv6);
/// \brief The destructor.
Modified: branches/trac221b/src/bin/auth/tests/asio_link_unittest.cc
==============================================================================
--- branches/trac221b/src/bin/auth/tests/asio_link_unittest.cc (original)
+++ branches/trac221b/src/bin/auth/tests/asio_link_unittest.cc Sat Jul 10 06:37:23 2010
@@ -156,6 +156,18 @@
return (res);
}
+// This fixture is a framework for various types of network operations
+// using the ASIO interfaces. Each test case creates an IOService object,
+// opens a local "client" socket for testing, sends data via the local socket
+// to the service that would run in the IOService object.
+// A mock callback function (an ASIOCallBack object) is registered with the
+// IOService object, so the test code should be able to examine the data
+// receives on the server side. It then checks the received data matches
+// expected parameters.
+// If initialization parameters of the IOService should be modified, the test
+// case can do it using the setIOService() method.
+// Note: the set of tests in ASIOLinkTest use actual network services and may
+// involve undesirable side effect such as blocking.
class ASIOLinkTest : public ::testing::Test {
protected:
ASIOLinkTest();
@@ -166,6 +178,7 @@
if (sock_ != -1) {
close(sock_);
}
+ delete io_service_;
}
void sendUDP(const int family) {
res_ = resolveAddress(family, SOCK_DGRAM, IPPROTO_UDP);
@@ -179,7 +192,7 @@
if (cc != sizeof(test_data)) {
isc_throw(IOError, "unexpected sendto result: " << cc);
}
- io_service_.run();
+ io_service_->run();
}
void sendTCP(const int family) {
res_ = resolveAddress(family, SOCK_STREAM, IPPROTO_TCP);
@@ -195,9 +208,54 @@
if (cc != sizeof(test_data)) {
isc_throw(IOError, "unexpected sendto result: " << cc);
}
- io_service_.run();
- }
-public:
+ io_service_->run();
+ }
+ void setIOService(const char& address) {
+ delete io_service_;
+ io_service_ = NULL;
+ io_service_ = new IOService(NULL, *TEST_PORT, address);
+ io_service_->setCallBack(ASIOCallBack(this));
+ }
+ void setIOService(const bool use_ipv4, const bool use_ipv6) {
+ delete io_service_;
+ io_service_ = NULL;
+ io_service_ = new IOService(NULL, *TEST_PORT, use_ipv4, use_ipv6);
+ io_service_->setCallBack(ASIOCallBack(this));
+ }
+ void doTest(const int family, const int protocol) {
+ if (protocol == IPPROTO_UDP) {
+ sendUDP(family);
+ } else {
+ sendTCP(family);
+ }
+
+ // There doesn't seem to be an effective test for the validity of
+ // 'native'.
+ // One thing we are sure is it must be different from our local socket.
+ EXPECT_NE(sock_, callback_native_);
+ EXPECT_EQ(protocol, callback_protocol_);
+ EXPECT_EQ(family == AF_INET6 ? TEST_IPV6_ADDR : TEST_IPV4_ADDR,
+ callback_address_);
+
+ const uint8_t* expected_data =
+ protocol == IPPROTO_UDP ? test_data : test_data + 2;
+ const size_t expected_datasize =
+ protocol == IPPROTO_UDP ? sizeof(test_data) :
+ sizeof(test_data) - 2;
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
+ callback_data_.size(),
+ expected_data, expected_datasize);
+ }
+private:
+ class ASIOCallBack : public std::unary_function<IOMessage, void> {
+ public:
+ ASIOCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
+ void operator()(const IOMessage& io_message) const {
+ test_obj_->callBack(io_message);
+ }
+ private:
+ ASIOLinkTest* test_obj_;
+ };
void callBack(const IOMessage& io_message) {
callback_protocol_ = io_message.getSocket().getProtocol();
callback_native_ = io_message.getSocket().getNative();
@@ -207,10 +265,10 @@
static_cast<const uint8_t*>(io_message.getData()),
static_cast<const uint8_t*>(io_message.getData()) +
io_message.getDataSize());
- io_service_.stop();
+ io_service_->stop();
}
protected:
- IOService io_service_;
+ IOService* io_service_;
int callback_protocol_;
int callback_native_;
string callback_address_;
@@ -220,61 +278,74 @@
struct addrinfo* res_;
};
-class ASIOCallBack : public std::unary_function<IOMessage, void> {
-public:
- ASIOCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
- void operator()(const IOMessage& io_message) const {
- test_obj_->callBack(io_message);
- }
-private:
- ASIOLinkTest* test_obj_;
-};
-
ASIOLinkTest::ASIOLinkTest() :
- io_service_(NULL, *TEST_PORT, true, true),
- sock_(-1), res_(NULL)
+ io_service_(NULL), sock_(-1), res_(NULL)
{
- io_service_.setCallBack(ASIOCallBack(this));
+ setIOService(true, true);
}
TEST_F(ASIOLinkTest, v6UDPSend) {
- sendUDP(AF_INET6);
- // There doesn't seem to be an effective test for the validity of 'native'.
- // One thing we are sure is it must be different from our local socket.
- EXPECT_NE(callback_native_, sock_);
- EXPECT_EQ(IPPROTO_UDP, callback_protocol_);
- EXPECT_EQ(TEST_IPV6_ADDR, callback_address_);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
- callback_data_.size(), test_data, sizeof(test_data));
+ doTest(AF_INET6, IPPROTO_UDP);
}
TEST_F(ASIOLinkTest, v6TCPSend) {
- sendTCP(AF_INET6);
- EXPECT_NE(callback_native_, sock_);
- EXPECT_EQ(IPPROTO_TCP, callback_protocol_);
- EXPECT_EQ(TEST_IPV6_ADDR, callback_address_);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
- callback_data_.size(),
- test_data + 2, sizeof(test_data) - 2);
+ doTest(AF_INET6, IPPROTO_TCP);
}
TEST_F(ASIOLinkTest, v4UDPSend) {
- sendUDP(AF_INET);
- EXPECT_NE(callback_native_, sock_);
- EXPECT_EQ(IPPROTO_UDP, callback_protocol_);
- EXPECT_EQ(TEST_IPV4_ADDR, callback_address_);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
- callback_data_.size(), test_data, sizeof(test_data));
+ doTest(AF_INET, IPPROTO_UDP);
}
TEST_F(ASIOLinkTest, v4TCPSend) {
- sendTCP(AF_INET);
- EXPECT_NE(callback_native_, sock_);
- EXPECT_EQ(IPPROTO_TCP, callback_protocol_);
- EXPECT_EQ(TEST_IPV4_ADDR, callback_address_);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &callback_data_[0],
- callback_data_.size(),
- test_data + 2, sizeof(test_data) - 2);
-}
-
-}
+ doTest(AF_INET, IPPROTO_TCP);
+}
+
+TEST_F(ASIOLinkTest, v6UDPSendSpecific) {
+ // Explicitly set a specific address to be bound to the socket.
+ // The subsequent test does not directly ensures the underlying socket
+ // is bound to the expected address, but the success of the tests should
+ // reasonably suggest it works as intended.
+ // Specifying an address also implicitly means the service runs in a
+ // single address-family mode. In tests using TCP we can confirm that
+ // by trying to make a connection and seeing a failure. In UDP, it'd be
+ // more complicated because we need to use a connected socket and catch
+ // an error on a subsequent read operation. We could do it, but for
+ // simplicity we only tests the easier cases for now.
+
+ setIOService(*TEST_IPV6_ADDR);
+ doTest(AF_INET6, IPPROTO_UDP);
+}
+
+TEST_F(ASIOLinkTest, v6TCPSendSpecific) {
+ setIOService(*TEST_IPV6_ADDR);
+ doTest(AF_INET6, IPPROTO_TCP);
+
+ EXPECT_THROW(sendTCP(AF_INET), IOError);
+}
+
+TEST_F(ASIOLinkTest, v4UDPSendSpecific) {
+ setIOService(*TEST_IPV4_ADDR);
+ doTest(AF_INET, IPPROTO_UDP);
+}
+
+TEST_F(ASIOLinkTest, v4TCPSendSpecific) {
+ setIOService(*TEST_IPV4_ADDR);
+ doTest(AF_INET, IPPROTO_TCP);
+
+ EXPECT_THROW(sendTCP(AF_INET6), IOError);
+}
+
+TEST_F(ASIOLinkTest, v6TCPOnly) {
+ // Open only IPv6 TCP socket. A subsequent attempt of establishing an
+ // IPv4/TCP connection should fail. See above for why we only test this
+ // for TCP.
+ setIOService(false, true);
+ EXPECT_THROW(sendTCP(AF_INET), IOError);
+}
+
+TEST_F(ASIOLinkTest, v4TCPOnly) {
+ setIOService(true, false);
+ EXPECT_THROW(sendTCP(AF_INET6), IOError);
+}
+
+}
More information about the bind10-changes
mailing list