BIND 10 master, updated. 8cb640551a6fc4a101bdc4c6469630d0cbeb7076 [510] whitespace style fix
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Dec 14 09:34:28 UTC 2011
The branch, master has been updated
via 8cb640551a6fc4a101bdc4c6469630d0cbeb7076 (commit)
via ff81c97c2ad006e5e28f33e67d3a8bde1dccc523 (commit)
via afddaf4c5718c2a0cc31f2eee79c4e0cc625499f (commit)
via b14866797ef758fd4e3a920b8ca9eab50053e120 (commit)
via a5c940634fbc5dffd80ff2c0cfd98294322583f7 (commit)
via f84f26374fd7f359eafd98a00c9065d2c1aaa924 (commit)
via 7a5214fa8a316a8096509226ff498ee1c39ec2de (commit)
via 1cd21e93810b18a4aa90d7d20afa6dbc3c0a8861 (commit)
from 2f4433fb15900481e4fb976a93692e68084c3925 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8cb640551a6fc4a101bdc4c6469630d0cbeb7076
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Wed Dec 14 18:29:28 2011 +0900
[510] whitespace style fix
commit ff81c97c2ad006e5e28f33e67d3a8bde1dccc523
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Wed Dec 14 18:11:27 2011 +0900
[510] forgot to merge
commit afddaf4c5718c2a0cc31f2eee79c4e0cc625499f
Merge: b14866797ef758fd4e3a920b8ca9eab50053e120 2f4433fb15900481e4fb976a93692e68084c3925
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Wed Dec 14 18:00:35 2011 +0900
Merge branch 'master' into trac510
Conflicts:
src/lib/statistics/counter_dict.cc
src/lib/statistics/counter_dict.h
src/lib/statistics/tests/counter_dict_unittest.cc
commit b14866797ef758fd4e3a920b8ca9eab50053e120
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Tue Dec 13 16:45:52 2011 +0900
[510] modify interface for enumerating zone names in CounterDictionary
commit a5c940634fbc5dffd80ff2c0cfd98294322583f7
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Tue Dec 13 15:41:01 2011 +0900
[510] fix unused variable
commit f84f26374fd7f359eafd98a00c9065d2c1aaa924
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Fri Dec 9 13:58:57 2011 +0900
[510] use std::map instead of boost::unordered_map
boost/unordered_map.hpp is available since Boost 1.36. we should
consider to check if the header file is present with configure.
commit 7a5214fa8a316a8096509226ff498ee1c39ec2de
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Fri Dec 9 13:56:32 2011 +0900
Revert "[510] do not use BOOST_FOREACH to address build failure on Mac OS X"
This reverts commit 1cd21e93810b18a4aa90d7d20afa6dbc3c0a8861.
commit 1cd21e93810b18a4aa90d7d20afa6dbc3c0a8861
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date: Thu Dec 8 19:51:44 2011 +0900
[510] do not use BOOST_FOREACH to address build failure on Mac OS X
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 6 +
configure.ac | 2 +
src/bin/auth/Makefile.am | 1 +
src/bin/auth/auth_srv.cc | 6 +-
src/bin/auth/auth_srv.h | 2 +-
src/bin/auth/benchmarks/Makefile.am | 1 +
src/bin/auth/statistics.cc | 61 +++--
src/bin/auth/statistics.h | 22 +-
src/bin/auth/tests/Makefile.am | 1 +
src/bin/auth/tests/auth_srv_unittest.cc | 16 +-
src/bin/auth/tests/statistics_unittest.cc | 39 ++--
src/lib/Makefile.am | 2 +-
src/lib/statistics/Makefile.am | 24 ++
src/lib/statistics/counter.cc | 68 ++++++
src/lib/statistics/counter.h | 55 +++++
src/lib/statistics/counter_dict.cc | 249 ++++++++++++++++++++
src/lib/statistics/counter_dict.h | 145 ++++++++++++
src/lib/{asiolink => statistics}/tests/Makefile.am | 15 +-
src/lib/statistics/tests/counter_dict_unittest.cc | 174 ++++++++++++++
src/lib/statistics/tests/counter_unittest.cc | 85 +++++++
.../tests/run_unittests.cc | 4 +-
21 files changed, 901 insertions(+), 77 deletions(-)
create mode 100644 src/lib/statistics/Makefile.am
create mode 100644 src/lib/statistics/counter.cc
create mode 100644 src/lib/statistics/counter.h
create mode 100644 src/lib/statistics/counter_dict.cc
create mode 100644 src/lib/statistics/counter_dict.h
copy src/lib/{asiolink => statistics}/tests/Makefile.am (67%)
create mode 100644 src/lib/statistics/tests/counter_dict_unittest.cc
create mode 100644 src/lib/statistics/tests/counter_unittest.cc
copy src/lib/{asiolink => statistics}/tests/run_unittests.cc (90%)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index c64c9f7..7a2a121 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+344. [func] y-aharen
+ src/lib/statistics: Added statistics counter library for entire server
+ items and per zone items. Also, modified b10-auth to use it. It is
+ also intended to use in the other modules such as b10-resolver.
+ (Trac #510, git TBD)
+
343. [func] jelte
Added IXFR-out system tests, based on the first two test sets of
http://bind10.isc.org/wiki/IxfrSystemTests.
diff --git a/configure.ac b/configure.ac
index e370e21..4c1d9cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -984,6 +984,8 @@ AC_CONFIG_FILES([Makefile
src/lib/util/tests/Makefile
src/lib/acl/Makefile
src/lib/acl/tests/Makefile
+ src/lib/statistics/Makefile
+ src/lib/statistics/tests/Makefile
tests/Makefile
tests/system/Makefile
tests/tools/Makefile
diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am
index 4d8ec83..3d60432 100644
--- a/src/bin/auth/Makefile.am
+++ b/src/bin/auth/Makefile.am
@@ -71,6 +71,7 @@ b10_auth_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
b10_auth_LDADD += $(top_builddir)/src/lib/log/liblog.la
b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
b10_auth_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
+b10_auth_LDADD += $(top_builddir)/src/lib/statistics/libstatistics.la
b10_auth_LDADD += $(SQLITE_LIBS)
# TODO: config.h.in is wrong because doesn't honor pkgdatadir
diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc
index caf69b9..da05e48 100644
--- a/src/bin/auth/auth_srv.cc
+++ b/src/bin/auth/auth_srv.cc
@@ -671,9 +671,9 @@ void
AuthSrvImpl::incCounter(const int protocol) {
// Increment query counter.
if (protocol == IPPROTO_UDP) {
- counters_.inc(AuthCounters::COUNTER_UDP_QUERY);
+ counters_.inc(AuthCounters::SERVER_UDP_QUERY);
} else if (protocol == IPPROTO_TCP) {
- counters_.inc(AuthCounters::COUNTER_TCP_QUERY);
+ counters_.inc(AuthCounters::SERVER_TCP_QUERY);
} else {
// unknown protocol
isc_throw(Unexpected, "Unknown protocol: " << protocol);
@@ -766,7 +766,7 @@ bool AuthSrv::submitStatistics() const {
}
uint64_t
-AuthSrv::getCounter(const AuthCounters::CounterType type) const {
+AuthSrv::getCounter(const AuthCounters::ServerCounterType type) const {
return (impl_->counters_.getCounter(type));
}
diff --git a/src/bin/auth/auth_srv.h b/src/bin/auth/auth_srv.h
index f2259a2..a50e427 100644
--- a/src/bin/auth/auth_srv.h
+++ b/src/bin/auth/auth_srv.h
@@ -343,7 +343,7 @@ public:
/// \param type Type of a counter to get the value of
///
/// \return the value of the counter.
- uint64_t getCounter(const AuthCounters::CounterType type) const;
+ uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
/**
* \brief Set and get the addresses we listen on.
diff --git a/src/bin/auth/benchmarks/Makefile.am b/src/bin/auth/benchmarks/Makefile.am
index dd00ea5..da6a5c8 100644
--- a/src/bin/auth/benchmarks/Makefile.am
+++ b/src/bin/auth/benchmarks/Makefile.am
@@ -35,5 +35,6 @@ query_bench_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
query_bench_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
query_bench_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
query_bench_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
+query_bench_LDADD += $(top_builddir)/src/lib/statistics/libstatistics.la
query_bench_LDADD += $(SQLITE_LIBS)
diff --git a/src/bin/auth/statistics.cc b/src/bin/auth/statistics.cc
index e62719f..7397a50 100644
--- a/src/bin/auth/statistics.cc
+++ b/src/bin/auth/statistics.cc
@@ -18,48 +18,67 @@
#include <cc/data.h>
#include <cc/session.h>
+#include <statistics/counter.h>
+#include <statistics/counter_dict.h>
+
#include <sstream>
#include <iostream>
+#include <boost/noncopyable.hpp>
+
using namespace isc::auth;
+using namespace isc::statistics;
// TODO: We need a namespace ("auth_server"?) to hold
// AuthSrv and AuthCounters.
-class AuthCountersImpl {
-private:
- // prohibit copy
- AuthCountersImpl(const AuthCountersImpl& source);
- AuthCountersImpl& operator=(const AuthCountersImpl& source);
+// TODO: Make use of wrappers like isc::dns::Opcode
+// for counter item type.
+
+class AuthCountersImpl : boost::noncopyable {
public:
AuthCountersImpl();
~AuthCountersImpl();
- void inc(const AuthCounters::CounterType type);
+ void inc(const AuthCounters::ServerCounterType type);
+ void inc(const std::string& zone,
+ const AuthCounters::PerZoneCounterType type);
bool submitStatistics() const;
void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
void registerStatisticsValidator
(AuthCounters::validator_type validator);
// Currently for testing purpose only
- uint64_t getCounter(const AuthCounters::CounterType type) const;
+ uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
private:
- std::vector<uint64_t> counters_;
+ Counter server_counter_;
+ CounterDictionary per_zone_counter_;
isc::cc::AbstractSession* statistics_session_;
AuthCounters::validator_type validator_;
};
AuthCountersImpl::AuthCountersImpl() :
// initialize counter
- // size: AuthCounters::COUNTER_TYPES, initial value: 0
- counters_(AuthCounters::COUNTER_TYPES, 0),
+ // size of server_counter_: AuthCounters::SERVER_COUNTER_TYPES
+ // size of per_zone_counter_: AuthCounters::PER_ZONE_COUNTER_TYPES
+ server_counter_(AuthCounters::SERVER_COUNTER_TYPES),
+ per_zone_counter_(AuthCounters::PER_ZONE_COUNTER_TYPES),
statistics_session_(NULL)
-{}
+{
+ per_zone_counter_.addElement("_SERVER_");
+}
AuthCountersImpl::~AuthCountersImpl()
{}
void
-AuthCountersImpl::inc(const AuthCounters::CounterType type) {
- ++counters_.at(type);
+AuthCountersImpl::inc(const AuthCounters::ServerCounterType type) {
+ server_counter_.inc(type);
+}
+
+void
+AuthCountersImpl::inc(const std::string& zone,
+ const AuthCounters::PerZoneCounterType type)
+{
+ per_zone_counter_[zone].inc(type);
}
bool
@@ -73,9 +92,9 @@ AuthCountersImpl::submitStatistics() const {
<< "{ \"owner\": \"Auth\","
<< " \"data\":"
<< "{ \"queries.udp\": "
- << counters_.at(AuthCounters::COUNTER_UDP_QUERY)
+ << server_counter_.get(AuthCounters::SERVER_UDP_QUERY)
<< ", \"queries.tcp\": "
- << counters_.at(AuthCounters::COUNTER_TCP_QUERY)
+ << server_counter_.get(AuthCounters::SERVER_TCP_QUERY)
<< " }"
<< "}"
<< "]}";
@@ -126,19 +145,17 @@ AuthCountersImpl::registerStatisticsValidator
// Currently for testing purpose only
uint64_t
-AuthCountersImpl::getCounter(const AuthCounters::CounterType type) const {
- return (counters_.at(type));
+AuthCountersImpl::getCounter(const AuthCounters::ServerCounterType type) const {
+ return (server_counter_.get(type));
}
AuthCounters::AuthCounters() : impl_(new AuthCountersImpl())
{}
-AuthCounters::~AuthCounters() {
- delete impl_;
-}
+AuthCounters::~AuthCounters() {}
void
-AuthCounters::inc(const AuthCounters::CounterType type) {
+AuthCounters::inc(const AuthCounters::ServerCounterType type) {
impl_->inc(type);
}
@@ -155,7 +172,7 @@ AuthCounters::setStatisticsSession
}
uint64_t
-AuthCounters::getCounter(const AuthCounters::CounterType type) const {
+AuthCounters::getCounter(const AuthCounters::ServerCounterType type) const {
return (impl_->getCounter(type));
}
diff --git a/src/bin/auth/statistics.h b/src/bin/auth/statistics.h
index c930414..280b4a5 100644
--- a/src/bin/auth/statistics.h
+++ b/src/bin/auth/statistics.h
@@ -17,6 +17,7 @@
#include <cc/session.h>
#include <stdint.h>
+#include <boost/scoped_ptr.hpp>
class AuthCountersImpl;
@@ -51,13 +52,18 @@ class AuthCountersImpl;
/// \todo Consider overhead of \c AuthCounters::inc()
class AuthCounters {
private:
- AuthCountersImpl* impl_;
+ boost::scoped_ptr<AuthCountersImpl> impl_;
public:
// Enum for the type of counter
- enum CounterType {
- COUNTER_UDP_QUERY = 0, ///< COUNTER_UDP_QUERY: counter for UDP queries
- COUNTER_TCP_QUERY = 1, ///< COUNTER_TCP_QUERY: counter for TCP queries
- COUNTER_TYPES = 2 ///< The number of defined counters
+ enum ServerCounterType {
+ SERVER_UDP_QUERY, ///< SERVER_UDP_QUERY: counter for UDP queries
+ SERVER_TCP_QUERY, ///< SERVER_TCP_QUERY: counter for TCP queries
+ SERVER_COUNTER_TYPES ///< The number of defined counters
+ };
+ enum PerZoneCounterType {
+ ZONE_UDP_QUERY, ///< ZONE_UDP_QUERY: counter for UDP queries
+ ZONE_TCP_QUERY, ///< ZONE_TCP_QUERY: counter for TCP queries
+ PER_ZONE_COUNTER_TYPES ///< The number of defined counters
};
/// The constructor.
///
@@ -77,9 +83,9 @@ public:
///
/// \throw std::out_of_range \a type is unknown.
///
- /// usage: counter.inc(CounterType::COUNTER_UDP_QUERY);
+ /// usage: counter.inc(AuthCounters::SERVER_UDP_QUERY);
///
- void inc(const CounterType type);
+ void inc(const ServerCounterType type);
/// \brief Submit statistics counters to statistics module.
///
@@ -130,7 +136,7 @@ public:
///
/// \return the value of the counter specified by \a type.
///
- uint64_t getCounter(const AuthCounters::CounterType type) const;
+ uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
/// \brief A type of validation function for the specification in
/// isc::config::ModuleSpec.
diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am
index d27386e..b5b96d7 100644
--- a/src/bin/auth/tests/Makefile.am
+++ b/src/bin/auth/tests/Makefile.am
@@ -65,6 +65,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/statistics/libstatistics.la
endif
noinst_PROGRAMS = $(TESTS)
diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc
index ac25cd6..d90006a 100644
--- a/src/bin/auth/tests/auth_srv_unittest.cc
+++ b/src/bin/auth/tests/auth_srv_unittest.cc
@@ -779,7 +779,7 @@ TEST_F(AuthSrvTest, cacheSlots) {
// 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_QUERY));
+ EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
// Create UDP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
@@ -788,13 +788,13 @@ TEST_F(AuthSrvTest, queryCounterUDPNormal) {
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
// After processing UDP query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_UDP_QUERY));
+ EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
}
// 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_QUERY));
+ EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
// Create TCP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
@@ -803,13 +803,13 @@ TEST_F(AuthSrvTest, queryCounterTCPNormal) {
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
// After processing TCP query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
}
// 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_QUERY));
+ EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::AXFR());
createRequestPacket(request_message, IPPROTO_TCP);
@@ -818,13 +818,13 @@ TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
// After processing TCP AXFR query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
}
// Submit TCP IXFR query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
// The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::IXFR());
createRequestPacket(request_message, IPPROTO_TCP);
@@ -833,7 +833,7 @@ TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
// After processing TCP IXFR query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
}
// class for queryCounterUnexpected test
diff --git a/src/bin/auth/tests/statistics_unittest.cc b/src/bin/auth/tests/statistics_unittest.cc
index 98e573b..3f19f91 100644
--- a/src/bin/auth/tests/statistics_unittest.cc
+++ b/src/bin/auth/tests/statistics_unittest.cc
@@ -150,25 +150,24 @@ AuthCountersTest::MockSession::setThrowSessionTimeout(bool flag) {
TEST_F(AuthCountersTest, incrementUDPCounter) {
// The counter should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_UDP_QUERY));
- EXPECT_NO_THROW(counters.inc(AuthCounters::COUNTER_UDP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
+ EXPECT_NO_THROW(counters.inc(AuthCounters::SERVER_UDP_QUERY));
// After increment, the counter should be 1.
- EXPECT_EQ(1, counters.getCounter(AuthCounters::COUNTER_UDP_QUERY));
+ EXPECT_EQ(1, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
}
TEST_F(AuthCountersTest, incrementTCPCounter) {
// The counter should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_TCP_QUERY));
- EXPECT_NO_THROW(counters.inc(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
+ EXPECT_NO_THROW(counters.inc(AuthCounters::SERVER_TCP_QUERY));
// After increment, the counter should be 1.
- EXPECT_EQ(1, counters.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(1, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
}
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);
+ // Expect to throw an isc::OutOfRange
+ EXPECT_THROW(counters.inc(AuthCounters::SERVER_COUNTER_TYPES),
+ isc::OutOfRange);
}
TEST_F(AuthCountersTest, submitStatisticsWithoutSession) {
@@ -195,14 +194,14 @@ TEST_F(AuthCountersTest, submitStatisticsWithoutValidator) {
// Validate if it submits correct data.
// Counters should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_UDP_QUERY));
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
// UDP query counter is set to 2.
- counters.inc(AuthCounters::COUNTER_UDP_QUERY);
- counters.inc(AuthCounters::COUNTER_UDP_QUERY);
+ counters.inc(AuthCounters::SERVER_UDP_QUERY);
+ counters.inc(AuthCounters::SERVER_UDP_QUERY);
// TCP query counter is set to 1.
- counters.inc(AuthCounters::COUNTER_TCP_QUERY);
+ counters.inc(AuthCounters::SERVER_TCP_QUERY);
counters.submitStatistics();
// Destination is "Stats".
@@ -237,14 +236,14 @@ TEST_F(AuthCountersTest, submitStatisticsWithValidator) {
counters.registerStatisticsValidator(validator);
// Counters should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_UDP_QUERY));
- EXPECT_EQ(0, counters.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
+ EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
// UDP query counter is set to 2.
- counters.inc(AuthCounters::COUNTER_UDP_QUERY);
- counters.inc(AuthCounters::COUNTER_UDP_QUERY);
+ counters.inc(AuthCounters::SERVER_UDP_QUERY);
+ counters.inc(AuthCounters::SERVER_UDP_QUERY);
// TCP query counter is set to 1.
- counters.inc(AuthCounters::COUNTER_TCP_QUERY);
+ counters.inc(AuthCounters::SERVER_TCP_QUERY);
// checks the value returned by submitStatistics
EXPECT_TRUE(counters.submitStatistics());
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index a569ea7..9ebd541 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,3 +1,3 @@
SUBDIRS = exceptions util log cryptolink dns cc config acl xfr bench \
asiolink asiodns nsas cache resolve testutils datasrc \
- server_common python dhcp
+ server_common python dhcp statistics
diff --git a/src/lib/statistics/Makefile.am b/src/lib/statistics/Makefile.am
new file mode 100644
index 0000000..6c7b910
--- /dev/null
+++ b/src/lib/statistics/Makefile.am
@@ -0,0 +1,24 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES) $(MULTITHREADING_FLAG)
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/statistics -I$(top_builddir)/src/lib/statistics
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+# Some versions of GCC warn about some versions of Boost regarding
+# missing initializer for members in its posix_time.
+# https://svn.boost.org/trac/boost/ticket/3477
+# But older GCC compilers don't have the flag.
+AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
+
+if USE_CLANGPP
+# clang++ complains about unused function parameters in some boost header
+# files.
+AM_CXXFLAGS += -Wno-unused-parameter
+endif
+
+lib_LTLIBRARIES = libstatistics.la
+libstatistics_la_SOURCES = counter.h counter.cc
+libstatistics_la_SOURCES += counter_dict.h counter_dict.cc
+
+CLEANFILES = *.gcno *.gcda
diff --git a/src/lib/statistics/counter.cc b/src/lib/statistics/counter.cc
new file mode 100644
index 0000000..9cb1a6f
--- /dev/null
+++ b/src/lib/statistics/counter.cc
@@ -0,0 +1,68 @@
+#include <vector>
+
+#include <boost/noncopyable.hpp>
+
+#include <statistics/counter.h>
+
+namespace {
+const unsigned int InitialValue = 0;
+} // namespace
+
+namespace isc {
+namespace statistics {
+
+class CounterImpl : boost::noncopyable {
+ private:
+ std::vector<Counter::Value> counters_;
+ public:
+ CounterImpl(const size_t nelements);
+ ~CounterImpl();
+ void inc(const Counter::Type&);
+ const Counter::Value& get(const Counter::Type&) const;
+};
+
+CounterImpl::CounterImpl(const size_t items) :
+ counters_(items, InitialValue)
+{
+ if (items == 0) {
+ isc_throw(isc::InvalidParameter, "Items must not be 0");
+ }
+}
+
+CounterImpl::~CounterImpl() {}
+
+void
+CounterImpl::inc(const Counter::Type& type) {
+ if(type >= counters_.size()) {
+ isc_throw(isc::OutOfRange, "Counter type is out of range");
+ }
+ ++counters_.at(type);
+ return;
+}
+
+const Counter::Value&
+CounterImpl::get(const Counter::Type& type) const {
+ if(type >= counters_.size()) {
+ isc_throw(isc::OutOfRange, "Counter type is out of range");
+ }
+ return (counters_.at(type));
+}
+
+Counter::Counter(const size_t items) : impl_(new CounterImpl(items))
+{}
+
+Counter::~Counter() {}
+
+void
+Counter::inc(const Type& type) {
+ impl_->inc(type);
+ return;
+}
+
+const Counter::Value&
+Counter::get(const Type& type) const {
+ return (impl_->get(type));
+}
+
+} // namespace statistics
+} // namespace isc
diff --git a/src/lib/statistics/counter.h b/src/lib/statistics/counter.h
new file mode 100644
index 0000000..b077616
--- /dev/null
+++ b/src/lib/statistics/counter.h
@@ -0,0 +1,55 @@
+#ifndef __COUNTER_H
+#define __COUNTER_H 1
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <exceptions/exceptions.h>
+
+namespace isc {
+namespace statistics {
+
+// forward declaration for pImpl idiom
+class CounterImpl;
+
+class Counter : boost::noncopyable {
+private:
+ boost::scoped_ptr<CounterImpl> impl_;
+public:
+ typedef unsigned int Type;
+ typedef unsigned int Value;
+
+ /// The constructor.
+ ///
+ /// This constructor is mostly exception free. But it may still throw
+ /// a standard exception if memory allocation fails inside the method.
+ ///
+ /// \param items A number of counter items to hold (greater than 0)
+ ///
+ /// \throw isc::InvalidParameter \a items is 0
+ Counter(const size_t items);
+
+ /// The destructor.
+ ///
+ /// This method never throws an exception.
+ ~Counter();
+
+ /// \brief Increment a counter item specified with \a type.
+ ///
+ /// \param type %Counter item to increment
+ ///
+ /// \throw isc::OutOfRange \a type is invalid
+ void inc(const Type& type);
+
+ /// \brief Get the value of a counter item specified with \a type.
+ ///
+ /// \param type %Counter item to get the value of
+ ///
+ /// \throw isc::OutOfRange \a type is invalid
+ const Value& get(const Type& type) const;
+};
+
+} // namespace statistics
+} // namespace isc
+
+#endif
diff --git a/src/lib/statistics/counter_dict.cc b/src/lib/statistics/counter_dict.cc
new file mode 100644
index 0000000..08302be
--- /dev/null
+++ b/src/lib/statistics/counter_dict.cc
@@ -0,0 +1,249 @@
+#include <cassert>
+#include <stdexcept>
+#include <iterator>
+#include <map>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <statistics/counter_dict.h>
+
+namespace {
+typedef boost::shared_ptr<isc::statistics::Counter> CounterPtr;
+typedef std::map<std::string, CounterPtr> DictionaryMap;
+}
+
+namespace isc {
+namespace statistics {
+
+// Implementation detail class for CounterDictionary::ConstIterator
+class CounterDictionaryConstIteratorImpl;
+
+class CounterDictionaryImpl : boost::noncopyable {
+private:
+ DictionaryMap dictionary_;
+ std::vector<std::string> elements_;
+ const size_t items_;
+ // Default constructor is forbidden; number of counter items must be
+ // specified at the construction of this class.
+ CounterDictionaryImpl();
+public:
+ CounterDictionaryImpl(const size_t items);
+ ~CounterDictionaryImpl();
+ void addElement(const std::string& name);
+ void deleteElement(const std::string& name);
+ Counter& getElement(const std::string& name);
+public:
+ CounterDictionaryConstIteratorImpl begin() const;
+ CounterDictionaryConstIteratorImpl end() const;
+};
+
+// Constructor with number of items
+CounterDictionaryImpl::CounterDictionaryImpl(const size_t items) :
+ items_(items)
+{
+ // The number of items must not be 0
+ if (items == 0) {
+ isc_throw(isc::InvalidParameter, "Items must not be 0");
+ }
+}
+
+// Destructor
+CounterDictionaryImpl::~CounterDictionaryImpl() {}
+
+void
+CounterDictionaryImpl::addElement(const std::string& name) {
+ // throw if the element already exists
+ if (dictionary_.count(name) != 0) {
+ isc_throw(isc::InvalidParameter,
+ "Element " << name << " already exists");
+ }
+ assert(items_ != 0);
+ // Create a new Counter and add to the map
+ dictionary_.insert(
+ DictionaryMap::value_type(name, CounterPtr(new Counter(items_))));
+}
+
+void
+CounterDictionaryImpl::deleteElement(const std::string& name) {
+ size_t result = dictionary_.erase(name);
+ if (result != 1) {
+ // If an element with specified name does not exist, throw
+ // isc::OutOfRange.
+ isc_throw(isc::OutOfRange, "Element " << name << " does not exist");
+ }
+}
+
+Counter&
+CounterDictionaryImpl::getElement(const std::string& name) {
+ try {
+ return (*(dictionary_.at(name)));
+ } catch (const std::out_of_range&) {
+ // If an element with specified name does not exist, throw
+ // isc::OutOfRange.
+ isc_throw(isc::OutOfRange, "Element " << name << " does not exist");
+ }
+}
+
+// Constructor
+// Initialize impl_
+CounterDictionary::CounterDictionary(const size_t items) :
+ impl_(new CounterDictionaryImpl(items))
+{}
+
+// Destructor
+// impl_ will be freed automatically with scoped_ptr
+CounterDictionary::~CounterDictionary() {}
+
+void
+CounterDictionary::addElement(const std::string& name) {
+ impl_->addElement(name);
+}
+
+void
+CounterDictionary::deleteElement(const std::string& name) {
+ impl_->deleteElement(name);
+}
+
+Counter&
+CounterDictionary::getElement(const std::string& name) const {
+ return (impl_->getElement(name));
+}
+
+Counter&
+CounterDictionary::operator[](const std::string& name) const {
+ return (impl_->getElement(name));
+}
+
+// Implementation detail class for CounterDictionary::ConstIterator
+class CounterDictionaryConstIteratorImpl {
+ public:
+ CounterDictionaryConstIteratorImpl();
+ ~CounterDictionaryConstIteratorImpl();
+ CounterDictionaryConstIteratorImpl(
+ const CounterDictionaryConstIteratorImpl &other);
+ CounterDictionaryConstIteratorImpl &operator=(
+ const CounterDictionaryConstIteratorImpl &source);
+ CounterDictionaryConstIteratorImpl(
+ DictionaryMap::const_iterator iterator);
+ public:
+ void increment();
+ const CounterDictionary::ConstIterator::value_type&
+ dereference() const;
+ bool equal(const CounterDictionaryConstIteratorImpl& other) const;
+ private:
+ DictionaryMap::const_iterator iterator_;
+};
+
+CounterDictionaryConstIteratorImpl::CounterDictionaryConstIteratorImpl() {}
+
+CounterDictionaryConstIteratorImpl::~CounterDictionaryConstIteratorImpl() {}
+
+// Copy constructor: deep copy of iterator_
+CounterDictionaryConstIteratorImpl::CounterDictionaryConstIteratorImpl(
+ const CounterDictionaryConstIteratorImpl &other) :
+ iterator_(other.iterator_)
+{}
+
+// Assignment operator: deep copy of iterator_
+CounterDictionaryConstIteratorImpl &
+CounterDictionaryConstIteratorImpl::operator=(
+ const CounterDictionaryConstIteratorImpl &source)
+{
+ iterator_ = source.iterator_;
+ return (*this);
+}
+
+// Constructor from implementation detail DictionaryMap::const_iterator
+CounterDictionaryConstIteratorImpl::CounterDictionaryConstIteratorImpl(
+ DictionaryMap::const_iterator iterator) :
+ iterator_(iterator)
+{}
+
+CounterDictionaryConstIteratorImpl
+CounterDictionaryImpl::begin() const {
+ return (CounterDictionaryConstIteratorImpl(dictionary_.begin()));
+}
+
+CounterDictionaryConstIteratorImpl
+CounterDictionaryImpl::end() const {
+ return (CounterDictionaryConstIteratorImpl(dictionary_.end()));
+}
+
+void
+CounterDictionaryConstIteratorImpl::increment() {
+ ++iterator_;
+ return;
+}
+
+const CounterDictionary::ConstIterator::value_type&
+CounterDictionaryConstIteratorImpl::dereference() const {
+ return (iterator_->first);
+}
+
+bool
+CounterDictionaryConstIteratorImpl::equal(
+ const CounterDictionaryConstIteratorImpl& other) const
+{
+ return (iterator_ == other.iterator_);
+}
+
+CounterDictionary::ConstIterator
+CounterDictionary::begin() const {
+ return (CounterDictionary::ConstIterator(
+ CounterDictionaryConstIteratorImpl(impl_->begin())));
+}
+
+CounterDictionary::ConstIterator
+CounterDictionary::end() const {
+ return (CounterDictionary::ConstIterator(
+ CounterDictionaryConstIteratorImpl(impl_->end())));
+}
+
+CounterDictionary::ConstIterator::ConstIterator() :
+ impl_(new CounterDictionaryConstIteratorImpl())
+{}
+
+CounterDictionary::ConstIterator::~ConstIterator() {}
+
+// Copy constructor: deep copy of impl_
+CounterDictionary::ConstIterator::ConstIterator(
+ const CounterDictionary::ConstIterator& source) :
+ impl_(new CounterDictionaryConstIteratorImpl(*(source.impl_)))
+{}
+
+// Assignment operator: deep copy of impl_
+CounterDictionary::ConstIterator &
+CounterDictionary::ConstIterator::operator=(
+ const CounterDictionary::ConstIterator &source)
+{
+ *impl_ = *source.impl_;
+ return (*this);
+}
+
+// The constructor from implementation detail
+CounterDictionary::ConstIterator::ConstIterator(
+ const CounterDictionaryConstIteratorImpl& source) :
+ impl_(new CounterDictionaryConstIteratorImpl(source))
+{}
+
+const CounterDictionary::ConstIterator::value_type&
+CounterDictionary::ConstIterator::dereference() const
+{
+ return (impl_->dereference());
+}
+
+bool
+CounterDictionary::ConstIterator::equal(
+ CounterDictionary::ConstIterator const& other) const
+{
+ return (impl_->equal(*(other.impl_)));
+}
+
+void
+CounterDictionary::ConstIterator::increment() {
+ impl_->increment();
+ return;
+}
+
+} // namespace statistics
+} // namespace isc
diff --git a/src/lib/statistics/counter_dict.h b/src/lib/statistics/counter_dict.h
new file mode 100644
index 0000000..4a4cab1
--- /dev/null
+++ b/src/lib/statistics/counter_dict.h
@@ -0,0 +1,145 @@
+#ifndef __COUNTER_DICT_H
+#define __COUNTER_DICT_H 1
+
+#include <string>
+#include <vector>
+#include <utility>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+#include <exceptions/exceptions.h>
+#include <statistics/counter.h>
+
+namespace isc {
+namespace statistics {
+
+class CounterDictionaryImpl;
+class CounterDictionaryConstIteratorImpl;
+
+class CounterDictionary : boost::noncopyable {
+private:
+ boost::scoped_ptr<CounterDictionaryImpl> impl_;
+ // Default constructor is forbidden; number of counter items must be
+ // specified at the construction of this class.
+ CounterDictionary();
+public:
+ /// The constructor.
+ /// This constructor is mostly exception free. But it may still throw
+ /// a standard exception if memory allocation fails inside the method.
+ ///
+ /// \param items A number of counter items to hold (greater than 0)
+ ///
+ /// \throw isc::InvalidParameter \a items is 0
+ CounterDictionary(const size_t items);
+
+ /// The destructor.
+ ///
+ /// This method never throws an exception.
+ ~CounterDictionary();
+
+ /// \brief Add an element
+ ///
+ /// \throw isc::InvalidParameter \a element already exists.
+ ///
+ /// \param name A name of the element to append
+ void addElement(const std::string& name);
+
+ /// \brief Delete
+ ///
+ /// \throw isc::OutOfRange \a element does not exist.
+ ///
+ /// \param name A name of the element to delete
+ void deleteElement(const std::string& name);
+
+ /// \brief Lookup
+ ///
+ /// \throw isc::OutOfRange \a element does not exist.
+ ///
+ /// \param name A name of the element to get the counters
+ Counter& getElement(const std::string &name) const;
+
+ /// Same as getElement()
+ Counter& operator[](const std::string &name) const;
+
+ /// \brief \c ConstIterator is a constant iterator that provides an
+ /// interface for enumerating name of zones stored in CounterDictionary.
+ ///
+ /// This class is derived from boost::iterator_facade and uses pImpl
+ /// idiom not to expose implementation detail of
+ /// CounterDictionary::iterator.
+ ///
+ /// It is intended to walk through the elements when sending the
+ /// counters to statistics module.
+ class ConstIterator :
+ public boost::iterator_facade<ConstIterator,
+ const std::string,
+ boost::forward_traversal_tag>
+ {
+ private:
+ boost::scoped_ptr<CounterDictionaryConstIteratorImpl> impl_;
+ public:
+ /// The constructor.
+ ///
+ /// This constructor is mostly exception free. But it may still
+ /// throw a standard exception if memory allocation fails
+ /// inside the method.
+ ConstIterator();
+ /// The destructor.
+ ///
+ /// This method never throws an exception.
+ ~ConstIterator();
+ /// The assignment operator.
+ ///
+ /// This method is mostly exception free. But it may still
+ /// throw a standard exception if memory allocation fails
+ /// inside the method.
+ ConstIterator& operator=(const ConstIterator &source);
+ /// The copy constructor.
+ ///
+ /// This constructor is mostly exception free. But it may still
+ /// throw a standard exception if memory allocation fails
+ /// inside the method.
+ ConstIterator(const ConstIterator& source);
+ /// The constructor from implementation detail.
+ ///
+ /// This method is used to create an instance of ConstIterator
+ /// by CounterDict::begin() and CounterDict::end().
+ ///
+ /// This constructor is mostly exception free. But it may still
+ /// throw a standard exception if memory allocation fails
+ /// inside the method.
+ ConstIterator(
+ const CounterDictionaryConstIteratorImpl& source);
+ private:
+ /// \brief An internal method to increment this iterator.
+ void increment();
+ /// \brief An internal method to check equality.
+ bool equal(const ConstIterator& other) const;
+ /// \brief An internal method to dereference this iterator.
+ const value_type& dereference() const;
+ private:
+ friend class boost::iterator_core_access;
+ };
+
+ typedef ConstIterator const_iterator;
+
+ /// \brief Return an iterator corresponding to the beginning of the
+ /// elements stored in CounterDictionary.
+ ///
+ /// This method is mostly exception free. But it may still throw a
+ /// standard exception if memory allocation fails inside the method.
+ const_iterator begin() const;
+
+ /// \brief Return an iterator corresponding to the end of the elements
+ /// stored in CounterDictionary.
+ ///
+ /// This method is mostly exception free. But it may still throw a
+ /// standard exception if memory allocation fails inside the method.
+ const_iterator end() const;
+};
+
+} // namespace statistics
+} // namespace isc
+
+#endif
diff --git a/src/lib/statistics/tests/Makefile.am b/src/lib/statistics/tests/Makefile.am
new file mode 100644
index 0000000..d66acdf
--- /dev/null
+++ b/src/lib/statistics/tests/Makefile.am
@@ -0,0 +1,47 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+# Some versions of GCC warn about some versions of Boost regarding
+# missing initializer for members in its posix_time.
+# https://svn.boost.org/trac/boost/ticket/3477
+# But older GCC compilers don't have the flag.
+AM_CXXFLAGS += $(WARNING_NO_MISSING_FIELD_INITIALIZERS_CFLAG)
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_SOURCES = run_unittests.cc
+run_unittests_SOURCES += counter_unittest.cc
+run_unittests_SOURCES += counter_dict_unittest.cc
+
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+
+run_unittests_LDADD = $(GTEST_LDADD)
+run_unittests_LDADD += $(top_builddir)/src/lib/statistics/libstatistics.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+
+# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
+# B10_CXXFLAGS)
+run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_GXX
+run_unittests_CXXFLAGS += -Wno-unused-parameter
+endif
+if USE_CLANGPP
+# Same for clang++, but we need to turn off -Werror completely.
+run_unittests_CXXFLAGS += -Wno-error
+endif
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/statistics/tests/counter_dict_unittest.cc b/src/lib/statistics/tests/counter_dict_unittest.cc
new file mode 100644
index 0000000..34ab219
--- /dev/null
+++ b/src/lib/statistics/tests/counter_dict_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright (C) 2011 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.
+
+#include <config.h>
+#include <gtest/gtest.h>
+
+#include <set>
+
+#include <boost/foreach.hpp>
+
+#include <statistics/counter_dict.h>
+
+enum CounterItems {
+ ITEM1 = 0,
+ ITEM2 = 1,
+ ITEM3 = 2,
+ NUMBER_OF_ITEMS = 3
+};
+
+using namespace isc::statistics;
+
+TEST(CounterDictionaryCreateTest, invalidCounterSize) {
+ // Creating counter with 0 elements will cause an isc::InvalidParameter
+ // exception
+ EXPECT_THROW(CounterDictionary counters(0), isc::InvalidParameter);
+}
+
+// This fixture is for testing CounterDictionary.
+class CounterDictionaryTest : public ::testing::Test {
+protected:
+ CounterDictionaryTest() : counters(NUMBER_OF_ITEMS) {
+ counters.addElement("test");
+ counters.addElement("sub.test");
+ }
+ ~CounterDictionaryTest() {}
+
+ CounterDictionary counters;
+};
+
+TEST_F(CounterDictionaryTest, initializeCheck) {
+ // Check if the all counters are initialized with 0
+ EXPECT_EQ(counters["test"].get(ITEM1), 0);
+ EXPECT_EQ(counters["test"].get(ITEM2), 0);
+ EXPECT_EQ(counters["test"].get(ITEM3), 0);
+}
+
+TEST_F(CounterDictionaryTest, getElement) {
+ // Another member function to get counters for the element
+ EXPECT_EQ(counters.getElement("test").get(ITEM1), 0);
+ EXPECT_EQ(counters.getElement("test").get(ITEM2), 0);
+ EXPECT_EQ(counters.getElement("test").get(ITEM3), 0);
+}
+
+TEST_F(CounterDictionaryTest, incrementCounterItem) {
+ // Increment counters
+ counters["test"].inc(ITEM1);
+ counters["test"].inc(ITEM2);
+ counters["test"].inc(ITEM2);
+ counters["test"].inc(ITEM3);
+ counters["test"].inc(ITEM3);
+ counters["test"].inc(ITEM3);
+ // Check if the counters have expected values
+ EXPECT_EQ(counters["test"].get(ITEM1), 1);
+ EXPECT_EQ(counters["test"].get(ITEM2), 2);
+ EXPECT_EQ(counters["test"].get(ITEM3), 3);
+ EXPECT_EQ(counters["sub.test"].get(ITEM1), 0);
+ EXPECT_EQ(counters["sub.test"].get(ITEM2), 0);
+ EXPECT_EQ(counters["sub.test"].get(ITEM3), 0);
+}
+
+TEST_F(CounterDictionaryTest, deleteElement) {
+ // Ensure the element is accessible
+ EXPECT_EQ(counters["test"].get(ITEM1), 0);
+ EXPECT_EQ(counters["test"].get(ITEM2), 0);
+ EXPECT_EQ(counters["test"].get(ITEM3), 0);
+ // Delete the element
+ counters.deleteElement("test");
+ // Accessing to the deleted element will cause an isc::OutOfRange exception
+ EXPECT_THROW(counters["test"].get(ITEM1), isc::OutOfRange);
+ // Deleting an element which does not exist will cause an isc::OutOfRange
+ // exception
+ EXPECT_THROW(counters.deleteElement("test"), isc::OutOfRange);
+}
+
+TEST_F(CounterDictionaryTest, invalidCounterItem) {
+ // Incrementing out-of-bound counter will cause an isc::OutOfRange
+ // exception
+ EXPECT_THROW(counters["test"].inc(NUMBER_OF_ITEMS), isc::OutOfRange);
+}
+
+TEST_F(CounterDictionaryTest, uniquenessCheck) {
+ // Adding an element which already exists will cause an isc::OutOfRange
+ // exception
+ EXPECT_THROW(counters.addElement("test"), isc::InvalidParameter);
+}
+
+TEST_F(CounterDictionaryTest, iteratorTest) {
+ // Increment counters
+ counters["test"].inc(ITEM1);
+ counters["sub.test"].inc(ITEM2);
+ counters["sub.test"].inc(ITEM2);
+
+ // boolean values to check all of the elements can be accessed through
+ // the iterator
+ bool element_test_visited = false;
+ bool element_sub_test_visited = false;
+ // Walk through the elements with iterator
+ // Check if the elements "test" and "sub.test" appears only once
+ // and the counters have expected value
+ for (CounterDictionary::ConstIterator i = counters.begin(),
+ e = counters.end();
+ i != e;
+ ++i
+ )
+ {
+ const std::string& zone = *i;
+ if (zone == "test" && element_test_visited == false) {
+ element_test_visited = true;
+ // Check if the counters have expected value
+ EXPECT_EQ(counters[zone].get(ITEM1), 1);
+ EXPECT_EQ(counters[zone].get(ITEM2), 0);
+ } else if (zone == "sub.test" &&
+ element_sub_test_visited == false) {
+ element_sub_test_visited = true;
+ // Check if the counters have expected value
+ EXPECT_EQ(counters[zone].get(ITEM1), 0);
+ EXPECT_EQ(counters[zone].get(ITEM2), 2);
+ } else {
+ // Test fails when reaches here: the element is not expected or
+ // the element appeared twice
+ FAIL() << "Unexpected iterator value";
+ }
+ }
+ // Check if the "test" and "sub.test" is accessible
+ EXPECT_TRUE(element_test_visited);
+ EXPECT_TRUE(element_sub_test_visited);
+}
+
+TEST_F(CounterDictionaryTest, iteratorCopyTest) {
+ // Increment counters
+ counters["test"].inc(ITEM1);
+ counters["sub.test"].inc(ITEM2);
+ counters["sub.test"].inc(ITEM2);
+
+ CounterDictionary::ConstIterator i1 = counters.begin();
+ CounterDictionary::ConstIterator i2(i1);
+ CounterDictionary::ConstIterator i3;
+ i3 = i1;
+
+ EXPECT_TRUE(i1 == i2);
+ EXPECT_TRUE(i1 == i3);
+ EXPECT_TRUE(i2 == i3);
+
+ ++i2;
+ EXPECT_TRUE(i1 != i2);
+ EXPECT_TRUE(i1 == i3);
+ EXPECT_TRUE(i2 != i3);
+
+ ++i3;
+ EXPECT_TRUE(i1 != i2);
+ EXPECT_TRUE(i1 != i3);
+ EXPECT_TRUE(i2 == i3);
+}
diff --git a/src/lib/statistics/tests/counter_unittest.cc b/src/lib/statistics/tests/counter_unittest.cc
new file mode 100644
index 0000000..e0d29ac
--- /dev/null
+++ b/src/lib/statistics/tests/counter_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright (C) 2011 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.
+
+#include <config.h>
+#include <gtest/gtest.h>
+
+#include <statistics/counter.h>
+
+namespace {
+enum CounterItems {
+ ITEM1 = 0,
+ ITEM2 = 1,
+ ITEM3 = 2,
+ NUMBER_OF_ITEMS = 3
+};
+}
+
+using namespace isc::statistics;
+
+TEST(CounterCreateTest, invalidCounterSize) {
+ // Creating counter with 0 elements will cause an isc::InvalidParameter
+ // exception
+ EXPECT_THROW(Counter counter(0), isc::InvalidParameter);
+}
+
+// This fixture is for testing Counter.
+class CounterTest : public ::testing::Test {
+protected:
+ CounterTest() : counter(NUMBER_OF_ITEMS) {}
+ ~CounterTest() {}
+
+ Counter counter;
+};
+
+TEST_F(CounterTest, createCounter) {
+ // Check if the all counters are initialized with 0
+ EXPECT_EQ(counter.get(ITEM1), 0);
+ EXPECT_EQ(counter.get(ITEM2), 0);
+ EXPECT_EQ(counter.get(ITEM3), 0);
+}
+
+TEST_F(CounterTest, incrementCounterItem) {
+ // Increment counters
+ counter.inc(ITEM1);
+ counter.inc(ITEM2);
+ counter.inc(ITEM2);
+ counter.inc(ITEM3);
+ counter.inc(ITEM3);
+ counter.inc(ITEM3);
+ // Check if the counters have expected values
+ EXPECT_EQ(counter.get(ITEM1), 1);
+ EXPECT_EQ(counter.get(ITEM2), 2);
+ EXPECT_EQ(counter.get(ITEM3), 3);
+ // Increment counters once more
+ counter.inc(ITEM1);
+ counter.inc(ITEM2);
+ counter.inc(ITEM2);
+ counter.inc(ITEM3);
+ counter.inc(ITEM3);
+ counter.inc(ITEM3);
+ // Check if the counters have expected values
+ EXPECT_EQ(counter.get(ITEM1), 2);
+ EXPECT_EQ(counter.get(ITEM2), 4);
+ EXPECT_EQ(counter.get(ITEM3), 6);
+}
+
+TEST_F(CounterTest, invalidCounterItem) {
+ // Incrementing out-of-bound counter will cause an isc::OutOfRange
+ // exception
+ EXPECT_THROW(counter.inc(NUMBER_OF_ITEMS), isc::OutOfRange);
+ // Trying to get out-of-bound counter will cause an isc::OutOfRange
+ // exception
+ EXPECT_THROW(counter.get(NUMBER_OF_ITEMS), isc::OutOfRange);
+}
diff --git a/src/lib/statistics/tests/run_unittests.cc b/src/lib/statistics/tests/run_unittests.cc
new file mode 100644
index 0000000..38a299e
--- /dev/null
+++ b/src/lib/statistics/tests/run_unittests.cc
@@ -0,0 +1,25 @@
+// Copyright (C) 2009 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.
+
+#include <gtest/gtest.h>
+#include <util/unittests/run_all.h>
+#include <log/logger_support.h>
+
+int
+main(int argc, char* argv[])
+{
+ ::testing::InitGoogleTest(&argc, argv); // Initialize Google test
+ isc::log::initLogger();
+ return (isc::util::unittests::run_all());
+}
More information about the bind10-changes
mailing list