Commit 5cda9e72 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[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.
parent ccb3b1ad
......@@ -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<TSIGContext> /*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);
}
......
......@@ -33,7 +33,7 @@
#include <log/logger_support.h>
#include <xfr/xfrout_client.h>
#include <testutils/mockups.h>
#include <util/unittests/mock_socketsession.h>
#include <auth/auth_srv.h>
#include <auth/auth_config.h>
......@@ -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:
......
......@@ -34,6 +34,7 @@
#include <auth/common.h>
#include <auth/statistics.h>
#include <util/unittests/mock_socketsession.h>
#include <dns/tests/unittest_util.h>
#include <testutils/dnsmessage_test.h>
#include <testutils/srv_test.h>
......@@ -41,15 +42,21 @@
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <vector>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
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()));
}
}
......
......@@ -32,6 +32,7 @@
#include <asiolink/asiolink.h>
#include <util/unittests/mock_socketsession.h>
#include <testutils/mockups.h>
#include <cassert>
......@@ -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;
......
......@@ -32,6 +32,7 @@
#include "datasrc_util.h"
#include <util/unittests/mock_socketsession.h>
#include <testutils/mockups.h>
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
......@@ -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 {
......
......@@ -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
......
......@@ -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)
......
// 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 <exceptions/exceptions.h>
#include <util/io/socketsession.h>
#include <util/io/sockaddr_util.h>
#include <cassert>
#include <cstring>
#include <vector>
#include <sys/socket.h>
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<uint8_t> 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<uint8_t> pushed_data_;
};
} // end of unittests
} // end of util
} // end of isc
#endif // __UTIL_UNITTESTS_MOCKSOCKETSESSION_H
// Local Variables:
// mode: c++
// End:
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