Browse Source

[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.
JINMEI Tatuya 13 years ago
parent
commit
5cda9e7282

+ 12 - 1
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<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);
 }
 

+ 2 - 2
src/bin/auth/benchmarks/query_bench.cc

@@ -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:

+ 43 - 1
src/bin/auth/tests/auth_srv_unittest.cc

@@ -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()));
     }
 }
 

+ 2 - 0
src/bin/auth/tests/command_unittest.cc

@@ -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;
 

+ 2 - 0
src/bin/auth/tests/config_unittest.cc

@@ -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 {

+ 0 - 53
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

+ 3 - 0
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)

+ 126 - 0
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 <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: