[svn] commit: r3954 - in /branches/trac347: ./ src/bin/auth/ src/bin/auth/tests/

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Dec 22 13:05:42 UTC 2010


Author: y-aharen
Date: Wed Dec 22 13:05:42 2010
New Revision: 3954

Log:
Address review comments on ticket:347:12

- Documentation and comments were appended.
- Some classes and functions were renamed.
- Some test cases were appended.
- Removed unnecessary includes.
- Thrown exceptions were changed not to hide asio specific definitions.
- Query counter increment is moved from AuthSrv::processMessage() to
  AuthSrvImpl::processNormalQuery() and AuthSrvImpl::processAxfrQuery().


Added:
    branches/trac347/src/bin/auth/statistics.cc
    branches/trac347/src/bin/auth/statistics.h
Modified:
    branches/trac347/ChangeLog
    branches/trac347/src/bin/auth/asio_link.cc
    branches/trac347/src/bin/auth/asio_link.h
    branches/trac347/src/bin/auth/auth_srv.cc
    branches/trac347/src/bin/auth/auth_srv.h
    branches/trac347/src/bin/auth/main.cc
    branches/trac347/src/bin/auth/tests/asio_link_unittest.cc
    branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc
    branches/trac347/src/bin/auth/tests/statistics_unittest.cc

Modified: branches/trac347/ChangeLog
==============================================================================
--- branches/trac347/ChangeLog (original)
+++ branches/trac347/ChangeLog Wed Dec 22 13:05:42 2010
@@ -1,11 +1,13 @@
   TBD.  [func]		y-aharen
-	src/bin/auth: Added a feature to count query and send counter
+	src/bin/auth: Added a feature to count queries and send counter
 	values to statistics periodically. To support it, added wrapping
 	class of asio::deadline_timer to use as interval timer.
 	Added a command 'sendstats' to send counter values at once.
-	The counter value can be seen with sending 'sendstats' command to
-	statistics module via bindctl like:
+	The counters can be seen using the "Stats show" command from
+	bindctl.  The result would look like:
 	  ... "auth.queries.tcp": 1, "auth.queries.udp": 1 ...
+	Using the "Auth sendstats" command you can make b10-auth send the
+	counters to b10-stats immediately.
 	(Trac #347, svn rxxxx)
 
   122.  [func]		stephen

Modified: branches/trac347/src/bin/auth/asio_link.cc
==============================================================================
--- branches/trac347/src/bin/auth/asio_link.cc (original)
+++ branches/trac347/src/bin/auth/asio_link.cc Wed Dec 22 13:05:42 2010
@@ -719,8 +719,12 @@
 
 void
 IntervalTimerImpl::updateTimer() {
-    // Update expire time to (current time + interval_).
-    timer_.expires_from_now(boost::posix_time::seconds(interval_));
+    try {
+        // Update expire time to (current time + interval_).
+        timer_.expires_from_now(boost::posix_time::seconds(interval_));
+    } catch (asio::system_error& e) {
+        isc_throw(isc::Unexpected, "Failed to update timer");
+    }
     // Reset timer.
     timer_.async_wait(boost::bind(&IntervalTimerImpl::callback, this, _1));
 }

Modified: branches/trac347/src/bin/auth/asio_link.h
==============================================================================
--- branches/trac347/src/bin/auth/asio_link.h (original)
+++ branches/trac347/src/bin/auth/asio_link.h Wed Dec 22 13:05:42 2010
@@ -462,9 +462,6 @@
 /// and updates the timer to expire in (now + interval) seconds.
 /// The type of call back function is \c void(void).
 ///
-/// This class is mainly designed to use for calling
-/// \c QueryCounters::submitStatistics() periodically.
-///
 /// Note: Destruction of an instance of this class while call back
 /// is pending causes throwing an exception from \c IOService.
 ///
@@ -516,22 +513,22 @@
     ~IntervalTimer();
     //@}
 
-    /// \brief Register timer callback function and interval
+    /// \brief Register timer callback function and interval.
     ///
     /// This function sets call back function and interval in seconds.
     /// Timer will actually start after calling \c IOService::run().
     ///
     /// \param cbfunc A reference to a function \c void(void) to call back
-    /// when the timer is expired
+    /// when the timer is expired (should not be an empty functor)
     /// \param interval Interval in seconds (greater than 0)
     ///
-    /// Note: IntervalTimer will not pass asio::error_code to
+    /// Note: IntervalTimer will not pass \c asio::error_code to
     /// call back function. In case the timer is cancelled, the function
     /// will not be called.
     ///
     /// \throw isc::InvalidParameter cbfunc is empty
     /// \throw isc::BadValue interval is 0
-    /// \throw asio::system_error ASIO library error
+    /// \throw isc::Unexpected ASIO library error
     ///
     void setupTimer(const Callback& cbfunc, const uint32_t interval);
 private:

Modified: branches/trac347/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac347/src/bin/auth/auth_srv.cc (original)
+++ branches/trac347/src/bin/auth/auth_srv.cc Wed Dec 22 13:05:42 2010
@@ -102,7 +102,10 @@
     isc::datasrc::HotCache cache_;
 
     /// Query counters for statistics
-    QueryCounters counters_;
+    AuthCounters counters_;
+private:
+    /// Increment query counter
+    void incCounter(int protocol);
 };
 
 AuthSrvImpl::AuthSrvImpl(const bool use_cache,
@@ -220,8 +223,8 @@
 }
 
 void
-AuthSrv::setStatsSession(AbstractSession* stats_session) {
-    impl_->counters_.setStatsSession(stats_session);
+AuthSrv::setStatisticsSession(AbstractSession* statistics_session) {
+    impl_->counters_.setStatisticsSession(statistics_session);
 }
 
 ModuleCCSession*
@@ -274,17 +277,6 @@
 
     if (impl_->verbose_mode_) {
         cerr << "[b10-auth] received a message:\n" << message.toText() << endl;
-    }
-
-    // increment Query Counter
-    if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
-        impl_->counters_.inc(QueryCounters::COUNTER_UDP);
-    } else if (io_message.getSocket().getProtocol() == IPPROTO_TCP) {
-        impl_->counters_.inc(QueryCounters::COUNTER_TCP);
-    } else {
-        // unknown protocol
-        isc_throw(Unexpected, "Unknown protocol: " <<
-                  io_message.getSocket().getProtocol());
     }
 
     // Perform further protocol-level validation.
@@ -334,6 +326,9 @@
     message.setHeaderFlag(Message::HEADERFLAG_AA);
     message.setRcode(Rcode::NOERROR());
 
+    // Increment query counter.
+    incCounter(io_message.getSocket().getProtocol());
+
     if (remote_edns) {
         EDNSPtr local_edns = EDNSPtr(new EDNS());
         local_edns->setDNSSECAwareness(dnssec_ok);
@@ -371,6 +366,9 @@
 AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
                             MessageRenderer& response_renderer)
 {
+    // Increment query counter.
+    incCounter(io_message.getSocket().getProtocol());
+
     if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
         if (verbose_mode_) {
             cerr << "[b10-auth] AXFR query over UDP isn't allowed" << endl;
@@ -498,6 +496,19 @@
     return (true);
 }
 
+void
+AuthSrvImpl::incCounter(int protocol) {
+    // Increment query counter.
+    if (protocol == IPPROTO_UDP) {
+        counters_.inc(AuthCounters::COUNTER_UDP);
+    } else if (protocol == IPPROTO_TCP) {
+        counters_.inc(AuthCounters::COUNTER_TCP);
+    } else {
+        // unknown protocol
+        isc_throw(Unexpected, "Unknown protocol: " << protocol);
+    }
+}
+
 ConstElementPtr
 AuthSrvImpl::setDbFile(ConstElementPtr config) {
     ConstElementPtr answer = isc::config::createAnswer();
@@ -565,11 +576,11 @@
     }
 }
 
-bool AuthSrv::submitStatistics() {
+bool AuthSrv::submitStatistics() const {
     return (impl_->counters_.submitStatistics());
 }
 
-const std::vector<uint64_t>&
-AuthSrv::getCounters() const {
-    return (impl_->counters_.getCounters());
-}
+uint64_t
+AuthSrv::getCounter(const AuthCounters::QueryType type) const {
+    return (impl_->counters_.getCounter(type));
+}

Modified: branches/trac347/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac347/src/bin/auth/auth_srv.h (original)
+++ branches/trac347/src/bin/auth/auth_srv.h Wed Dec 22 13:05:42 2010
@@ -22,6 +22,8 @@
 #include <cc/data.h>
 #include <config/ccsession.h>
 
+#include <auth/statistics.h>
+
 namespace isc {
 namespace dns {
 class InputBuffer;
@@ -62,6 +64,7 @@
 ///
 /// The design of this class is still in flux.  It's quite likely to change
 /// in future versions.
+///
 class AuthSrv {
     ///
     /// \name Constructors, Assignment Operator and Destructor.
@@ -86,6 +89,8 @@
     //@}
     /// \return \c true if the \a message contains a response to be returned;
     /// otherwise \c false.
+    ///
+    /// \throw isc::Unexpected Protocol type of \a message is unexpected
     bool processMessage(const asio_link::IOMessage& io_message,
                         isc::dns::Message& message,
                         isc::dns::MessageRenderer& response_renderer);
@@ -203,13 +208,13 @@
     /// \brief Set the communication session with Statistics.
     ///
     /// This function never throws an exception as far as
-    /// QueryCounters::setStatsSession() doesn't throw.
+    /// AuthCounters::setStatisticsSession() doesn't throw.
     ///
     /// Note: this interface is tentative.  We'll revisit the ASIO and
     /// session frameworks, at which point the session will probably
     /// be passed on construction of the server.
     ///
-    /// \param stats_session A Session object over which statistics
+    /// \param statistics_session A Session object over which statistics
     /// information is exchanged with statistics module.
     /// The session must be established before setting in the server
     /// object.
@@ -218,32 +223,33 @@
     /// disconnecting the session and destroying the object when the server
     /// is shutdown.
     ///
-    void setStatsSession(isc::cc::AbstractSession* stats_session);
+    void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
 
     /// \brief Submit statistics counters to statistics module.
     ///
     /// This function can throw an exception from
-    /// QueryCounters::submitStatistics().
+    /// AuthCounters::submitStatistics().
     ///
     /// \return true on success, false on failure (e.g. session timeout,
     /// session error).
     ///
-    bool submitStatistics();
-
-    /// \brief Get counters in the QueryCounters.
+    bool submitStatistics() const;
+
+    /// \brief Get the value of counter in the AuthCounters.
     /// 
-    /// This function calls QueryCounters::getCounters() and
-    /// returns its return velue, a reference to the counters.
+    /// This function calls AuthCounters::getCounter() and
+    /// returns its return value.
     ///
     /// This function never throws an exception as far as
-    /// QueryCounters::getCounters() doesn't throw.
+    /// AuthCounters::getCounter() doesn't throw.
     /// 
     /// Note: Currently this function is for testing purpose only.
-    /// This function should not be called except from tests.
-    ///
-    /// \return a reference to the counters.
-    ///
-    const std::vector<uint64_t>& getCounters() const;
+    ///
+    /// \param type Type of a counter to get the value of
+    ///
+    /// \return the value of the counter.
+    ///
+    uint64_t getCounter(const AuthCounters::QueryType type) const;
 private:
     AuthSrvImpl* impl_;
 };

Modified: branches/trac347/src/bin/auth/main.cc
==============================================================================
--- branches/trac347/src/bin/auth/main.cc (original)
+++ branches/trac347/src/bin/auth/main.cc Wed Dec 22 13:05:42 2010
@@ -61,7 +61,7 @@
 
 // Note: this value must be greater than 0.
 // TODO: make it configurable via command channel.
-const uint32_t STATS_SEND_INTERVAL_SEC = 60;
+const uint32_t STATISTICS_SEND_INTERVAL_SEC = 60;
 
 /* need global var for config/command handlers.
  * todo: turn this around, and put handlers in the authserver
@@ -170,10 +170,10 @@
     // XXX: we should eventually pass io_service here.
     Session* cc_session = NULL;
     Session* xfrin_session = NULL;
-    Session* stats_session = NULL;
+    Session* statistics_session = NULL;
     asio_link::IntervalTimer* itimer = NULL;
     bool xfrin_session_established = false; // XXX (see Trac #287)
-    bool stats_session_established = false; // XXX (see Trac #287)
+    bool statistics_session_established = false; // XXX (see Trac #287)
     ModuleCCSession* config_session = NULL;
     string xfrout_socket_path;
     if (getenv("B10_FROM_BUILD") != NULL) {
@@ -228,11 +228,11 @@
         xfrin_session_established = true;
         cout << "[b10-auth] Xfrin session channel established." << endl;
 
-        stats_session = new Session(io_service->get_io_service());
-        cout << "[b10-auth] Stats session channel created." << endl;
-        stats_session->establish(NULL);
-        stats_session_established = true;
-        cout << "[b10-auth] Stats session channel established." << endl;
+        statistics_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Statistics session channel created." << endl;
+        statistics_session->establish(NULL);
+        statistics_session_established = true;
+        cout << "[b10-auth] Statistics session channel established." << endl;
 
         // XXX: with the current interface to asio_link we have to create
         // auth_server before io_service while Session needs io_service.
@@ -240,7 +240,7 @@
         // from auth_server, and create io_service, auth_server, and
         // sessions in that order.
         auth_server->setXfrinSession(xfrin_session);
-        auth_server->setStatsSession(stats_session);
+        auth_server->setStatisticsSession(statistics_session);
         auth_server->setConfigSession(config_session);
         auth_server->updateConfig(ElementPtr());
 
@@ -249,8 +249,8 @@
         // set up interval timer
         // register function to send statistics with interval
         itimer->setupTimer(boost::bind(statisticsTimerCallback, auth_server),
-                           STATS_SEND_INTERVAL_SEC);
-        cout << "[b10-auth] Interval timer set to send stats." << endl;
+                           STATISTICS_SEND_INTERVAL_SEC);
+        cout << "[b10-auth] Interval timer to send statistics set." << endl;
 
         cout << "[b10-auth] Server started." << endl;
         io_service->run();
@@ -259,8 +259,8 @@
         ret = 1;
     }
 
-    if (stats_session_established) {
-        stats_session->disconnect();
+    if (statistics_session_established) {
+        statistics_session->disconnect();
     }
 
     if (xfrin_session_established) {
@@ -268,7 +268,7 @@
     }
 
     delete itimer;
-    delete stats_session;
+    delete statistics_session;
     delete xfrin_session;
     delete config_session;
     delete cc_session;

Modified: branches/trac347/src/bin/auth/tests/asio_link_unittest.cc
==============================================================================
--- branches/trac347/src/bin/auth/tests/asio_link_unittest.cc (original)
+++ branches/trac347/src/bin/auth/tests/asio_link_unittest.cc Wed Dec 22 13:05:42 2010
@@ -257,20 +257,129 @@
                             callback_data_.size(),
                             expected_data, expected_datasize);
     }
-    class TimerCallBack : public std::unary_function<void, void> {
+private:
+    class ASIOCallBack : public std::unary_function<IOMessage, void> {
     public:
-        TimerCallBack(ASIOLinkTest* test_obj) : test_obj_(test_obj) {}
-        void operator()() const {
-            test_obj_->timer_called_ = true;
-            test_obj_->io_service_->stop();
-            return;
+        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();
+        callback_address_ =
+            io_message.getRemoteEndpoint().getAddress().toText();
+        callback_data_.assign(
+            static_cast<const uint8_t*>(io_message.getData()),
+            static_cast<const uint8_t*>(io_message.getData()) +
+            io_message.getDataSize());
+        io_service_->stop();
+    }
+protected:
+    IOService* io_service_;
+    int callback_protocol_;
+    int callback_native_;
+    string callback_address_;
+    vector<uint8_t> callback_data_;
+    int sock_;
+private:
+    struct addrinfo* res_;
+};
+
+ASIOLinkTest::ASIOLinkTest() :
+    io_service_(NULL), sock_(-1), res_(NULL)
+{
+    setIOService(true, true);
+}
+
+TEST_F(ASIOLinkTest, v6UDPSend) {
+    doTest(AF_INET6, IPPROTO_UDP);
+}
+
+TEST_F(ASIOLinkTest, v6TCPSend) {
+    doTest(AF_INET6, IPPROTO_TCP);
+}
+
+TEST_F(ASIOLinkTest, v4UDPSend) {
+    doTest(AF_INET, IPPROTO_UDP);
+}
+
+TEST_F(ASIOLinkTest, v4TCPSend) {
+    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);
+}
+
+// This fixture is for testing IntervalTimer. Some callback functors are 
+// registered as callback function of the timer to test if they are called
+// or not.
+class IntervalTimerTest : public ::testing::Test {
+protected:
+    IntervalTimerTest() : io_service_(NULL, *TEST_PORT, false, false) {};
+    ~IntervalTimerTest() {}
+    class TimerCallBack : public std::unary_function<void, void> {
+    public:
+        TimerCallBack(IntervalTimerTest* test_obj) : test_obj_(test_obj) {}
+        void operator()() const {
+            test_obj_->timer_called_ = true;
+            test_obj_->io_service_.stop();
+            return;
+        }
+    private:
+        IntervalTimerTest* test_obj_;
+    };
     class TimerCallBackCounter : public std::unary_function<void, void> {
     public:
-        TimerCallBackCounter(ASIOLinkTest* test_obj) : test_obj_(test_obj) {
+        TimerCallBackCounter(IntervalTimerTest* test_obj) : test_obj_(test_obj) {
             counter_ = 0;
         }
         void operator()() {
@@ -279,11 +388,11 @@
         }
         int counter_;
     private:
-        ASIOLinkTest* test_obj_;
+        IntervalTimerTest* test_obj_;
     };
     class TimerCallBackCancelDeleter : public std::unary_function<void, void> {
     public:
-        TimerCallBackCancelDeleter(ASIOLinkTest* test_obj,
+        TimerCallBackCancelDeleter(IntervalTimerTest* test_obj,
                                    IntervalTimer* timer,
                                    TimerCallBackCounter& counter)
             : test_obj_(test_obj), timer_(timer), counter_(counter), count_(0)
@@ -298,7 +407,7 @@
             } else if (count_ == 2) {
                 // Second time of call back.
                 // Stop io_service to stop all timers.
-                test_obj_->io_service_->stop();
+                test_obj_->io_service_.stop();
                 // Compare the value of counter_.counter_ with stored one.
                 // If TimerCallBackCounter was not called (expected behavior),
                 // they are same.
@@ -309,7 +418,7 @@
             return;
         }
     private:
-        ASIOLinkTest* test_obj_;
+        IntervalTimerTest* test_obj_;
         IntervalTimer* timer_;
         TimerCallBackCounter& counter_;
         int count_;
@@ -317,7 +426,7 @@
     };
     class TimerCallBackOverwriter : public std::unary_function<void, void> {
     public:
-        TimerCallBackOverwriter(ASIOLinkTest* test_obj,
+        TimerCallBackOverwriter(IntervalTimerTest* test_obj,
                                 IntervalTimer& timer)
             : test_obj_(test_obj), timer_(timer), count_(0)
         {}
@@ -328,153 +437,47 @@
                 // Call setupTimer() to update callback function
                 // to TimerCallBack.
                 test_obj_->timer_called_ = false;
-                timer_.setupTimer(IntervalTimer::Callback(
-                                      TimerCallBack(test_obj_)), 1);
+                timer_.setupTimer(TimerCallBack(test_obj_), 1);
             } else if (count_ == 2) {
                 // Second time of call back.
                 // If it reaches here, re-setupTimer() is failed (unexpected).
                 // We should stop here.
-                test_obj_->io_service_->stop();
+                test_obj_->io_service_.stop();
             }
             return;
         }
     private:
-        ASIOLinkTest* test_obj_;
+        IntervalTimerTest* test_obj_;
         IntervalTimer& timer_;
         int count_;
     };
-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();
-        callback_address_ =
-            io_message.getRemoteEndpoint().getAddress().toText();
-        callback_data_.assign(
-            static_cast<const uint8_t*>(io_message.getData()),
-            static_cast<const uint8_t*>(io_message.getData()) +
-            io_message.getDataSize());
-        io_service_->stop();
-    }
 protected:
-    IOService* io_service_;
-    int callback_protocol_;
-    int callback_native_;
-    string callback_address_;
-    vector<uint8_t> callback_data_;
+    IOService io_service_;
     bool timer_called_;
     bool timer_cancel_success_;
-    int sock_;
-private:
-    struct addrinfo* res_;
 };
 
-ASIOLinkTest::ASIOLinkTest() :
-    io_service_(NULL), sock_(-1), res_(NULL)
-{
-    setIOService(true, true);
-}
-
-TEST_F(ASIOLinkTest, v6UDPSend) {
-    doTest(AF_INET6, IPPROTO_UDP);
-}
-
-TEST_F(ASIOLinkTest, v6TCPSend) {
-    doTest(AF_INET6, IPPROTO_TCP);
-}
-
-TEST_F(ASIOLinkTest, v4UDPSend) {
-    doTest(AF_INET, IPPROTO_UDP);
-}
-
-TEST_F(ASIOLinkTest, v4TCPSend) {
-    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);
-}
-
-TEST_F(ASIOLinkTest, invalidArgumentToIntervalTimer) {
+TEST_F(IntervalTimerTest, invalidArgumentToIntervalTimer) {
     // Create asio_link::IntervalTimer and setup.
-    setIOService(false, false);
-    IntervalTimer itimer(*io_service_);
+    IntervalTimer itimer(io_service_);
     // expect throw if call back function is empty
-    EXPECT_THROW(itimer.setupTimer(
-                     IntervalTimer::Callback(), 1),
+    EXPECT_THROW(itimer.setupTimer(IntervalTimer::Callback(), 1),
                      isc::InvalidParameter);
     // expect throw if interval is 0
-    EXPECT_THROW(itimer.setupTimer(
-                     IntervalTimer::Callback(TimerCallBack(this)), 0),
-                     isc::BadValue);
-}
-
-TEST_F(ASIOLinkTest, startIntervalTimer) {
+    EXPECT_THROW(itimer.setupTimer(TimerCallBack(this), 0), isc::BadValue);
+}
+
+TEST_F(IntervalTimerTest, startIntervalTimer) {
     // Create asio_link::IntervalTimer and setup.
     // Then run IOService and test if the callback function is called.
-    setIOService(false, false);
-    IntervalTimer itimer(*io_service_);
+    IntervalTimer itimer(io_service_);
     timer_called_ = false;
     // store start time
     boost::posix_time::ptime start;
     start = boost::posix_time::microsec_clock::universal_time();
     // setup timer
-    EXPECT_NO_THROW(itimer.setupTimer(
-                        IntervalTimer::Callback(TimerCallBack(this)),
-                        1));
-    io_service_->run();
+    itimer.setupTimer(TimerCallBack(this), 1);
+    io_service_.run();
     // reaches here after timer expired
     // delta: difference between elapsed time and 1 second
     boost::posix_time::time_duration delta =
@@ -483,16 +486,40 @@
     if (delta.is_negative()) {
         delta.invert_sign();
     }
-    // expect call back is updated: TimerCallBack is called
+    // expect TimerCallBack is called; timer_called_ is true
     EXPECT_TRUE(timer_called_);
     // expect interval is 1 second +/- TIMER_MERGIN_MSEC.
     EXPECT_TRUE(delta < TIMER_MERGIN_MSEC);
 }
 
-TEST_F(ASIOLinkTest, destructIntervalTimer) {
-    // The call back function will not be called
-    // after the timer is destructed.
-    setIOService(false, false);
+TEST_F(IntervalTimerTest, deleteIntervalTimerBeforeStart) {
+    // Note: This code isn't exception safe, but we'd rather keep the code
+    // simpler and more readable as this is only for tests and if it throws
+    // the program would immediately terminate anyway.
+
+    // Create asio_link::IntervalTimer and delete before starting timer.
+    // Test if the callback function is not called.
+    IntervalTimer* itimer = new IntervalTimer(io_service_);
+    timer_called_ = false;
+    // setup timer...
+    itimer->setupTimer(TimerCallBack(this), 1);
+    // and delete
+    delete itimer;
+    // expect the callback function is not called
+    EXPECT_FALSE(timer_called_);
+}
+
+TEST_F(IntervalTimerTest, destructIntervalTimer) {
+    // Note: This test currently takes 6 seconds. The timer should have
+    // finer granularity and timer periods in this test should be shorter
+    // in the future.
+    // This code isn't exception safe, but we'd rather keep the code
+    // simpler and more readable as this is only for tests and if it throws
+    // the program would immediately terminate anyway.
+
+    // The call back function will not be called after the timer is
+    // destructed.
+    //
     // There are two timers:
     //  itimer_counter (A)
     //   (Calls TimerCallBackCounter)
@@ -513,35 +540,37 @@
     // (B) i--------+--------s
     //                       ^stop io_service
     //                        and test itimer_counter have been stopped
-
-    // itimer_counter will be deleted in
-    // TimerCallBackCancelDeleter
-    IntervalTimer* itimer_counter = NULL;
-    ASSERT_NO_THROW(itimer_counter = new IntervalTimer(*io_service_));
-    IntervalTimer itimer_canceller(*io_service_);
+    //
+
+    // itimer_counter will be deleted in TimerCallBackCancelDeleter
+    IntervalTimer* itimer_counter = new IntervalTimer(io_service_);
+    IntervalTimer itimer_canceller(io_service_);
     timer_cancel_success_ = false;
     TimerCallBackCounter callback_canceller(this);
-    itimer_counter->setupTimer(IntervalTimer::Callback(callback_canceller), 2);
+    itimer_counter->setupTimer(callback_canceller, 2);
     itimer_canceller.setupTimer(
-        IntervalTimer::Callback(
-            TimerCallBackCancelDeleter(this, itimer_counter,
-                                       callback_canceller)),
+        TimerCallBackCancelDeleter(this, itimer_counter,
+                                   callback_canceller),
         3);
-    io_service_->run();
+    io_service_.run();
     EXPECT_TRUE(timer_cancel_success_);
 }
 
-TEST_F(ASIOLinkTest, overwriteIntervalTimer) {
-    // Calling setupTimer() multiple times updates call back
-    // function and interval.
-    setIOService(false, false);
+TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
+    // Note: This test currently takes 4 seconds. The timer should have
+    // finer granularity and timer periods in this test should be shorter
+    // in the future.
+
+    // Calling setupTimer() multiple times updates call back function
+    // and interval.
+    //
     // There are two timers:
     //  itimer (A)
     //   (Calls TimerCallBackCounter / TimerCallBack)
     //     - increments internal counter in callback function
     //       (TimerCallBackCounter)
     //       interval: 2 seconds
-    //     - io_service_->stop() (TimerCallBack)
+    //     - io_service_.stop() (TimerCallBack)
     //       interval: 1 second
     //  itimer_overwriter (B)
     //   (Calls TimerCallBackOverwriter)
@@ -558,16 +587,16 @@
     //              |change call back function
     // (B) i--------+--------S
     //                       ^(stop io_service on fail)
-
-    IntervalTimer itimer(*io_service_);
-    IntervalTimer itimer_overwriter(*io_service_);
+    //
+
+    IntervalTimer itimer(io_service_);
+    IntervalTimer itimer_overwriter(io_service_);
     // store start time
     boost::posix_time::ptime start;
     start = boost::posix_time::microsec_clock::universal_time();
-    itimer.setupTimer(IntervalTimer::Callback(TimerCallBackCounter(this)), 2);
-    itimer_overwriter.setupTimer(
-        IntervalTimer::Callback(TimerCallBackOverwriter(this, itimer)), 3);
-    io_service_->run();
+    itimer.setupTimer(TimerCallBackCounter(this), 2);
+    itimer_overwriter.setupTimer(TimerCallBackOverwriter(this, itimer), 3);
+    io_service_.run();
     // reaches here after timer expired
     // if interval is updated, it takes
     //   3 seconds for TimerCallBackOverwriter
@@ -584,7 +613,7 @@
     if (delta.is_negative()) {
         delta.invert_sign();
     }
-    // expect call back is updated: TimerCallBack is called
+    // expect callback function is updated: TimerCallBack is called
     EXPECT_TRUE(timer_called_);
     // expect interval is updated
     EXPECT_TRUE(delta < TIMER_MERGIN_MSEC);

Modified: branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac347/src/bin/auth/tests/auth_srv_unittest.cc Wed Dec 22 13:05:42 2010
@@ -124,14 +124,14 @@
                     response_obuffer(0), response_renderer(response_obuffer)
     {
         server.setXfrinSession(&notify_session);
-        server.setStatsSession(&stats_session);
+        server.setStatisticsSession(&statistics_session);
     }
     ~AuthSrvTest() {
         delete io_message;
         delete endpoint;
     }
     MockSession notify_session;
-    MockSession stats_session;
+    MockSession statistics_session;
     MockXfroutClient xfrout;
     AuthSrv server;
     Message request_message;
@@ -771,21 +771,76 @@
     EXPECT_EQ(00, server.getCacheSlots());
 }
 
-TEST_F(AuthSrvTest, queryCounterUDP) {
-    // submit UDP query and check query counter
+// Submit UDP normal query and check query counter
+TEST_F(AuthSrvTest, queryCounterUDPNormal) {
+    // The counter should be initialized to 0.
+    EXPECT_EQ(0, server.getCounter(AuthCounters::COUNTER_UDP));
     createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
                         RRType::NS(), IPPROTO_UDP);
     EXPECT_TRUE(server.processMessage(*io_message, parse_message,
                                       response_renderer));
-    EXPECT_EQ(1, server.getCounters().at(QueryCounters::COUNTER_UDP));
-}
-
-TEST_F(AuthSrvTest, queryCounterTCP) {
-    // submit TCP query and check query counter
+    // After processing UDP query, the counter should be 1.
+    EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_UDP));
+}
+
+// Submit TCP normal query and check query counter
+TEST_F(AuthSrvTest, queryCounterTCPNormal) {
+    // The counter should be initialized to 0.
+    EXPECT_EQ(0, server.getCounter(AuthCounters::COUNTER_TCP));
     createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
                         RRType::NS(), IPPROTO_TCP);
     EXPECT_TRUE(server.processMessage(*io_message, parse_message,
                                       response_renderer));
-    EXPECT_EQ(1, server.getCounters().at(QueryCounters::COUNTER_TCP));
-}
-}
+    // After processing TCP query, the counter should be 1.
+    EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP));
+}
+
+// Submit TCP AXFR query and check query counter
+TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
+    // The counter should be initialized to 0.
+    EXPECT_EQ(0, server.getCounter(AuthCounters::COUNTER_TCP));
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::AXFR(), IPPROTO_TCP);
+    // It returns false. see AXFRSuccess test.
+    EXPECT_FALSE(server.processMessage(*io_message, parse_message,
+                                      response_renderer));
+    // After processing TCP AXFR query, the counter should be 1.
+    EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP));
+}
+
+// class for queryCounterUnexpected test
+// getProtocol() returns IPPROTO_IP
+class DummyUnknownSocket : public IOSocket {
+public:
+    DummyUnknownSocket() {}
+    virtual int getNative() const { return (0); }
+    virtual int getProtocol() const { return (IPPROTO_IP); }
+};
+
+// function for queryCounterUnexpected test
+// returns a reference to a static object of DummyUnknownSocket
+IOSocket&
+getDummyUnknownSocket() {
+    static DummyUnknownSocket socket;
+    return (socket);
+}
+
+// Submit unexpected type of query and check it throws IPPROTO_IP
+TEST_F(AuthSrvTest, queryCounterUnexpected) {
+    // Create UDP query packet.
+    createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
+                        RRType::NS(), IPPROTO_UDP);
+
+    // Modify the message
+    delete io_message;
+    endpoint = IOEndpoint::create(IPPROTO_UDP,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
+    io_message = new IOMessage(request_renderer.getData(),
+                               request_renderer.getLength(),
+                               getDummyUnknownSocket(), *endpoint);
+
+    EXPECT_THROW(server.processMessage(*io_message, parse_message,
+                                       response_renderer),
+                 isc::Unexpected);
+}
+}

Modified: branches/trac347/src/bin/auth/tests/statistics_unittest.cc
==============================================================================
--- branches/trac347/src/bin/auth/tests/statistics_unittest.cc (original)
+++ branches/trac347/src/bin/auth/tests/statistics_unittest.cc Wed Dec 22 13:05:42 2010
@@ -33,7 +33,7 @@
 
 namespace {
 
-class QueryCountersTest : public ::testing::Test {
+class AuthCountersTest : public ::testing::Test {
 private:
     class MockSession : public AbstractSession {
     public:
@@ -71,46 +71,46 @@
     };
 
 protected:
-    QueryCountersTest() : counters(verbose_mode_) {
-        counters.setStatsSession(&stats_session_);
-    }
-    ~QueryCountersTest() {
-    }
-    MockSession stats_session_;
-    QueryCounters counters;
+    AuthCountersTest() : verbose_mode_(false), counters(verbose_mode_) {
+        counters.setStatisticsSession(&statistics_session_);
+    }
+    ~AuthCountersTest() {
+    }
+    MockSession statistics_session_;
     bool verbose_mode_;
+    AuthCounters counters;
 };
 
 void
-QueryCountersTest::MockSession::establish(const char*) {}
-
-void
-QueryCountersTest::MockSession::disconnect() {}
-
-void
-QueryCountersTest::MockSession::subscribe(string, string)
+AuthCountersTest::MockSession::establish(const char*) {}
+
+void
+AuthCountersTest::MockSession::disconnect() {}
+
+void
+AuthCountersTest::MockSession::subscribe(string, string)
 {}
 
 void
-QueryCountersTest::MockSession::unsubscribe(string, string)
+AuthCountersTest::MockSession::unsubscribe(string, string)
 {}
 
 void
-QueryCountersTest::MockSession::startRead(boost::function<void()>)
+AuthCountersTest::MockSession::startRead(boost::function<void()>)
 {}
 
 int
-QueryCountersTest::MockSession::reply(ConstElementPtr, ConstElementPtr) {
+AuthCountersTest::MockSession::reply(ConstElementPtr, ConstElementPtr) {
     return (-1);
 }
 
 bool
-QueryCountersTest::MockSession::hasQueuedMsgs() const {
+AuthCountersTest::MockSession::hasQueuedMsgs() const {
     return (false);
 }
 
 int
-QueryCountersTest::MockSession::group_sendmsg(ConstElementPtr msg,
+AuthCountersTest::MockSession::group_sendmsg(ConstElementPtr msg,
                                               string group, string, string)
 {
     if (throw_session_error_) {
@@ -122,7 +122,7 @@
 }
 
 bool
-QueryCountersTest::MockSession::group_recvmsg(ConstElementPtr&,
+AuthCountersTest::MockSession::group_recvmsg(ConstElementPtr&,
                                               ConstElementPtr& msg, bool, int)
 {
     if (throw_session_timeout_) {
@@ -133,68 +133,83 @@
 }
 
 void
-QueryCountersTest::MockSession::setThrowSessionError(bool flag) {
+AuthCountersTest::MockSession::setThrowSessionError(bool flag) {
     throw_session_error_ = flag;
 }
 
 void
-QueryCountersTest::MockSession::setThrowSessionTimeout(bool flag) {
+AuthCountersTest::MockSession::setThrowSessionTimeout(bool flag) {
     throw_session_timeout_ = flag;
 }
 
-TEST_F(QueryCountersTest, incrementUDPCounter) {
-    EXPECT_NO_THROW(counters.inc(QueryCounters::COUNTER_UDP));
-}
-
-TEST_F(QueryCountersTest, incrementTCPCounter) {
-    EXPECT_NO_THROW(counters.inc(QueryCounters::COUNTER_TCP));
-}
-
-TEST_F(QueryCountersTest, incrementInvalidCounter) {
-    EXPECT_THROW(counters.inc(QueryCounters::COUNTER_TYPES),
-                 isc::InvalidParameter);
-}
-
-TEST_F(QueryCountersTest, submitStatisticsWithoutSession) {
-    // Set stats_session to NULL and call submitStatistics().
+TEST_F(AuthCountersTest, incrementUDPCounter) {
+    // The counter should be initialized to 0.
+    EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_UDP));
+    EXPECT_NO_THROW(counters.inc(AuthCounters::COUNTER_UDP));
+    // After increment, the counter should be 1.
+    EXPECT_EQ(1, counters.getCounter(AuthCounters::COUNTER_UDP));
+}
+
+TEST_F(AuthCountersTest, incrementTCPCounter) {
+    // The counter should be initialized to 0.
+    EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_TCP));
+    EXPECT_NO_THROW(counters.inc(AuthCounters::COUNTER_TCP));
+    // After increment, the counter should be 1.
+    EXPECT_EQ(1, counters.getCounter(AuthCounters::COUNTER_TCP));
+}
+
+TEST_F(AuthCountersTest, incrementInvalidCounter) {
+    // Expect to throw isc::InvalidParameter if the type of the counter is
+    // invalid.
+    EXPECT_THROW(counters.inc(AuthCounters::COUNTER_TYPES),
+                 std::out_of_range);
+}
+
+TEST_F(AuthCountersTest, submitStatisticsWithoutSession) {
+    // Set statistics_session to NULL and call submitStatistics().
     // Expect to return false.
-    counters.setStatsSession(NULL);
+    counters.setStatisticsSession(NULL);
     EXPECT_FALSE(counters.submitStatistics());
 }
 
-TEST_F(QueryCountersTest, submitStatisticsWithException) {
+TEST_F(AuthCountersTest, submitStatisticsWithException) {
     // Exception SessionError and SessionTimeout will be thrown
     // while sending statistics data.
     // Both expect to return false.
-    stats_session_.setThrowSessionError(true);
+    statistics_session_.setThrowSessionError(true);
     EXPECT_FALSE(counters.submitStatistics());
-    stats_session_.setThrowSessionError(false);
-    stats_session_.setThrowSessionTimeout(true);
+    statistics_session_.setThrowSessionError(false);
+    statistics_session_.setThrowSessionTimeout(true);
     EXPECT_FALSE(counters.submitStatistics());
-    stats_session_.setThrowSessionTimeout(false);
-}
-
-TEST_F(QueryCountersTest, submitStatistics) {
+    statistics_session_.setThrowSessionTimeout(false);
+}
+
+TEST_F(AuthCountersTest, submitStatistics) {
     // Submit statistics data.
     // Validate if it submits correct data.
 
+    // Counters should be initialized to 0.
+    EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_UDP));
+    EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_TCP));
+
     // UDP query counter is set to 2.
-    counters.inc(QueryCounters::COUNTER_UDP);
-    counters.inc(QueryCounters::COUNTER_UDP);
+    counters.inc(AuthCounters::COUNTER_UDP);
+    counters.inc(AuthCounters::COUNTER_UDP);
     // TCP query counter is set to 1.
-    counters.inc(QueryCounters::COUNTER_TCP);
+    counters.inc(AuthCounters::COUNTER_TCP);
     counters.submitStatistics();
 
     // Destination is "Stats".
-    EXPECT_EQ("Stats", stats_session_.msg_destination);
+    EXPECT_EQ("Stats", statistics_session_.msg_destination);
     // Command is "set".
-    EXPECT_EQ("set", stats_session_.sent_msg->get("command")
+    EXPECT_EQ("set", statistics_session_.sent_msg->get("command")
                          ->get(0)->stringValue());
-    ConstElementPtr stats_data = stats_session_.sent_msg ->get("command")
-                                     ->get(1)->get("stats_data");
+    ConstElementPtr statistics_data = statistics_session_.sent_msg
+                                          ->get("command")->get(1)
+                                          ->get("stats_data");
     // UDP query counter is 2 and TCP query counter is 1.
-    EXPECT_EQ(2, stats_data->get("auth.queries.udp")->intValue());
-    EXPECT_EQ(1, stats_data->get("auth.queries.tcp")->intValue());
-}
-
-}
+    EXPECT_EQ(2, statistics_data->get("auth.queries.udp")->intValue());
+    EXPECT_EQ(1, statistics_data->get("auth.queries.tcp")->intValue());
+}
+
+}




More information about the bind10-changes mailing list