From: JINMEI Tatuya Date: Fri, 18 May 2012 23:40:30 +0000 (-0700) Subject: [1539] push update request via the forwarder and extend the test for it. X-Git-Tag: trac2351_base~226^2~85^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5cda9e7282db2eca7c9bb7e2805bb03ef6ad616e;p=thirdparty%2Fkea.git [1539] push update request via the forwarder and extend the test for it. MockSocketSessionForwarder was now moved to lib/util/unittests for possible wider use. --- diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc index 609e572d68..dfb396de08 100644 --- a/src/bin/auth/auth_srv.cc +++ b/src/bin/auth/auth_srv.cc @@ -782,7 +782,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message, } bool -AuthSrvImpl::processUpdate(const IOMessage& /*io_message*/, +AuthSrvImpl::processUpdate(const IOMessage& io_message, Message& /*message*/, OutputBuffer& /*buffer*/, std::auto_ptr /*tsig_context*/) @@ -790,6 +790,17 @@ AuthSrvImpl::processUpdate(const IOMessage& /*io_message*/, // hardcode for initial test ddns_forwarder_.connect(); + const IOEndpoint& remote_ep = io_message.getRemoteEndpoint(); + const int protocol = remote_ep.getProtocol(); + const int sock_type = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; + ddns_forwarder_.forwarder_.push(io_message.getSocket().getNative(), + remote_ep.getFamily(), sock_type, protocol, + // XXX: no I/F to get local + remote_ep.getSockAddr(), + remote_ep.getSockAddr(), + io_message.getData(), + io_message.getDataSize()); + return (false); } diff --git a/src/bin/auth/benchmarks/query_bench.cc b/src/bin/auth/benchmarks/query_bench.cc index 17a7490bca..2e705e4f2b 100644 --- a/src/bin/auth/benchmarks/query_bench.cc +++ b/src/bin/auth/benchmarks/query_bench.cc @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include @@ -49,11 +49,11 @@ using namespace isc::auth; using namespace isc::dns; using namespace isc::log; using namespace isc::util; +using namespace isc::util::unittests; using namespace isc::xfr; using namespace isc::bench; using namespace isc::asiodns; using namespace isc::asiolink; -using namespace isc::testutils; namespace { // Commonly used constant: diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc index 412db99693..2c87c9bafb 100644 --- a/src/bin/auth/tests/auth_srv_unittest.cc +++ b/src/bin/auth/tests/auth_srv_unittest.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -41,15 +42,21 @@ #include #include +#include #include #include #include +#include +#include +#include + using namespace std; using namespace isc::cc; using namespace isc::dns; using namespace isc::util; +using namespace isc::util::unittests; using namespace isc::dns::rdata; using namespace isc::data; using namespace isc::xfr; @@ -1407,6 +1414,27 @@ TEST_F(AuthSrvTest, queryWithThrowingInToWire) { // // DDNS related tests // + +// Helper subroutine to check if the given socket address has the expected +// address and port. It depends on specific output of getnameinfo() (while +// there can be multiple textual representation of the same address) but +// in practice it should be reliable. +void +checkAddrPort(const struct sockaddr& actual_sa, + const string& expected_addr, const string& expected_port) +{ + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + const int error = getnameinfo(&actual_sa, actual_sa.sa_len, hbuf, + sizeof(hbuf), sbuf, sizeof(sbuf), + NI_NUMERICHOST | NI_NUMERICSERV); + if (error != 0) { + isc_throw(isc::Unexpected, "getnameinfo failed: " << + gai_strerror(error)); + } + EXPECT_EQ(expected_addr, hbuf); + EXPECT_EQ(expected_port, sbuf); +} + TEST_F(AuthSrvTest, DDNSForward) { EXPECT_FALSE(ddns_forwarder.isConnected()); @@ -1414,9 +1442,23 @@ TEST_F(AuthSrvTest, DDNSForward) { // confirm the forwarder connection will be established exactly once, // and kept established. for (size_t i = 0; i < 2; ++i) { - createAndSendRequest(RRType::SOA(), Opcode::UPDATE()); + // Use different names for each iteration + const Name zone_name = Name(i == 0 ? "example.com" : "example.org"); + createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), zone_name); 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()); + checkAddrPort(ddns_forwarder.getPushedRemoteend(), + DEFAULT_REMOTE_ADDRESS, "53210"); + EXPECT_EQ(io_message->getDataSize(), + ddns_forwarder.getPushedData().size()); + EXPECT_EQ(0, memcmp(io_message->getData(), + &ddns_forwarder.getPushedData()[0], + ddns_forwarder.getPushedData().size())); } } diff --git a/src/bin/auth/tests/command_unittest.cc b/src/bin/auth/tests/command_unittest.cc index e9e3090d98..0909e0d245 100644 --- a/src/bin/auth/tests/command_unittest.cc +++ b/src/bin/auth/tests/command_unittest.cc @@ -32,6 +32,7 @@ #include +#include #include #include @@ -51,6 +52,7 @@ using namespace isc::dns; using namespace isc::data; using namespace isc::datasrc; using namespace isc::config; +using namespace isc::util::unittests; using namespace isc::testutils; using namespace isc::auth::unittest; diff --git a/src/bin/auth/tests/config_unittest.cc b/src/bin/auth/tests/config_unittest.cc index 3c87c3bdee..50d8fa1393 100644 --- a/src/bin/auth/tests/config_unittest.cc +++ b/src/bin/auth/tests/config_unittest.cc @@ -32,6 +32,7 @@ #include "datasrc_util.h" +#include #include #include #include @@ -44,6 +45,7 @@ using namespace isc::data; using namespace isc::datasrc; using namespace isc::asiodns; using namespace isc::auth::unittest; +using namespace isc::util::unittests; using namespace isc::testutils; namespace { diff --git a/src/lib/testutils/mockups.h b/src/lib/testutils/mockups.h index e82cb1b03d..ed7fbd350e 100644 --- a/src/lib/testutils/mockups.h +++ b/src/lib/testutils/mockups.h @@ -203,59 +203,6 @@ private: bool disconnect_ok_; }; -// Mock socket session forwarder -class MockSocketSessionForwarder : - public isc::util::io::BaseSocketSessionForwarder -{ -public: - MockSocketSessionForwarder() : - is_connected_(false), connect_ok_(true), push_ok_(true), - close_ok_(true) - {} - - virtual void connectToReceiver() { - if (!connect_ok_) { - isc_throw(isc::util::io::SocketSessionError, "socket session " - "forwarding connection disabled for test"); - } - if (is_connected_) { - isc_throw(isc::util::io::SocketSessionError, "duplicate connect"); - } - is_connected_ = true; - } - virtual void close() { - is_connected_ = false; - } -#if 0 - virtual void push(int sock, int family, int type, int protocol, - const struct sockaddr& local_end, - const struct sockaddr& remote_end, - const void* data, size_t data_len) -#endif - virtual void push(int, int, int, int, - const struct sockaddr&, - const struct sockaddr&, - const void*, size_t) - { - if (!push_ok_) { - isc_throw(isc::util::io::SocketSessionError, - "socket session forwarding is disabled for test"); - } - } - bool isConnected() const { return (is_connected_); } - void disableConnect() { connect_ok_ = false; } - void enableConnect() { connect_ok_ = true; } - void disableClose() { close_ok_ = false; } - void enableClose() { close_ok_ = true; } - void disablePush() { push_ok_ = false; } - -private: - bool is_connected_; - bool connect_ok_; - bool push_ok_; - bool close_ok_; -}; - } // end of testutils } // end of isc #endif // __ISC_TESTUTILS_MOCKUPS_H diff --git a/src/lib/util/unittests/Makefile.am b/src/lib/util/unittests/Makefile.am index 28274712a6..3007a839d8 100644 --- a/src/lib/util/unittests/Makefile.am +++ b/src/lib/util/unittests/Makefile.am @@ -11,6 +11,9 @@ libutil_unittests_la_SOURCES += run_all.h run_all.cc libutil_unittests_la_SOURCES += textdata.h endif +# For now, this isn't needed for libutil_unittests +EXTRA_DIST = mock_socketsession.h + libutil_unittests_la_CPPFLAGS = $(AM_CPPFLAGS) if HAVE_GTEST libutil_unittests_la_CPPFLAGS += $(GTEST_INCLUDES) diff --git a/src/lib/util/unittests/mock_socketsession.h b/src/lib/util/unittests/mock_socketsession.h new file mode 100644 index 0000000000..47915f511a --- /dev/null +++ b/src/lib/util/unittests/mock_socketsession.h @@ -0,0 +1,126 @@ +// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#ifndef __UTIL_UNITTESTS_MOCKSOCKETSESSION_H +#define __UTIL_UNITTESTS_MOCKSOCKETSESSION_H 1 + +#include + +#include +#include + +#include +#include +#include + +#include + +namespace isc { +namespace util { +namespace unittests { + +// Mock socket session forwarder +class MockSocketSessionForwarder : + public isc::util::io::BaseSocketSessionForwarder +{ +public: + MockSocketSessionForwarder() : + is_connected_(false), connect_ok_(true), push_ok_(true), + close_ok_(true) + {} + + virtual void connectToReceiver() { + if (!connect_ok_) { + isc_throw(isc::util::io::SocketSessionError, "socket session " + "forwarding connection disabled for test"); + } + if (is_connected_) { + isc_throw(isc::util::io::SocketSessionError, "duplicate connect"); + } + is_connected_ = true; + } + virtual void close() { + is_connected_ = false; + } + virtual void push(int sock, int family, int type, int protocol, + const struct sockaddr& local_end, + const struct sockaddr& remote_end, + const void* data, size_t data_len) + { + if (!push_ok_) { + isc_throw(isc::util::io::SocketSessionError, + "socket session forwarding is disabled for test"); + } + + // Copy parameters for later checks + pushed_sock_ = sock; + 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, + io::internal::getSALength(local_end)); + assert(io::internal::getSALength(remote_end) <= + sizeof(pushed_remote_end_ss_)); + std::memcpy(&pushed_remote_end_ss_, &remote_end, + io::internal::getSALength(remote_end)); + pushed_data_.resize(data_len); + std::memcpy(&pushed_data_[0], data, data_len); + } + bool isConnected() const { return (is_connected_); } + void disableConnect() { connect_ok_ = false; } + void enableConnect() { connect_ok_ = true; } + void disableClose() { close_ok_ = false; } + void enableClose() { close_ok_ = true; } + void disablePush() { push_ok_ = false; } + + // Read-only accessors to recorded parameters to the previous successful + // call to push(). Return values are undefined if there has been no + // successful call to push(). + int getPushedSock() const { return (pushed_sock_); } + int getPushedFamily() const { return (pushed_family_); } + int getPushedType() const { return (pushed_type_); } + int getPushedProtocol() const { return (pushed_protocol_); } + const struct sockaddr& getPushedLocalend() const { + return (*io::internal::convertSockAddr(&pushed_local_end_ss_)); + } + const struct sockaddr& getPushedRemoteend() const { + return (*io::internal::convertSockAddr(&pushed_remote_end_ss_)); + } + const std::vector getPushedData() const { return (pushed_data_); } + +private: + bool is_connected_; + bool connect_ok_; + bool push_ok_; + bool close_ok_; + int pushed_sock_; + int pushed_family_; + int pushed_type_; + int pushed_protocol_; + struct sockaddr_storage pushed_local_end_ss_; + struct sockaddr_storage pushed_remote_end_ss_; + std::vector pushed_data_; +}; + +} // end of unittests +} // end of util +} // end of isc +#endif // __UTIL_UNITTESTS_MOCKSOCKETSESSION_H + +// Local Variables: +// mode: c++ +// End: