[svn] commit: r4030 - in /branches/trac447: ./ doc/guide/ src/bin/auth/ src/bin/auth/benchmarks/ src/bin/auth/tests/ src/bin/auth/tests/testdata/ src/bin/bind10/ src/bin/bind10/tests/ src/bin/bindctl/ src/bin/bindctl/tests/ src/bin/cfgmgr/tests/ src/bin/cmdctl/ src/bin/cmdctl/tests/ src/bin/loadzone/ src/bin/loadzone/tests/correct/ src/bin/loadzone/tests/error/ src/bin/msgq/ src/bin/msgq/tests/ src/bin/recurse/ src/bin/stats/ src/bin/stats/tests/ src/bin/stats/tests/isc/util/ src/bin/tests/ src/bin/usermgr/ src/bin/xfrin/ src/bin/xfrin/tests/ src/bin/xfrout/ src/bin/xfrout/tests/ src/bin/zonemgr/ src/bin/zonemgr/tests/ src/lib/asiolink/ src/lib/asiolink/internal/ src/lib/asiolink/tests/ src/lib/config/ src/lib/config/tests/ src/lib/config/tests/testdata/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/dns/python/tests/ src/lib/python/isc/cc/tests/ src/lib/python/isc/config/ src/lib/python/isc/config/tests/ src/lib/python/isc/datasrc/tests/ src/lib/python/isc/log/tests/ src/lib/python/isc/net/tests/ src/lib/python/isc/notify/tests/ src/lib/python/isc/util/tests/ src/lib/python/isc/utils/
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Dec 28 10:31:10 UTC 2010
Author: vorner
Date: Tue Dec 28 10:31:10 2010
New Revision: 4030
Log:
Sync with trunk
Added:
branches/trac447/src/bin/auth/config.cc
- copied unchanged from r4028, trunk/src/bin/auth/config.cc
branches/trac447/src/bin/auth/config.h
- copied unchanged from r4028, trunk/src/bin/auth/config.h
branches/trac447/src/bin/auth/statistics.cc
- copied unchanged from r4028, trunk/src/bin/auth/statistics.cc
branches/trac447/src/bin/auth/statistics.h
- copied unchanged from r4028, trunk/src/bin/auth/statistics.h
branches/trac447/src/bin/auth/tests/config_unittest.cc
- copied unchanged from r4028, trunk/src/bin/auth/tests/config_unittest.cc
branches/trac447/src/bin/auth/tests/statistics_unittest.cc
- copied unchanged from r4028, trunk/src/bin/auth/tests/statistics_unittest.cc
branches/trac447/src/bin/auth/tests/testdata/
- copied from r4028, trunk/src/bin/auth/tests/testdata/
branches/trac447/src/lib/config/tests/testdata/data22_9.data
- copied unchanged from r4028, trunk/src/lib/config/tests/testdata/data22_9.data
branches/trac447/src/lib/python/isc/utils/ (props changed)
- copied from r4028, trunk/src/lib/python/isc/utils/
Modified:
branches/trac447/ (props changed)
branches/trac447/ChangeLog
branches/trac447/Makefile.am
branches/trac447/README
branches/trac447/configure.ac
branches/trac447/doc/guide/bind10-guide.xml
branches/trac447/src/bin/auth/Makefile.am
branches/trac447/src/bin/auth/auth.spec.pre.in
branches/trac447/src/bin/auth/auth_srv.cc
branches/trac447/src/bin/auth/auth_srv.h
branches/trac447/src/bin/auth/benchmarks/Makefile.am
branches/trac447/src/bin/auth/benchmarks/query_bench.cc
branches/trac447/src/bin/auth/change_user.cc
branches/trac447/src/bin/auth/common.h
branches/trac447/src/bin/auth/main.cc
branches/trac447/src/bin/auth/query.cc
branches/trac447/src/bin/auth/query.h
branches/trac447/src/bin/auth/tests/Makefile.am
branches/trac447/src/bin/auth/tests/auth_srv_unittest.cc
branches/trac447/src/bin/auth/tests/query_unittest.cc
branches/trac447/src/bin/bind10/bind10.py.in (props changed)
branches/trac447/src/bin/bind10/run_bind10.sh.in
branches/trac447/src/bin/bind10/tests/Makefile.am
branches/trac447/src/bin/bindctl/run_bindctl.sh.in
branches/trac447/src/bin/bindctl/tests/Makefile.am
branches/trac447/src/bin/cfgmgr/tests/Makefile.am
branches/trac447/src/bin/cmdctl/run_b10-cmdctl.sh.in
branches/trac447/src/bin/cmdctl/tests/Makefile.am
branches/trac447/src/bin/loadzone/run_loadzone.sh.in
branches/trac447/src/bin/loadzone/tests/correct/Makefile.am
branches/trac447/src/bin/loadzone/tests/error/Makefile.am
branches/trac447/src/bin/msgq/run_msgq.sh.in
branches/trac447/src/bin/msgq/tests/Makefile.am
branches/trac447/src/bin/recurse/b10-recurse.8
branches/trac447/src/bin/recurse/b10-recurse.xml
branches/trac447/src/bin/stats/run_b10-stats.sh.in
branches/trac447/src/bin/stats/run_b10-stats_stub.sh.in
branches/trac447/src/bin/stats/tests/Makefile.am
branches/trac447/src/bin/stats/tests/isc/util/ (props changed)
branches/trac447/src/bin/tests/Makefile.am
branches/trac447/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
branches/trac447/src/bin/xfrin/run_b10-xfrin.sh.in
branches/trac447/src/bin/xfrin/tests/Makefile.am
branches/trac447/src/bin/xfrout/run_b10-xfrout.sh.in
branches/trac447/src/bin/xfrout/tests/Makefile.am
branches/trac447/src/bin/zonemgr/run_b10-zonemgr.sh.in
branches/trac447/src/bin/zonemgr/tests/Makefile.am
branches/trac447/src/lib/asiolink/asiolink.cc
branches/trac447/src/lib/asiolink/asiolink.h
branches/trac447/src/lib/asiolink/internal/tcpdns.h
branches/trac447/src/lib/asiolink/tests/asiolink_unittest.cc
branches/trac447/src/lib/config/module_spec.cc
branches/trac447/src/lib/config/tests/module_spec_unittests.cc
branches/trac447/src/lib/config/tests/testdata/Makefile.am
branches/trac447/src/lib/config/tests/testdata/data22_8.data
branches/trac447/src/lib/datasrc/data_source.h
branches/trac447/src/lib/datasrc/memory_datasrc.cc
branches/trac447/src/lib/datasrc/memory_datasrc.h
branches/trac447/src/lib/datasrc/tests/memory_datasrc_unittest.cc
branches/trac447/src/lib/datasrc/tests/zonetable_unittest.cc
branches/trac447/src/lib/datasrc/zonetable.cc
branches/trac447/src/lib/datasrc/zonetable.h
branches/trac447/src/lib/dns/python/tests/Makefile.am
branches/trac447/src/lib/python/isc/cc/tests/Makefile.am
branches/trac447/src/lib/python/isc/config/ccsession.py
branches/trac447/src/lib/python/isc/config/config_data.py
branches/trac447/src/lib/python/isc/config/module_spec.py
branches/trac447/src/lib/python/isc/config/tests/Makefile.am
branches/trac447/src/lib/python/isc/config/tests/ccsession_test.py
branches/trac447/src/lib/python/isc/config/tests/config_data_test.py
branches/trac447/src/lib/python/isc/config/tests/module_spec_test.py
branches/trac447/src/lib/python/isc/datasrc/tests/Makefile.am
branches/trac447/src/lib/python/isc/log/tests/Makefile.am
branches/trac447/src/lib/python/isc/net/tests/Makefile.am
branches/trac447/src/lib/python/isc/notify/tests/Makefile.am
branches/trac447/src/lib/python/isc/util/tests/Makefile.am
Modified: branches/trac447/ChangeLog
==============================================================================
--- branches/trac447/ChangeLog (original)
+++ branches/trac447/ChangeLog Tue Dec 28 10:31:10 2010
@@ -1,3 +1,55 @@
+ 140. [func] y-aharen
+ 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.
+ 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 r4026)
+
+ 139. [build] jreed
+ Introduced configure option and make targets for generating
+ Python code coverage report. This adds new make targets:
+ report-python-coverage and clean-python-coverage. The C++
+ code coverage targets were renamed to clean-cpp-coverage
+ and report-cpp-coverage. (Trac #362, svn r4023)
+
+ 138. [func]* jinmei
+ b10-auth: added a configuration interface to support in memory
+ data sources. For example, the following command to bindctl
+ will configure a memory data source containing the "example.com"
+ zone with the zone file named "example.com.zone":
+ > config set Auth/datasources/ [{"type": "memory", "zones": \
+ [{"origin": "example.com", "file": "example.com.zone"}]}]
+ By default, the memory data source is disabled; it must be
+ configured explicitly. To disable it again, specify a null list
+ for Auth/datasources:
+ > config set Auth/datasources/ []
+ Notes: it's currently for class IN only. The zone files are not
+ actually loaded into memory yet (which will soon be implemented).
+ This is an experimental feature and the syntax may change in
+ future versions.
+ (Trac #446, svn r3998)
+
+ 137. [bug] jreed
+ Fix run_*.sh scripts that are used for development testing
+ so they use a msgq socket file in the build tree.
+ (Trac #226, svn r3989)
+
+ 136. [bug] jelte
+ bindctl (and the configuration manager in general) now no longer
+ accepts 'unknown' data; i.e. data for modules that it does not know
+ about, or configuration items that are not specified in the .spec
+ files.
+ (Trac #202, svn r3967)
+
+ 135. [func] each
+ Add b10-recurse. This is an example recursive server that
+ currently does forwarding only and no caching.
+ (Trac #327, svn r3903)
+
134. [func] vorner
b10-recurse supports timeouts and retries in forwarder mode.
(Trac #401, svn r3660)
@@ -8,7 +60,7 @@
(Trac #393, r3602)
132. [func] vorner
- The b10-recursive is configured through config manager.
+ The b10-recurse is configured through config manager.
It has "listen_on" and "forward_addresses" options.
(Trac #389, r3448)
@@ -39,7 +91,6 @@
for root zone was added.
(Trac #85, svn r3836)
->>>>>>> .merge-right.r3894
127. [bug] stephen
During normal operation process termination and resurrection messages
are now output regardless of the state of the verbose flag.
Modified: branches/trac447/Makefile.am
==============================================================================
--- branches/trac447/Makefile.am (original)
+++ branches/trac447/Makefile.am Tue Dec 28 10:31:10 2010
@@ -8,20 +8,30 @@
# When running distcheck target, do not install the configurations
DISTCHECK_CONFIGURE_FLAGS = --disable-install-configurations
-clean-coverage:
+clean-cpp-coverage:
@if [ $(USE_LCOV) = yes ] ; then \
$(LCOV) --directory . --zerocounters; \
rm -rf coverage/; \
else \
- echo "Code coverage not enabled at configuration time"; \
- exit 1; \
+ echo "C++ code coverage not enabled at configuration time." ; \
+ echo "Use: ./configure --with-lcov" ; \
+ fi
+
+clean-python-coverage:
+ @if [ $(USE_PYCOVERAGE) = yes ] ; then \
+ rm -f $(abs_top_srcdir)/.coverage ; \
+ rm -rf $(abs_top_srcdir)/py-coverage-html ; \
+ else \
+ echo "Python code coverage not enabled at configuration time." ; \
+ echo "Use: ./configure --with-pycoverage" ; \
fi
perform-coverage: check
-report-coverage:
- $(LCOV) --capture --directory . --output-file all.info
- $(LCOV) --remove all.info \
+report-cpp-coverage:
+ @if [ $(USE_LCOV) = yes ] ; then \
+ $(LCOV) --capture --directory . --output-file all.info ; \
+ $(LCOV) --remove all.info \
c++/4.4\*/\* \
c++/4.4\*/backward/\* \
c++/4.4\*/bits/\* \
@@ -36,10 +46,29 @@
\*_unittests.cc \
\*_unittest.cc \
\*_unittests.h \
- --output report.info
- $(GENHTML) --legend -o coverage report.info
-
+ --output report.info ; \
+ $(GENHTML) --legend -o $(abs_top_builddir)/coverage-cpp-html report.info ; \
+ echo "Generated C++ Code Coverage report in HTML at $(abs_top_builddir)/coverage-cpp-html" ; \
+ else \
+ echo "C++ code coverage not enabled at configuration time." ; \
+ echo "Use: ./configure --with-lcov" ; \
+ fi
+
+report-python-coverage:
+ @if [ $(USE_PYCOVERAGE) = yes ] ; then \
+ $(PYCOVERAGE) html -d $(abs_top_builddir)/coverage-python-html --omit=src/bin/bind10/tests/,src/bin/bindctl/tests/,src/bin/cfgmgr/tests/,src/bin/cmdctl/tests/,src/bin/loadzone/tests/,src/bin/msgq/tests/,src/bin/stats/tests/,src/bin/tests/,src/bin/xfrin/tests/,src/bin/xfrout/tests/,src/bin/zonemgr/tests/,src/lib/dns/python/tests/,src/lib/dns/tests/,src/lib/python/isc/cc/tests/,src/lib/python/isc/config/tests/,src/lib/python/isc/datasrc/tests/,src/lib/python/isc/log/tests/,src/lib/python/isc/net/tests/,src/lib/python/isc/notify/tests/,src/lib/python/isc/util/tests/ ; \
+ echo "Generated Python Code Coverage report in HTML at $(abs_top_builddir)/coverage-python-html" ; \
+ else \
+ echo "Python code coverage not enabled at configuration time." ; \
+ echo "Use: ./configure --with-pycoverage" ; \
+ fi
+
+# for python and c++ test coverage
coverage: clean-coverage perform-coverage report-coverage
+
+clean-coverage: clean-cpp-coverage clean-python-coverage
+
+report-coverage: report-cpp-coverage report-python-coverage
#### include external sources in the distributed tarball:
EXTRA_DIST = ext/asio/README
Modified: branches/trac447/README
==============================================================================
--- branches/trac447/README (original)
+++ branches/trac447/README Tue Dec 28 10:31:10 2010
@@ -15,11 +15,11 @@
This release includes the bind10 master process, b10-msgq message
bus, b10-auth authoritative DNS server (with SQLite3 backend),
-b10-cmdctl remote control daemon, b10-cfgmgr configuration manager,
-b10-xfrin AXFR inbound service, b10-xfrout outgoing AXFR service,
-b10-zonemgr secondary manager, b10-stats statistics collection and
-reporting daemon, and a new libdns++ library for C++ with a python
-wrapper.
+b10-recurse forwarding DNS server, b10-cmdctl remote control daemon,
+b10-cfgmgr configuration manager, b10-xfrin AXFR inbound service,
+b10-xfrout outgoing AXFR service, b10-zonemgr secondary manager,
+b10-stats statistics collection and reporting daemon, and a new
+libdns++ library for C++ with a python wrapper.
Documentation is included and also available via the BIND 10
website at http://bind10.isc.org/
@@ -93,26 +93,55 @@
TEST COVERAGE
+Code coverage reports may be generated using make. These are
+based on running on the unit tests. The resulting reports are placed
+in coverage-cpp-html and coverage-python-html directories for C++
+and Python, respectively.
+
The code coverage report for the C++ tests uses LCOV. It is available
-from http://ltp.sourceforge.net/. To generate your own HTML report,
+from http://ltp.sourceforge.net/. To generate the HTML report,
first configure BIND 10 with:
./configure --with-lcov
+The code coverage report for the Python tests uses coverage.py (aka
+pycoverage). It is available from http://nedbatchelder.com/code/coverage/.
+To generate the HTML report, first configure BIND 10 with:
+
+ ./configure --with-pycoverage
+
Doing code coverage tests:
make coverage
- Does the following:
+ Does the clean, perform, and report targets for C++ and Python.
make clean-coverage
- Zeroes the lcov code coverage counters and removes the coverage HTML.
+ Zeroes the code coverage counters and removes the HTML reports
+ for C++ and Python.
make perform-coverage
- Runs the C++ tests (using googletests framework).
+ Runs the C++ (using the googletests framework) and Python
+ tests.
make report-coverage
- Generates the coverage HTML, excluding some unrelated headers.
- The HTML reports are placed in a directory called coverage/.
+ Generates the coverage reports in HTML for C++ and Python.
+
+ make clean-cpp-coverage
+ Zeroes the code coverage counters and removes the HTML report
+ for the C++ tests.
+
+ make clean-python-coverage
+ Zeroes the code coverage counters and removes the HTML report
+ for the Python tests.
+
+ make report-cpp-coverage
+ Generates the coverage report in HTML for C++, excluding
+ some unrelated headers. The HTML reports are placed in a
+ directory called coverage-cpp-html/.
+
+ make report-python-coverage
+ Generates the coverage report in HTML for Python. The HTML
+ reports are placed in a directory called coverage-python-html/.
DEVELOPERS
Modified: branches/trac447/configure.ac
==============================================================================
--- branches/trac447/configure.ac (original)
+++ branches/trac447/configure.ac Tue Dec 28 10:31:10 2010
@@ -287,6 +287,26 @@
AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if sockaddr has a sa_len member, and corresponding sin_len and sun_len])],
AC_MSG_RESULT(no))
+AC_ARG_WITH(pycoverage,
+[ --with-pycoverage[=PROGRAM] enable python code coverage using the specified coverage], pycoverage="$withval", pycoverage="no")
+if test "$pycoverage" = "no" ; then
+ # just run the tests normally with python
+ PYCOVERAGE_RUN="${PYTHON}"
+ USE_PYCOVERAGE="no"
+elif test "$pycoverage" = "yes" ; then
+ PYCOVERAGE="coverage"
+ PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
+ USE_PYCOVERAGE="yes"
+else
+ PYCOVERAGE="$pycoverage"
+ PYCOVERAGE_RUN="${PYCOVERAGE} run --branch --append"
+ USE_PYCOVERAGE="yes"
+fi
+AM_CONDITIONAL(ENABLE_PYTHON_COVERAGE, test x$USE_PYCOVERAGE != xno)
+AC_SUBST(PYCOVERAGE)
+AC_SUBST(PYCOVERAGE_RUN)
+AC_SUBST(USE_PYCOVERAGE)
+
AC_ARG_WITH(lcov,
[ --with-lcov[=PROGRAM] enable gtest and coverage target using the specified lcov], lcov="$withval", lcov="no")
@@ -351,7 +371,7 @@
BOOST_INCLUDES="-I${boost_include_path}"
CPPFLAGS="$CPPFLAGS $BOOST_INCLUDES"
fi
-AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp boost/interprocess/sync/interprocess_upgradable_mutex.hpp],,
+AC_CHECK_HEADERS([boost/shared_ptr.hpp boost/foreach.hpp boost/interprocess/sync/interprocess_upgradable_mutex.hpp boost/date_time/posix_time/posix_time_types.hpp boost/bind.hpp boost/function.hpp],,
AC_MSG_ERROR([Missing required header files.]))
CPPFLAGS="$CPPFLAGS_SAVES"
AC_SUBST(BOOST_INCLUDES)
@@ -729,7 +749,8 @@
Developer:
Google Tests: $gtest_path
- Code Coverage: $USE_LCOV
+ C++ Code Coverage: $USE_LCOV
+ Python Code Coverage: $USE_PYCOVERAGE
Generate Manuals: $enable_man
END
Modified: branches/trac447/doc/guide/bind10-guide.xml
==============================================================================
--- branches/trac447/doc/guide/bind10-guide.xml (original)
+++ branches/trac447/doc/guide/bind10-guide.xml Tue Dec 28 10:31:10 2010
@@ -42,9 +42,8 @@
<note>
<para>
- BIND 10, at this time, does not provide a recursive
- DNS server. It does provide a EDNS0- and DNSSEC-capable
- authoritative DNS server.
+ BIND 10 provides a EDNS0- and DNSSEC-capable
+ authoritative DNS server and a forwarding DNS server.
</para>
</note>
Modified: branches/trac447/src/bin/auth/Makefile.am
==============================================================================
--- branches/trac447/src/bin/auth/Makefile.am (original)
+++ branches/trac447/src/bin/auth/Makefile.am Tue Dec 28 10:31:10 2010
@@ -34,12 +34,14 @@
spec_config.h: spec_config.h.pre
$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
-BUILT_SOURCES = spec_config.h
+BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-auth
-b10_auth_SOURCES = auth_srv.cc auth_srv.h
-b10_auth_SOURCES += query.cc query.h
+b10_auth_SOURCES = query.cc query.h
+b10_auth_SOURCES += auth_srv.cc auth_srv.h
b10_auth_SOURCES += change_user.cc change_user.h
+b10_auth_SOURCES += config.cc config.h
b10_auth_SOURCES += common.h
+b10_auth_SOURCES += statistics.cc statistics.h
b10_auth_SOURCES += main.cc
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
Modified: branches/trac447/src/bin/auth/auth.spec.pre.in
==============================================================================
--- branches/trac447/src/bin/auth/auth.spec.pre.in (original)
+++ branches/trac447/src/bin/auth/auth.spec.pre.in Tue Dec 28 10:31:10 2010
@@ -7,6 +7,51 @@
"item_type": "string",
"item_optional": true,
"item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3"
+ },
+ { "item_name": "datasources",
+ "item_type": "list",
+ "item_optional": true,
+ "item_default": [],
+ "list_item_spec": {
+ "item_name": "list_element",
+ "item_type": "map",
+ "item_optional": false,
+ "item_default": {},
+ "map_item_spec": [
+ { "item_name": "type",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ },
+ { "item_name": "class",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": "IN"
+ },
+ { "item_name": "zones",
+ "item_type": "list",
+ "item_optional": false,
+ "item_default": [],
+ "list_item_spec": {
+ "item_name": "list_element",
+ "item_type": "map",
+ "item_optional": true,
+ "map_item_spec": [
+ { "item_name": "origin",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ },
+ { "item_name": "file",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ }
+ ]
+ }
+ }
+ ]
+ }
}
],
"commands": [
@@ -14,6 +59,11 @@
"command_name": "shutdown",
"command_description": "Shut down authoritative DNS server",
"command_args": []
+ },
+ {
+ "command_name": "sendstats",
+ "command_description": "Send data to a statistics module at once",
+ "command_args": []
}
]
}
Modified: branches/trac447/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/trac447/src/bin/auth/auth_srv.cc (original)
+++ branches/trac447/src/bin/auth/auth_srv.cc Tue Dec 28 10:31:10 2010
@@ -45,13 +45,17 @@
#include <datasrc/query.h>
#include <datasrc/data_source.h>
+#include <datasrc/memory_datasrc.h>
#include <datasrc/static_datasrc.h>
#include <datasrc/sqlite3_datasrc.h>
#include <xfr/xfrout_client.h>
#include <auth/common.h>
+#include <auth/config.h>
#include <auth/auth_srv.h>
+#include <auth/query.h>
+#include <auth/statistics.h>
using namespace std;
@@ -59,6 +63,7 @@
using namespace isc::cc;
using namespace isc::datasrc;
using namespace isc::dns;
+using namespace isc::auth;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::config;
@@ -90,8 +95,15 @@
bool verbose_mode_;
AbstractSession* xfrin_session_;
+ /// In-memory data source. Currently class IN only for simplicity.
+ const RRClass memory_datasrc_class_;
+ AuthSrv::MemoryDataSrcPtr memory_datasrc_;
+
/// Hot spot cache
isc::datasrc::HotCache cache_;
+
+ /// Query counters for statistics
+ AuthCounters counters_;
private:
std::string db_file_;
@@ -103,12 +115,17 @@
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
+
+ /// Increment query counter
+ void incCounter(const int protocol);
};
AuthSrvImpl::AuthSrvImpl(const bool use_cache,
AbstractXfroutClient& xfrout_client) :
config_session_(NULL), verbose_mode_(false),
xfrin_session_(NULL),
+ memory_datasrc_class_(RRClass::IN()),
+ counters_(verbose_mode_),
xfrout_connected_(false),
xfrout_client_(xfrout_client)
{
@@ -285,9 +302,47 @@
impl_->config_session_ = config_session;
}
+void
+AuthSrv::setStatisticsSession(AbstractSession* statistics_session) {
+ impl_->counters_.setStatisticsSession(statistics_session);
+}
+
ModuleCCSession*
AuthSrv::getConfigSession() const {
return (impl_->config_session_);
+}
+
+AuthSrv::ConstMemoryDataSrcPtr
+AuthSrv::getMemoryDataSrc(const RRClass& rrclass) const {
+ // XXX: for simplicity, we only support the IN class right now.
+ if (rrclass != impl_->memory_datasrc_class_) {
+ isc_throw(InvalidParameter,
+ "Memory data source is not supported for RR class "
+ << rrclass);
+ }
+ return (impl_->memory_datasrc_);
+}
+
+void
+AuthSrv::setMemoryDataSrc(const isc::dns::RRClass& rrclass,
+ MemoryDataSrcPtr memory_datasrc)
+{
+ // XXX: see above
+ if (rrclass != impl_->memory_datasrc_class_) {
+ isc_throw(InvalidParameter,
+ "Memory data source is not supported for RR class "
+ << rrclass);
+ }
+ if (impl_->verbose_mode_) {
+ if (!impl_->memory_datasrc_ && memory_datasrc) {
+ cerr << "[b10-auth] Memory data source is enabled for class "
+ << rrclass << endl;
+ } else if (impl_->memory_datasrc_ && !memory_datasrc) {
+ cerr << "[b10-auth] Memory data source is disabled for class "
+ << rrclass << endl;
+ }
+ }
+ impl_->memory_datasrc_ = memory_datasrc;
}
void
@@ -387,6 +442,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);
@@ -395,8 +453,17 @@
}
try {
- Query query(*message, cache_, dnssec_ok);
- data_sources_.doQuery(query);
+ // If a memory data source is configured call the separate
+ // Query::process()
+ const ConstQuestionPtr question = *message->beginQuestion();
+ if (memory_datasrc_ && memory_datasrc_class_ == question->getClass()) {
+ const RRType& qtype = question->getType();
+ const Name& qname = question->getName();
+ auth::Query(*memory_datasrc_, qname, qtype, *message).process();
+ } else {
+ datasrc::Query query(*message, cache_, dnssec_ok);
+ data_sources_.doQuery(query);
+ }
} catch (const Exception& ex) {
if (verbose_mode_) {
cerr << "[b10-auth] Internal error, returning SERVFAIL: " <<
@@ -405,7 +472,6 @@
makeErrorMessage(message, buffer, Rcode::SERVFAIL(), verbose_mode_);
return (true);
}
-
MessageRenderer renderer(*buffer);
const bool udp_buffer =
@@ -426,6 +492,9 @@
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer)
{
+ // 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;
@@ -551,6 +620,19 @@
return (true);
}
+void
+AuthSrvImpl::incCounter(const int protocol) {
+ // Increment query counter.
+ if (protocol == IPPROTO_UDP) {
+ counters_.inc(AuthCounters::COUNTER_UDP_QUERY);
+ } else if (protocol == IPPROTO_TCP) {
+ counters_.inc(AuthCounters::COUNTER_TCP_QUERY);
+ } else {
+ // unknown protocol
+ isc_throw(Unexpected, "Unknown protocol: " << protocol);
+ }
+}
+
ConstElementPtr
AuthSrvImpl::setDbFile(ConstElementPtr config) {
ConstElementPtr answer = isc::config::createAnswer();
@@ -609,6 +691,9 @@
try {
// the ModuleCCSession has already checked if we have
// the correct ElementPtr type as specified in our .spec file
+ if (new_config) {
+ configureAuthServer(*this, new_config);
+ }
return (impl_->setDbFile(new_config));
} catch (const isc::Exception& error) {
if (impl_->verbose_mode_) {
@@ -617,3 +702,12 @@
return (isc::config::createAnswer(1, error.what()));
}
}
+
+bool AuthSrv::submitStatistics() const {
+ return (impl_->counters_.submitStatistics());
+}
+
+uint64_t
+AuthSrv::getCounter(const AuthCounters::CounterType type) const {
+ return (impl_->counters_.getCounter(type));
+}
Modified: branches/trac447/src/bin/auth/auth_srv.h
==============================================================================
--- branches/trac447/src/bin/auth/auth_srv.h (original)
+++ branches/trac447/src/bin/auth/auth_srv.h Tue Dec 28 10:31:10 2010
@@ -19,16 +19,25 @@
#include <string>
+// For MemoryDataSrcPtr below. This should be a temporary definition until
+// we reorganize the data source framework.
+#include <boost/shared_ptr.hpp>
+
#include <cc/data.h>
#include <config/ccsession.h>
#include <asiolink/asiolink.h>
+#include <auth/statistics.h>
namespace isc {
+namespace datasrc {
+class MemoryDataSrc;
+}
namespace xfr {
class AbstractXfroutClient;
}
}
+
/// \brief The implementation class for the \c AuthSrv class using the pimpl
/// idiom.
@@ -54,6 +63,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.
@@ -88,6 +98,8 @@
/// \param message Pointer to the \c Message object
/// \param buffer Pointer to an \c OutputBuffer for the resposne
/// \param server Pointer to the \c DNSServer
+ ///
+ /// \throw isc::Unexpected Protocol type of \a message is unexpected
void processMessage(const asiolink::IOMessage& io_message,
isc::dns::MessagePtr message,
isc::dns::OutputBufferPtr buffer,
@@ -123,9 +135,11 @@
/// If there is a data source installed, it will be replaced with the
/// new one.
///
- /// In the current implementation, the SQLite data source is assumed.
- /// The \c config parameter will simply be passed to the initialization
- /// routine of the \c Sqlite3DataSrc class.
+ /// In the current implementation, the SQLite data source and MemoryDataSrc
+ /// are assumed.
+ /// We can enable memory data source and get the path of SQLite database by
+ /// the \c config parameter. If we disabled memory data source, the SQLite
+ /// data source will be used.
///
/// On success this method returns a data \c Element (in the form of a
/// pointer like object) indicating the successful result,
@@ -224,6 +238,96 @@
///
void setXfrinSession(isc::cc::AbstractSession* xfrin_session);
+ /// A shared pointer type for \c MemoryDataSrc.
+ ///
+ /// This is defined inside the \c AuthSrv class as it's supposed to be
+ /// a short term interface until we integrate the in-memory and other
+ /// data source frameworks.
+ typedef boost::shared_ptr<isc::datasrc::MemoryDataSrc> MemoryDataSrcPtr;
+
+ /// An immutable shared pointer type for \c MemoryDataSrc.
+ typedef boost::shared_ptr<const isc::datasrc::MemoryDataSrc>
+ ConstMemoryDataSrcPtr;
+
+ /// Returns the in-memory data source configured for the \c AuthSrv,
+ /// if any.
+ ///
+ /// The in-memory data source is configured per RR class. However,
+ /// the data source may not be available for all RR classes.
+ /// If it is not available for the specified RR class, an exception of
+ /// class \c InvalidParameter will be thrown.
+ /// This method never throws an exception otherwise.
+ ///
+ /// Even for supported RR classes, the in-memory data source is not
+ /// configured by default. In that case a NULL (shared) pointer will
+ /// be returned.
+ ///
+ /// \param rrclass The RR class of the requested in-memory data source.
+ /// \return A pointer to the in-memory data source, if configured;
+ /// otherwise NULL.
+ ConstMemoryDataSrcPtr
+ getMemoryDataSrc(const isc::dns::RRClass& rrclass) const;
+
+ /// Sets or replaces the in-memory data source of the specified RR class.
+ ///
+ /// As noted in \c getMemoryDataSrc(), some RR classes may not be
+ /// supported, in which case an exception of class \c InvalidParameter
+ /// will be thrown.
+ /// This method never throws an exception otherwise.
+ ///
+ /// If there is already an in memory data source configured, it will be
+ /// replaced with the newly specified one.
+ /// \c memory_datasrc can be NULL, in which case it will (re)disable the
+ /// in-memory data source.
+ ///
+ /// \param rrclass The RR class of the in-memory data source to be set.
+ /// \param memory_datasrc A (shared) pointer to \c MemoryDataSrc to be set.
+ void setMemoryDataSrc(const isc::dns::RRClass& rrclass,
+ MemoryDataSrcPtr memory_datasrc);
+
+ /// \brief Set the communication session with Statistics.
+ ///
+ /// This function never throws an exception as far as
+ /// 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 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.
+ /// Ownership isn't transferred: the caller is responsible for keeping
+ /// this object to be valid while the server object is working and for
+ /// disconnecting the session and destroying the object when the server
+ /// is shutdown.
+ void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
+
+ /// \brief Submit statistics counters to statistics module.
+ ///
+ /// This function can throw an exception from
+ /// AuthCounters::submitStatistics().
+ ///
+ /// \return true on success, false on failure (e.g. session timeout,
+ /// session error).
+ bool submitStatistics() const;
+
+ /// \brief Get the value of counter in the AuthCounters.
+ ///
+ /// This function calls AuthCounters::getCounter() and
+ /// returns its return value.
+ ///
+ /// This function never throws an exception as far as
+ /// AuthCounters::getCounter() doesn't throw.
+ ///
+ /// Note: Currently this function is for testing purpose only.
+ ///
+ /// \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;
+
private:
AuthSrvImpl* impl_;
asiolink::IOService* io_service_;
Modified: branches/trac447/src/bin/auth/benchmarks/Makefile.am
==============================================================================
--- branches/trac447/src/bin/auth/benchmarks/Makefile.am (original)
+++ branches/trac447/src/bin/auth/benchmarks/Makefile.am Tue Dec 28 10:31:10 2010
@@ -8,7 +8,10 @@
noinst_PROGRAMS = query_bench
query_bench_SOURCES = query_bench.cc
+query_bench_SOURCES += ../query.h ../query.cc
query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
+query_bench_SOURCES += ../config.h ../config.cc
+query_bench_SOURCES += ../statistics.h ../statistics.cc
query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
query_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
Modified: branches/trac447/src/bin/auth/benchmarks/query_bench.cc
==============================================================================
--- branches/trac447/src/bin/auth/benchmarks/query_bench.cc (original)
+++ branches/trac447/src/bin/auth/benchmarks/query_bench.cc Tue Dec 28 10:31:10 2010
@@ -33,11 +33,14 @@
#include <xfr/xfrout_client.h>
#include <auth/auth_srv.h>
+#include <auth/query.h>
+
#include <asiolink/asiolink.h>
using namespace std;
using namespace isc;
using namespace isc::data;
+using namespace isc::auth;
using namespace isc::dns;
using namespace isc::xfr;
using namespace isc::bench;
Modified: branches/trac447/src/bin/auth/change_user.cc
==============================================================================
--- branches/trac447/src/bin/auth/change_user.cc (original)
+++ branches/trac447/src/bin/auth/change_user.cc Tue Dec 28 10:31:10 2010
@@ -26,6 +26,7 @@
#include <auth/common.h>
using namespace boost;
+using namespace std;
void
changeUser(const char* const username) {
@@ -42,14 +43,14 @@
}
}
if (runas_pw == NULL) {
- isc_throw(FatalError, "Unknown user name or UID:" << username);
+ throw FatalError("Unknown user name or UID:" + string(username));
}
if (setgid(runas_pw->pw_gid) < 0) {
- isc_throw(FatalError, "setgid() failed: " << strerror(errno));
+ throw FatalError("setgid() failed: " + string(strerror(errno)));
}
if (setuid(runas_pw->pw_uid) < 0) {
- isc_throw(FatalError, "setuid() failed: " << strerror(errno));
+ throw FatalError("setuid() failed: " + string(strerror(errno)));
}
}
Modified: branches/trac447/src/bin/auth/common.h
==============================================================================
--- branches/trac447/src/bin/auth/common.h (original)
+++ branches/trac447/src/bin/auth/common.h Tue Dec 28 10:31:10 2010
@@ -17,12 +17,18 @@
#ifndef __COMMON_H
#define __COMMON_H 1
-#include <exceptions/exceptions.h>
+#include <stdexcept>
+#include <string>
-class FatalError : public isc::Exception {
+/// An exception class that is thrown in an unrecoverable error condition.
+///
+/// This exception should not be caught except at the highest level of
+/// the application only for terminating the program gracefully, and so
+/// it cannot be a derived class of \c isc::Exception.
+class FatalError : public std::runtime_error {
public:
- FatalError(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ FatalError(const std::string& what) : std::runtime_error(what)
+ {}
};
#endif // __COMMON_H
Modified: branches/trac447/src/bin/auth/main.cc
==============================================================================
--- branches/trac447/src/bin/auth/main.cc (original)
+++ branches/trac447/src/bin/auth/main.cc Tue Dec 28 10:31:10 2010
@@ -25,7 +25,7 @@
#include <cassert>
#include <iostream>
-#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include <exceptions/exceptions.h>
@@ -41,6 +41,7 @@
#include <auth/spec_config.h>
#include <auth/common.h>
+#include <auth/config.h>
#include <auth/change_user.h>
#include <auth/auth_srv.h>
#include <asiolink/asiolink.h>
@@ -61,6 +62,10 @@
static const string PROGRAM = "Auth";
static const char* DNSPORT = "5300";
+// Note: this value must be greater than 0.
+// TODO: make it configurable via command channel.
+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
* class itself? */
@@ -83,8 +88,14 @@
answer = createAnswer(0, args);
} else if (command == "shutdown") {
io_service.stop();
- }
-
+ } else if (command == "sendstats") {
+ if (verbose_mode) {
+ cerr << "[b10-auth] command 'sendstats' received" << endl;
+ }
+ assert(auth_server != NULL);
+ auth_server->submitStatistics();
+ }
+
return (answer);
}
@@ -102,6 +113,12 @@
cerr << "\t-v: verbose output" << endl;
exit(1);
}
+
+void
+statisticsTimerCallback(AuthSrv* auth_server) {
+ assert(auth_server != NULL);
+ auth_server->submitStatistics();
+}
} // end of anonymous namespace
int
@@ -167,7 +184,10 @@
// XXX: we should eventually pass io_service here.
Session* cc_session = NULL;
Session* xfrin_session = NULL;
+ Session* statistics_session = NULL;
+ IntervalTimer* itimer = NULL;
bool xfrin_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) {
@@ -229,14 +249,35 @@
xfrin_session_established = true;
cout << "[b10-auth] Xfrin 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 asiolink we have to create
// auth_server before io_service while Session needs io_service.
// In a next step of refactoring we should make asiolink independent
// from auth_server, and create io_service, auth_server, and
// sessions in that order.
auth_server->setXfrinSession(xfrin_session);
+ auth_server->setStatisticsSession(statistics_session);
+
+ // Configure the server. configureAuthServer() is expected to install
+ // all initial configurations, but as a short term workaround we
+ // handle the traditional "database_file" setup by directly calling
+ // updateConfig().
auth_server->setConfigSession(config_session);
+ configureAuthServer(*auth_server, config_session->getFullConfig());
auth_server->updateConfig(ElementPtr());
+
+ // create interval timer instance
+ itimer = new IntervalTimer(io_service);
+ // set up interval timer
+ // register function to send statistics with interval
+ itimer->setupTimer(boost::bind(statisticsTimerCallback, auth_server),
+ STATISTICS_SEND_INTERVAL_SEC);
+ cout << "[b10-auth] Interval timer to send statistics set." << endl;
cout << "[b10-auth] Server started." << endl;
io_service.run();
@@ -247,10 +288,16 @@
ret = 1;
}
+ if (statistics_session_established) {
+ statistics_session->disconnect();
+ }
+
if (xfrin_session_established) {
xfrin_session->disconnect();
}
+ delete itimer;
+ delete statistics_session;
delete xfrin_session;
delete config_session;
delete cc_session;
Modified: branches/trac447/src/bin/auth/query.cc
==============================================================================
--- branches/trac447/src/bin/auth/query.cc (original)
+++ branches/trac447/src/bin/auth/query.cc Tue Dec 28 10:31:10 2010
@@ -15,7 +15,7 @@
#include <dns/message.h>
#include <dns/rcode.h>
-#include <datasrc/zonetable.h>
+#include <datasrc/memory_datasrc.h>
#include <auth/query.h>
@@ -24,19 +24,54 @@
namespace isc {
namespace auth {
+
void
Query::process() const {
- const ZoneTable::FindResult result = zone_table_.findZone(qname_);
+ bool keep_doing = true;
+ response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
+ const MemoryDataSrc::FindResult result =
+ memory_datasrc_.findZone(qname_);
- if (result.code != isc::datasrc::result::SUCCESS &&
- result.code != isc::datasrc::result::PARTIALMATCH) {
- response_.setRcode(Rcode::SERVFAIL());
+ // If we have no matching authoritative zone for the query name, return
+ // REFUSED. In short, this is to be compatible with BIND 9, but the
+ // background discussion is not that simple. See the relevant topic
+ // at the BIND 10 developers's ML:
+ // https://lists.isc.org/mailman/htdig/bind10-dev/2010-December/001633.html
+ if (result.code != result::SUCCESS &&
+ result.code != result::PARTIALMATCH) {
+ response_.setRcode(Rcode::REFUSED());
return;
}
- // Right now we have no code to search the zone, so we simply return
- // NXDOMAIN for tests.
- response_.setRcode(Rcode::NXDOMAIN());
+ // Found a zone which is the nearest ancestor to QNAME, set the AA bit
+ response_.setHeaderFlag(Message::HEADERFLAG_AA);
+ while (keep_doing) {
+ keep_doing = false;
+ Zone::FindResult db_result = result.zone->find(qname_, qtype_);
+ switch (db_result.code) {
+ case Zone::SUCCESS:
+ response_.setRcode(Rcode::NOERROR());
+ response_.addRRset(Message::SECTION_ANSWER,
+ boost::const_pointer_cast<RRset>(db_result.rrset));
+ // TODO : fill in authority and addtional sections.
+ break;
+ case Zone::DELEGATION:
+ // TODO : add NS to authority section, fill in additional section.
+ break;
+ case Zone::NXDOMAIN:
+ response_.setRcode(Rcode::NXDOMAIN());
+ // TODO : add SOA to authority section
+ break;
+ case Zone::NXRRSET:
+ response_.setRcode(Rcode::NOERROR());
+ // TODO : add SOA to authority section
+ break;
+ case Zone::CNAME:
+ case Zone::DNAME:
+ // TODO : replace qname, continue lookup
+ break;
+ }
+ }
}
}
}
Modified: branches/trac447/src/bin/auth/query.h
==============================================================================
--- branches/trac447/src/bin/auth/query.h (original)
+++ branches/trac447/src/bin/auth/query.h Tue Dec 28 10:31:10 2010
@@ -22,7 +22,7 @@
}
namespace datasrc {
-class ZoneTable;
+class MemoryDataSrc;
}
namespace auth {
@@ -32,11 +32,11 @@
///
/// Many of the design details for this class are still in flux.
/// We'll revisit and update them as we add more functionality, for example:
-/// - zone_table parameter of the constructor. This will eventually be
-/// replaced with a generic DataSrc object, or perhaps a notion of "view".
+/// - memory_datasrc parameter of the constructor. It is a data source that
+/// uses in memory dedicated backend.
/// - as a related point, we may have to pass the RR class of the query.
-/// in the initial implementation the RR class is an attribute of zone
-/// table and omitted. It's not clear if this assumption holds with
+/// in the initial implementation the RR class is an attribute of memory
+/// datasource and omitted. It's not clear if this assumption holds with
/// generic data sources. On the other hand, it will help keep
/// implementation simpler, and we might rather want to modify the design
/// of the data source on this point.
@@ -47,8 +47,8 @@
/// separate attribute setter.
/// - likewise, we'll eventually need to do per zone access control, for which
/// we need querier's information such as its IP address.
-/// - zone_table (or DataSrc eventually) and response may better be parameters
-/// to process() instead of the constructor.
+/// - memory_datasrc and response may better be parameters to process() instead
+/// of the constructor.
///
/// <b>Note:</b> The class name is intentionally the same as the one used in
/// the datasrc library. This is because the plan is to eventually merge
@@ -65,15 +65,15 @@
///
/// This constructor never throws an exception.
///
- /// \param zone_table The zone table wherein the answer to the query is
+ /// \param memory_datasrc The memory datasource wherein the answer to the query is
/// to be found.
/// \param qname The query name
/// \param qtype The RR type of the query
/// \param response The response message to store the answer to the query.
- Query(const isc::datasrc::ZoneTable& zone_table,
+ Query(const isc::datasrc::MemoryDataSrc& memory_datasrc,
const isc::dns::Name& qname, const isc::dns::RRType& qtype,
isc::dns::Message& response) :
- zone_table_(zone_table), qname_(qname), qtype_(qtype),
+ memory_datasrc_(memory_datasrc), qname_(qname), qtype_(qtype),
response_(response)
{}
@@ -87,7 +87,7 @@
/// successful search would result in adding a corresponding RRset to
/// the answer section of the response.
///
- /// If no matching zone is found in the zone table, the RCODE of
+ /// If no matching zone is found in the memory datasource, the RCODE of
/// SERVFAIL will be set in the response.
/// <b>Note:</b> this is different from the error code that BIND 9 returns
/// by default when it's configured as an authoritative-only server (and
@@ -105,7 +105,7 @@
void process() const;
private:
- const isc::datasrc::ZoneTable& zone_table_;
+ const isc::datasrc::MemoryDataSrc& memory_datasrc_;
const isc::dns::Name& qname_;
const isc::dns::RRType& qtype_;
isc::dns::Message& response_;
Modified: branches/trac447/src/bin/auth/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/auth/tests/Makefile.am (original)
+++ branches/trac447/src/bin/auth/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -21,9 +21,13 @@
run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
run_unittests_SOURCES += ../query.h ../query.cc
run_unittests_SOURCES += ../change_user.h ../change_user.cc
+run_unittests_SOURCES += ../config.h ../config.cc
+run_unittests_SOURCES += ../statistics.h ../statistics.cc
run_unittests_SOURCES += auth_srv_unittest.cc
+run_unittests_SOURCES += config_unittest.cc
run_unittests_SOURCES += query_unittest.cc
run_unittests_SOURCES += change_user_unittest.cc
+run_unittests_SOURCES += statistics_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
Modified: branches/trac447/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- branches/trac447/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ branches/trac447/src/bin/auth/tests/auth_srv_unittest.cc Tue Dec 28 10:31:10 2010
@@ -15,10 +15,11 @@
// $Id$
#include <config.h>
+#include <datasrc/memory_datasrc.h>
#include <auth/auth_srv.h>
#include <testutils/srv_unittest.h>
-
-using namespace std;
+#include <auth/statistics.h>
+
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::data;
@@ -36,11 +37,14 @@
class AuthSrvTest : public SrvTestBase {
protected:
- AuthSrvTest() : server(true, xfrout) {
+ AuthSrvTest() : server(true, xfrout), rrclass(RRClass::IN()) {
server.setXfrinSession(¬ify_session);
+ server.setStatisticsSession(&statistics_session);
}
+ MockSession statistics_session;
MockXfroutClient xfrout;
AuthSrv server;
+ const RRClass rrclass;
};
// Unsupported requests. Should result in NOTIMP.
@@ -325,11 +329,11 @@
}
void
-updateConfig(AuthSrv* server, const char* const dbfile,
+updateConfig(AuthSrv* server, const char* const config_data,
const bool expect_success)
{
ConstElementPtr config_answer =
- server->updateConfig(Element::fromJSON(dbfile));
+ server->updateConfig(Element::fromJSON(config_data));
EXPECT_EQ(Element::map, config_answer->getType());
EXPECT_TRUE(config_answer->contains("result"));
@@ -381,6 +385,44 @@
QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
+TEST_F(AuthSrvTest, updateWithMemoryDataSrc) {
+ // Test configuring memory data source. Detailed test cases are covered
+ // in the configuration tests. We only check the AuthSrv interface here.
+
+ // By default memory data source isn't enabled
+ EXPECT_EQ(AuthSrv::MemoryDataSrcPtr(), server.getMemoryDataSrc(rrclass));
+ updateConfig(&server,
+ "{\"datasources\": [{\"type\": \"memory\"}]}", true);
+ // after successful configuration, we should have one (with empty zoneset).
+ ASSERT_NE(AuthSrv::MemoryDataSrcPtr(), server.getMemoryDataSrc(rrclass));
+ EXPECT_EQ(0, server.getMemoryDataSrc(rrclass)->getZoneCount());
+
+ // The memory data source is empty, should return REFUSED rcode.
+ createDataFromFile("examplequery_fromWire.wire");
+ server.processMessage(*io_message, parse_message, response_obuffer,
+ &dnsserv);
+ EXPECT_TRUE(dnsserv.hasAnswer());
+ headerCheck(*parse_message, default_qid, Rcode::REFUSED(),
+ opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+}
+
+TEST_F(AuthSrvTest, chQueryWithMemoryDataSrc) {
+ // Configure memory data source for class IN
+ updateConfig(&server, "{\"datasources\": "
+ "[{\"class\": \"IN\", \"type\": \"memory\"}]}", true);
+
+ // This shouldn't affect the result of class CH query
+ UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
+ default_qid, Name("version.bind"),
+ RRClass::CH(), RRType::TXT());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ server.processMessage(*io_message, parse_message, response_obuffer,
+ &dnsserv);
+ EXPECT_TRUE(dnsserv.hasAnswer());
+ headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
+ opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
+}
+
TEST_F(AuthSrvTest, cacheSlots) {
// simple check for the get/set operations
server.setCacheSlots(10); // 10 = arbitrary choice
@@ -390,4 +432,90 @@
server.setCacheSlots(0);
EXPECT_EQ(00, server.getCacheSlots());
}
-}
+
+// 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));
+ // Create UDP message and process.
+ UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::NS());
+ createRequestPacket(request_message, IPPROTO_UDP);
+ 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));
+}
+
+// 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));
+ // Create TCP message and process.
+ UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::NS());
+ createRequestPacket(request_message, IPPROTO_TCP);
+ 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));
+}
+
+// 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));
+ UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
+ Name("example.com"), RRClass::IN(), RRType::AXFR());
+ createRequestPacket(request_message, IPPROTO_TCP);
+ // On success, the AXFR query has been passed to a separate process,
+ // so we shouldn't have to respond.
+ server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv);
+ // After processing TCP AXFR query, the counter should be 1.
+ EXPECT_EQ(1, server.getCounter(AuthCounters::COUNTER_TCP_QUERY));
+}
+
+// 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 isc::Unexpected
+TEST_F(AuthSrvTest, queryCounterUnexpected) {
+ // 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 UDP query packet.
+ UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::NS());
+ createRequestPacket(request_message, 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_obuffer, &dnsserv),
+ isc::Unexpected);
+}
+}
Modified: branches/trac447/src/bin/auth/tests/query_unittest.cc
==============================================================================
--- branches/trac447/src/bin/auth/tests/query_unittest.cc (original)
+++ branches/trac447/src/bin/auth/tests/query_unittest.cc Tue Dec 28 10:31:10 2010
@@ -15,9 +15,9 @@
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rcode.h>
+#include <dns/rrttl.h>
#include <dns/rrtype.h>
-#include <datasrc/zonetable.h>
#include <datasrc/memory_datasrc.h>
#include <auth/query.h>
@@ -28,17 +28,69 @@
using namespace isc::datasrc;
using namespace isc::auth;
+RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
+ RRClass::IN(), RRType::A(),
+ RRTTL(3600)));
namespace {
+// This is a mock Zone class for testing.
+// It is a derived class of Zone, and simply hardcode the results of find()
+// return SUCCESS for "www.example.com",
+// return NXDOMAIN for "nxdomain.example.com",
+// return NXRRSET for "nxrrset.example.com",
+// return CNAME for "cname.example.com",
+// else return DNAME
+class MockZone : public Zone {
+public:
+ MockZone() : origin_(Name("example.com"))
+ {}
+ virtual const isc::dns::Name& getOrigin() const;
+ virtual const isc::dns::RRClass& getClass() const;
+
+ FindResult find(const isc::dns::Name& name,
+ const isc::dns::RRType& type) const;
+
+private:
+ Name origin_;
+};
+
+const Name&
+MockZone::getOrigin() const {
+ return (origin_);
+}
+
+const RRClass&
+MockZone::getClass() const {
+ return (RRClass::IN());
+}
+
+Zone::FindResult
+MockZone::find(const Name& name, const RRType&) const {
+ // hardcode the find results
+ if (name == Name("www.example.com")) {
+ return FindResult(SUCCESS, a_rrset);
+ } else if (name == Name("delegation.example.com")) {
+ return FindResult(DELEGATION, RRsetPtr());
+ } else if (name == Name("nxdomain.example.com")) {
+ return FindResult(NXDOMAIN, RRsetPtr());
+ } else if (name == Name("nxrrset.example.com")) {
+ return FindResult(NXRRSET, RRsetPtr());
+ } else if (name == Name("cname.example.com")) {
+ return FindResult(CNAME, RRsetPtr());
+ } else {
+ return FindResult(DNAME, RRsetPtr());
+ }
+}
+
class QueryTest : public ::testing::Test {
protected:
QueryTest() :
qname(Name("www.example.com")), qclass(RRClass::IN()),
qtype(RRType::A()), response(Message::RENDER),
- query(zone_table, qname, qtype, response)
+ query(memory_datasrc, qname, qtype, response)
{
response.setRcode(Rcode::NOERROR());
}
- ZoneTable zone_table;
+ MemoryDataSrc memory_datasrc;
const Name qname;
const RRClass qclass;
const RRType qtype;
@@ -47,25 +99,41 @@
};
TEST_F(QueryTest, noZone) {
- // There's no zone in the zone table. So the response should have
- // SERVFAIL.
+ // There's no zone in the memory datasource. So the response should have
+ // REFUSED.
query.process();
- EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
+ EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
}
TEST_F(QueryTest, matchZone) {
- // add a matching zone. since the zone is empty right now, the response
- // should have NXDOMAIN.
- zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.com"))));
+ // match qname, normal query
+ memory_datasrc.addZone(ZonePtr(new MockZone()));
query.process();
+ EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+ EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+ Name("www.example.com"), RRClass::IN(),
+ RRType::A()));
+
+ // NXDOMAIN
+ const Name nxdomain_name(Name("nxdomain.example.com"));
+ Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
+ nxdomain_query.process();
EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
+
+ // NXRRSET
+ const Name nxrrset_name(Name("nxrrset.example.com"));
+ Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
+ nxrrset_query.process();
+ EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
}
TEST_F(QueryTest, noMatchZone) {
- // there's a zone in the table but it doesn't match the qname. should
- // result in SERVFAIL.
- zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.org"))));
- query.process();
- EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
+ // there's a zone in the memory datasource but it doesn't match the qname.
+ // should result in REFUSED.
+ memory_datasrc.addZone(ZonePtr(new MockZone()));
+ const Name nomatch_name(Name("example.org"));
+ Query nomatch_query(memory_datasrc, nomatch_name, qtype, response);
+ nomatch_query.process();
+ EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
}
}
Modified: branches/trac447/src/bin/bind10/run_bind10.sh.in
==============================================================================
--- branches/trac447/src/bin/bind10/run_bind10.sh.in (original)
+++ branches/trac447/src/bin/bind10/run_bind10.sh.in Tue Dec 28 10:31:10 2010
@@ -46,5 +46,5 @@
export BIND10_MSGQ_SOCKET_FILE
cd ${BIND10_PATH}
-exec ${PYTHON_EXEC} -O bind10 $*
+exec ${PYTHON_EXEC} -O bind10 "$@"
Modified: branches/trac447/src/bin/bind10/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/bind10/tests/Makefile.am (original)
+++ branches/trac447/src/bin/bind10/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,17 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+#PYTESTS = args_test.py bind10_test.py
PYTESTS = bind10_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bind10 \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/bindctl/run_bindctl.sh.in
==============================================================================
--- branches/trac447/src/bin/bindctl/run_bindctl.sh.in (original)
+++ branches/trac447/src/bin/bindctl/run_bindctl.sh.in Tue Dec 28 10:31:10 2010
@@ -26,5 +26,8 @@
B10_FROM_SOURCE=@abs_top_srcdir@
export B10_FROM_SOURCE
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${BINDCTL_PATH}
-exec ${PYTHON_EXEC} -O bindctl $*
+exec ${PYTHON_EXEC} -O bindctl "$@"
Modified: branches/trac447/src/bin/bindctl/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/bindctl/tests/Makefile.am (original)
+++ branches/trac447/src/bin/bindctl/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,16 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = bindctl_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_srcdir)/src/bin \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/cfgmgr/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/cfgmgr/tests/Makefile.am (original)
+++ branches/trac447/src/bin/cfgmgr/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,13 +1,17 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = b10-cfgmgr_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr \
- $(PYCOVERAGE) $(abs_builddir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/cmdctl/run_b10-cmdctl.sh.in
==============================================================================
--- branches/trac447/src/bin/cmdctl/run_b10-cmdctl.sh.in (original)
+++ branches/trac447/src/bin/cmdctl/run_b10-cmdctl.sh.in Tue Dec 28 10:31:10 2010
@@ -22,6 +22,8 @@
PYTHONPATH=@abs_top_srcdir@/src/lib/python
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${CMD_CTRLD_PATH}
-${PYTHON_EXEC} b10-cmdctl
-
+exec ${PYTHON_EXEC} b10-cmdctl "$@"
Modified: branches/trac447/src/bin/cmdctl/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/cmdctl/tests/Makefile.am (original)
+++ branches/trac447/src/bin/cmdctl/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,14 +1,18 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = cmdctl_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cmdctl \
CMDCTL_SPEC_PATH=$(abs_top_builddir)/src/bin/cmdctl \
CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/loadzone/run_loadzone.sh.in
==============================================================================
--- branches/trac447/src/bin/loadzone/run_loadzone.sh.in (original)
+++ branches/trac447/src/bin/loadzone/run_loadzone.sh.in Tue Dec 28 10:31:10 2010
@@ -21,5 +21,8 @@
PYTHONPATH=@abs_top_builddir@/src/lib/python
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
LOADZONE_PATH=@abs_top_builddir@/src/bin/loadzone
-exec ${LOADZONE_PATH}/b10-loadzone $*
+exec ${LOADZONE_PATH}/b10-loadzone "$@"
Modified: branches/trac447/src/bin/loadzone/tests/correct/Makefile.am
==============================================================================
--- branches/trac447/src/bin/loadzone/tests/correct/Makefile.am (original)
+++ branches/trac447/src/bin/loadzone/tests/correct/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,4 +1,3 @@
-PYTESTS = correct_test.sh
EXTRA_DIST = get_zonedatas.py
EXTRA_DIST += include.db
EXTRA_DIST += inclsub.db
@@ -14,12 +13,8 @@
EXTRA_DIST += ttlext.db
EXTRA_DIST += example.db
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
+# TODO: maybe use TESTS?
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
- for pytest in $(PYTESTS) ; do \
- echo Running test: $$pytest ; \
- env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/loadzone \
- $(SHELL) $(abs_builddir)/$$pytest || exit ; \
- done
+ echo Running test: correct_test.sh
+ $(SHELL) $(abs_builddir)/correct_test.sh
Modified: branches/trac447/src/bin/loadzone/tests/error/Makefile.am
==============================================================================
--- branches/trac447/src/bin/loadzone/tests/error/Makefile.am (original)
+++ branches/trac447/src/bin/loadzone/tests/error/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,5 +1,3 @@
-PYTESTS = error_test.sh
-
EXTRA_DIST = error.known
EXTRA_DIST += formerr1.db
EXTRA_DIST += formerr2.db
@@ -14,12 +12,8 @@
EXTRA_DIST += originerr1.db
EXTRA_DIST += originerr2.db
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
+# TODO: use TESTS ?
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
- for pytest in $(PYTESTS) ; do \
- echo Running test: $$pytest ; \
- env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/bin/loadzone \
- $(SHELL) $(abs_builddir)/$$pytest || exit ; \
- done
+ echo Running test: error_test.sh
+ $(SHELL) $(abs_builddir)/error_test.sh
Modified: branches/trac447/src/bin/msgq/run_msgq.sh.in
==============================================================================
--- branches/trac447/src/bin/msgq/run_msgq.sh.in (original)
+++ branches/trac447/src/bin/msgq/run_msgq.sh.in Tue Dec 28 10:31:10 2010
@@ -23,5 +23,8 @@
PYTHONPATH=@abs_top_srcdir@/src/lib/python
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${MYPATH_PATH}
-exec ${PYTHON_EXEC} -O b10-msgq $*
+exec ${PYTHON_EXEC} -O b10-msgq "$@"
Modified: branches/trac447/src/bin/msgq/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/msgq/tests/Makefile.am (original)
+++ branches/trac447/src/bin/msgq/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,14 +1,18 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = msgq_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_builddir)/src/bin/msgq:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
BIND10_TEST_SOCKET_FILE=$(builddir)/test_msgq_socket.sock \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/recurse/b10-recurse.8
==============================================================================
--- branches/trac447/src/bin/recurse/b10-recurse.8 (original)
+++ branches/trac447/src/bin/recurse/b10-recurse.8 Tue Dec 28 10:31:10 2010
@@ -2,12 +2,12 @@
.\" Title: b10-recurse
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: September 16, 2010
+.\" Date: December 27, 2010
.\" Manual: BIND10
.\" Source: BIND10
.\" Language: English
.\"
-.TH "B10\-RECURSE" "8" "September 16, 2010" "BIND10" "BIND10"
+.TH "B10\-RECURSE" "8" "December 27, 2010" "BIND10" "BIND10"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@@ -22,7 +22,7 @@
b10-recurse \- Recursive DNS server
.SH "SYNOPSIS"
.HP \w'\fBb10\-recurse\fR\ 'u
-\fBb10\-recurse\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
+\fBb10\-recurse\fR [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
.SH "DESCRIPTION"
.PP
The
@@ -60,55 +60,6 @@
.PP
The arguments are as follows:
.PP
-\fB\-4\fR
-.RS 4
-Enables IPv4 only mode\&. This switch may not be used with
-\fB\-6\fR
-nor
-\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
-.RE
-.PP
-\fB\-6\fR
-.RS 4
-Enables IPv6 only mode\&. This switch may not be used with
-\fB\-4\fR
-nor
-\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
-.RE
-.PP
-\fB\-a \fR\fB\fIaddress\fR\fR
-.RS 4
-The IPv4 or IPv6 address to listen on\&. This switch may not be used with
-\fB\-4\fR
-nor
-\fB\-6\fR\&. The default is to listen on all addresses\&. (This is a short term workaround\&. This argument may change\&.)
-.RE
-.PP
-\fB\-n\fR
-.RS 4
-Do not cache answers in memory\&. The default is to use the cache for faster responses\&. The cache keeps the most recent 30,000 answers (positive and negative) in memory for 30 seconds (instead of querying the data source, such as SQLite3 database, each time)\&.
-.RE
-.PP
-\fB\-p \fR\fB\fInumber\fR\fR
-.RS 4
-The port number it listens on\&. The default is 5300\&.
-.if n \{\
-.sp
-.\}
-.RS 4
-.it 1 an-trap
-.nr an-no-space-flag 1
-.nr an-break-flag 1
-.br
-.ps +1
-\fBNote\fR
-.ps -1
-.br
-The Y1 prototype runs on all interfaces and on this nonstandard port\&.
-.sp .5v
-.RE
-.RE
-.PP
\fB\-u \fR\fB\fIusername\fR\fR
.RS 4
The user name of the
@@ -130,7 +81,6 @@
\fBb10-cfgmgr\fR(8),
\fBb10-cmdctl\fR(8),
-\fBb10-loadzone\fR(8),
\fBb10-msgq\fR(8),
\fBbind10\fR(8),
BIND 10 Guide\&.
Modified: branches/trac447/src/bin/recurse/b10-recurse.xml
==============================================================================
--- branches/trac447/src/bin/recurse/b10-recurse.xml (original)
+++ branches/trac447/src/bin/recurse/b10-recurse.xml Tue Dec 28 10:31:10 2010
@@ -21,7 +21,7 @@
<refentry>
<refentryinfo>
- <date>September 16, 2010</date>
+ <date>December 27, 2010</date>
</refentryinfo>
<refmeta>
@@ -45,11 +45,6 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>b10-recurse</command>
- <arg><option>-4</option></arg>
- <arg><option>-6</option></arg>
- <arg><option>-a <replaceable>address</replaceable></option></arg>
- <arg><option>-n</option></arg>
- <arg><option>-p <replaceable>number</replaceable></option></arg>
<arg><option>-u <replaceable>username</replaceable></option></arg>
<arg><option>-v</option></arg>
</cmdsynopsis>
@@ -89,59 +84,6 @@
<para>The arguments are as follows:</para>
<variablelist>
- <varlistentry>
- <term><option>-4</option></term>
- <listitem><para>
- Enables IPv4 only mode.
- This switch may not be used with <option>-6</option> nor
- <option>-a</option>.
- By default, it listens on both IPv4 and IPv6 (if capable).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-6</option></term>
- <listitem><para>
- Enables IPv6 only mode.
- This switch may not be used with <option>-4</option> nor
- <option>-a</option>.
- By default, it listens on both IPv4 and IPv6 (if capable).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-a <replaceable>address</replaceable></option></term>
-
- <listitem>
- <para>The IPv4 or IPv6 address to listen on.
- This switch may not be used with <option>-4</option> nor
- <option>-6</option>.
- The default is to listen on all addresses.
- (This is a short term workaround. This argument may change.)
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-n</option></term>
- <listitem><para>
- Do not cache answers in memory.
- The default is to use the cache for faster responses.
- The cache keeps the most recent 30,000 answers (positive
- and negative) in memory for 30 seconds (instead of querying
- the data source, such as SQLite3 database, each time).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-p <replaceable>number</replaceable></option></term>
- <listitem><para>
- The port number it listens on.
- The default is 5300.</para>
- <note><simpara>The Y1 prototype runs on all interfaces
- and on this nonstandard port.</simpara></note>
- </listitem>
- </varlistentry>
<varlistentry>
<term><option>-u <replaceable>username</replaceable></option></term>
@@ -187,9 +129,6 @@
<refentrytitle>b10-cmdctl</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
- <refentrytitle>b10-loadzone</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
<refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>,
<citerefentry>
Modified: branches/trac447/src/bin/stats/run_b10-stats.sh.in
==============================================================================
--- branches/trac447/src/bin/stats/run_b10-stats.sh.in (original)
+++ branches/trac447/src/bin/stats/run_b10-stats.sh.in Tue Dec 28 10:31:10 2010
@@ -21,10 +21,13 @@
PYTHONPATH=@abs_top_builddir@/src/lib/python
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
B10_FROM_BUILD=@abs_top_builddir@
export B10_FROM_BUILD
STATS_PATH=@abs_top_builddir@/src/bin/stats
cd ${STATS_PATH}
-exec ${PYTHON_EXEC} -O b10-stats $*
+exec ${PYTHON_EXEC} -O b10-stats "$@"
Modified: branches/trac447/src/bin/stats/run_b10-stats_stub.sh.in
==============================================================================
--- branches/trac447/src/bin/stats/run_b10-stats_stub.sh.in (original)
+++ branches/trac447/src/bin/stats/run_b10-stats_stub.sh.in Tue Dec 28 10:31:10 2010
@@ -24,7 +24,10 @@
B10_FROM_BUILD=@abs_top_srcdir@
export B10_FROM_BUILD
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
STATS_PATH=@abs_top_builddir@/src/bin/stats
cd ${STATS_PATH}
-exec ${PYTHON_EXEC} -O b10-stats_stub $*
+exec ${PYTHON_EXEC} -O b10-stats_stub "$@"
Modified: branches/trac447/src/bin/stats/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/stats/tests/Makefile.am (original)
+++ branches/trac447/src/bin/stats/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,15 +1,19 @@
SUBDIRS = isc testdata
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = b10-stats_test.py b10-stats_stub_test.py
EXTRA_DIST = $(PYTESTS) fake_time.py
CLEANFILES = fake_time.pyc
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/stats:$(abs_top_builddir)/src/bin/stats/tests \
B10_FROM_BUILD=$(abs_top_builddir) \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/tests/Makefile.am (original)
+++ branches/trac447/src/bin/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,13 +1,17 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = process_rename_test.py
# .py will be generated by configure, so we don't have to include it
# in EXTRA_DIST.
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
- $(PYCOVERAGE) $(abs_builddir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in
==============================================================================
--- branches/trac447/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in (original)
+++ branches/trac447/src/bin/usermgr/run_b10-cmdctl-usermgr.sh.in Tue Dec 28 10:31:10 2010
@@ -20,6 +20,8 @@
MYPATH_PATH=@abs_top_builddir@/src/bin/usermgr
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${MYPATH_PATH}
-${PYTHON_EXEC} b10-cmdctl-usermgr
-
+exec ${PYTHON_EXEC} b10-cmdctl-usermgr "$@"
Modified: branches/trac447/src/bin/xfrin/run_b10-xfrin.sh.in
==============================================================================
--- branches/trac447/src/bin/xfrin/run_b10-xfrin.sh.in (original)
+++ branches/trac447/src/bin/xfrin/run_b10-xfrin.sh.in Tue Dec 28 10:31:10 2010
@@ -22,6 +22,8 @@
PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/dns/.libs
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${MYPATH_PATH}
-${PYTHON_EXEC} b10-xfrin
-
+exec ${PYTHON_EXEC} b10-xfrin "$@"
Modified: branches/trac447/src/bin/xfrin/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/xfrin/tests/Makefile.am (original)
+++ branches/trac447/src/bin/xfrin/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,3 +1,4 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = xfrin_test.py
EXTRA_DIST = $(PYTESTS)
@@ -8,13 +9,16 @@
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
endif
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/bin/xfrin:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
$(LIBRARY_PATH_PLACEHOLDER) \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/xfrout/run_b10-xfrout.sh.in
==============================================================================
--- branches/trac447/src/bin/xfrout/run_b10-xfrout.sh.in (original)
+++ branches/trac447/src/bin/xfrout/run_b10-xfrout.sh.in Tue Dec 28 10:31:10 2010
@@ -22,6 +22,8 @@
PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/dns/python/.libs
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${MYPATH_PATH}
-${PYTHON_EXEC} b10-xfrout
-
+exec ${PYTHON_EXEC} b10-xfrout "$@"
Modified: branches/trac447/src/bin/xfrout/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/xfrout/tests/Makefile.am (original)
+++ branches/trac447/src/bin/xfrout/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,3 +1,4 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = xfrout_test.py
EXTRA_DIST = $(PYTESTS)
@@ -8,13 +9,16 @@
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
endif
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
$(LIBRARY_PATH_PLACEHOLDER) \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/bin/zonemgr/run_b10-zonemgr.sh.in
==============================================================================
--- branches/trac447/src/bin/zonemgr/run_b10-zonemgr.sh.in (original)
+++ branches/trac447/src/bin/zonemgr/run_b10-zonemgr.sh.in Tue Dec 28 10:31:10 2010
@@ -22,6 +22,8 @@
PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/dns/.libs
export PYTHONPATH
+BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
+export BIND10_MSGQ_SOCKET_FILE
+
cd ${MYPATH_PATH}
-${PYTHON_EXEC} b10-zonemgr
-
+exec ${PYTHON_EXEC} b10-zonemgr "$@"
Modified: branches/trac447/src/bin/zonemgr/tests/Makefile.am
==============================================================================
--- branches/trac447/src/bin/zonemgr/tests/Makefile.am (original)
+++ branches/trac447/src/bin/zonemgr/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,14 +1,17 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = zonemgr_test.py
EXTRA_DIST = $(PYTESTS)
-
CLEANFILES = initdb.file
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_builddir)/src/bin/zonemgr:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/asiolink/asiolink.cc
==============================================================================
--- branches/trac447/src/lib/asiolink/asiolink.cc (original)
+++ branches/trac447/src/lib/asiolink/asiolink.cc Tue Dec 28 10:31:10 2010
@@ -26,6 +26,7 @@
#include <asio.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/shared_ptr.hpp>
@@ -374,4 +375,90 @@
timeout_, retries_);
}
-}
+class IntervalTimerImpl {
+private:
+ // prohibit copy
+ IntervalTimerImpl(const IntervalTimerImpl& source);
+ IntervalTimerImpl& operator=(const IntervalTimerImpl& source);
+public:
+ IntervalTimerImpl(IOService& io_service);
+ ~IntervalTimerImpl();
+ void setupTimer(const IntervalTimer::Callback& cbfunc,
+ const uint32_t interval);
+ void callback(const asio::error_code& error);
+private:
+ // a function to update timer_ when it expires
+ void updateTimer();
+ // a function to call back when timer_ expires
+ IntervalTimer::Callback cbfunc_;
+ // interval in seconds
+ uint32_t interval_;
+ // asio timer
+ asio::deadline_timer timer_;
+};
+
+IntervalTimerImpl::IntervalTimerImpl(IOService& io_service) :
+ timer_(io_service.get_io_service())
+{}
+
+IntervalTimerImpl::~IntervalTimerImpl()
+{}
+
+void
+IntervalTimerImpl::setupTimer(const IntervalTimer::Callback& cbfunc,
+ const uint32_t interval)
+{
+ // Interval should not be 0.
+ if (interval == 0) {
+ isc_throw(isc::BadValue, "Interval should not be 0");
+ }
+ // Call back function should not be empty.
+ if (cbfunc.empty()) {
+ isc_throw(isc::InvalidParameter, "Callback function is empty");
+ }
+ cbfunc_ = cbfunc;
+ interval_ = interval;
+ // Set initial expire time.
+ // At this point the timer is not running yet and will not expire.
+ // After calling IOService::run(), the timer will expire.
+ updateTimer();
+ return;
+}
+
+void
+IntervalTimerImpl::updateTimer() {
+ try {
+ // Update expire time to (current time + interval_).
+ timer_.expires_from_now(boost::posix_time::seconds(interval_));
+ } catch (const asio::system_error& e) {
+ isc_throw(isc::Unexpected, "Failed to update timer");
+ }
+ // Reset timer.
+ timer_.async_wait(boost::bind(&IntervalTimerImpl::callback, this, _1));
+}
+
+void
+IntervalTimerImpl::callback(const asio::error_code& cancelled) {
+ // Do not call cbfunc_ in case the timer was cancelled.
+ // The timer will be canelled in the destructor of asio::deadline_timer.
+ if (!cancelled) {
+ cbfunc_();
+ // Set next expire time.
+ updateTimer();
+ }
+}
+
+IntervalTimer::IntervalTimer(IOService& io_service) {
+ impl_ = new IntervalTimerImpl(io_service);
+}
+
+IntervalTimer::~IntervalTimer() {
+ delete impl_;
+}
+
+void
+IntervalTimer::setupTimer(const Callback& cbfunc, const uint32_t interval) {
+ return (impl_->setupTimer(cbfunc, interval));
+}
+
+}
Modified: branches/trac447/src/lib/asiolink/asiolink.h
==============================================================================
--- branches/trac447/src/lib/asiolink/asiolink.h (original)
+++ branches/trac447/src/lib/asiolink/asiolink.h Tue Dec 28 10:31:10 2010
@@ -23,6 +23,7 @@
#include <unistd.h> // for some network system calls
#include <asio/ip/address.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
#include <functional>
#include <string>
@@ -98,6 +99,7 @@
namespace asiolink {
class DNSServiceImpl;
struct IOServiceImpl;
+struct IntervalTimerImpl;
/// \brief An exception that is thrown if an error occurs within the IO
/// module. This is mainly intended to be a wrapper exception class for
@@ -300,13 +302,13 @@
///
/// \param done If true, this signals the system there is an answer
/// to return.
- virtual inline void resume(const bool done) { self_->resume(done); }
+ virtual void resume(const bool done) { self_->resume(done); }
/// \brief Indicate whether the server is able to send an answer
/// to a query.
///
/// This is presently used only for testing purposes.
- virtual inline bool hasAnswer() { return (self_->hasAnswer()); }
+ virtual bool hasAnswer() { return (self_->hasAnswer()); }
/// \brief Returns the current value of the 'coroutine' object
///
@@ -316,7 +318,7 @@
/// about its current state.
///
/// \return The value of the 'coroutine' object
- virtual inline int value() { return (self_->value()); }
+ virtual int value() { return (self_->value()); }
/// \brief Returns a pointer to a clone of this DNSServer object.
///
@@ -326,7 +328,7 @@
/// that the underlying object is also correctly copied.
///
/// \return A deep copy of this DNSServer object
- virtual inline DNSServer* clone() { return (self_->clone()); }
+ virtual DNSServer* clone() { return (self_->clone()); }
//@}
protected:
@@ -349,7 +351,7 @@
class AsyncLookup {
public:
AsyncLookup(T& caller) : caller_(caller) {}
- inline void operator()() { caller_.asyncLookup(); }
+ void operator()() { caller_.asyncLookup(); }
private:
T caller_;
};
@@ -361,7 +363,7 @@
/// the details of the query and a pointer back to the current
/// server object. It is called asynchronously via the AsyncLookup
/// handler class.
- virtual inline void asyncLookup() { self_->asyncLookup(); }
+ virtual void asyncLookup() { self_->asyncLookup(); }
private:
DNSServer* self_;
@@ -567,6 +569,98 @@
unsigned retries_;
};
+/// \brief The \c IntervalTimer class is a wrapper for the ASIO
+/// \c asio::deadline_timer class.
+///
+/// This class is implemented to use \c asio::deadline_timer as
+/// interval timer.
+///
+/// \c setupTimer() sets a timer to expire on (now + interval) and
+/// a call back function.
+///
+/// \c IntervalTimerImpl::callback() is called by the timer when
+/// it expires.
+///
+/// The function calls the call back function set by \c setupTimer()
+/// and updates the timer to expire in (now + interval) seconds.
+/// The type of call back function is \c void(void).
+///
+/// The call back function will not be called if the instance of this
+/// class is destructed before the timer is expired.
+///
+/// Note: Destruction of an instance of this class while call back
+/// is pending causes throwing an exception from \c IOService.
+///
+/// Sample code:
+/// \code
+/// void function_to_call_back() {
+/// // this function will be called periodically
+/// }
+/// int interval_in_seconds = 1;
+/// IOService io_service;
+///
+/// IntervalTimer intervalTimer(io_service);
+/// intervalTimer.setupTimer(function_to_call_back, interval_in_seconds);
+/// io_service.run();
+/// \endcode
+///
+class IntervalTimer {
+public:
+ /// \name The type of timer callback function
+ typedef boost::function<void()> Callback;
+
+ ///
+ /// \name Constructors and Destructor
+ ///
+ /// Note: The copy constructor and the assignment operator are
+ /// intentionally defined as private, making this class non-copyable.
+ //@{
+private:
+ IntervalTimer(const IntervalTimer& source);
+ IntervalTimer& operator=(const IntervalTimer& source);
+public:
+ /// \brief The constructor with \c IOService.
+ ///
+ /// This constructor may throw a standard exception if
+ /// memory allocation fails inside the method.
+ /// This constructor may also throw \c asio::system_error.
+ ///
+ /// \param io_service A reference to an instance of IOService
+ ///
+ IntervalTimer(IOService& io_service);
+
+ /// \brief The destructor.
+ ///
+ /// This destructor never throws an exception.
+ ///
+ /// On the destruction of this class the timer will be canceled
+ /// inside \c asio::deadline_timer.
+ ///
+ ~IntervalTimer();
+ //@}
+
+ /// \brief Register timer callback function and interval.
+ ///
+ /// This function sets callback 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 (should not be an empty functor)
+ /// \param interval Interval in seconds (greater than 0)
+ ///
+ /// 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 isc::Unexpected ASIO library error
+ ///
+ void setupTimer(const Callback& cbfunc, const uint32_t interval);
+private:
+ IntervalTimerImpl* impl_;
+};
+
} // asiolink
#endif // __ASIOLINK_H
Modified: branches/trac447/src/lib/asiolink/internal/tcpdns.h
==============================================================================
--- branches/trac447/src/lib/asiolink/internal/tcpdns.h (original)
+++ branches/trac447/src/lib/asiolink/internal/tcpdns.h Tue Dec 28 10:31:10 2010
@@ -79,25 +79,25 @@
~TCPEndpoint() { delete asio_endpoint_placeholder_; }
//@}
- inline IOAddress getAddress() const {
+ IOAddress getAddress() const {
return (asio_endpoint_.address());
}
- inline uint16_t getPort() const {
+ uint16_t getPort() const {
return (asio_endpoint_.port());
}
- inline short getProtocol() const {
+ short getProtocol() const {
return (asio_endpoint_.protocol().protocol());
}
- inline short getFamily() const {
+ short getFamily() const {
return (asio_endpoint_.protocol().family());
}
// This is not part of the exosed IOEndpoint API but allows
// direct access to the ASIO implementation of the endpoint
- inline const asio::ip::tcp::endpoint& getASIOEndpoint() const {
+ const asio::ip::tcp::endpoint& getASIOEndpoint() const {
return (asio_endpoint_);
}
@@ -123,8 +123,8 @@
/// \param socket The ASIO representation of the TCP socket.
TCPSocket(asio::ip::tcp::socket& socket) : socket_(socket) {}
- inline int getNative() const { return (socket_.native()); }
- inline int getProtocol() const { return (IPPROTO_TCP); }
+ int getNative() const { return (socket_.native()); }
+ int getProtocol() const { return (IPPROTO_TCP); }
private:
asio::ip::tcp::socket& socket_;
Modified: branches/trac447/src/lib/asiolink/tests/asiolink_unittest.cc
==============================================================================
--- branches/trac447/src/lib/asiolink/tests/asiolink_unittest.cc (original)
+++ branches/trac447/src/lib/asiolink/tests/asiolink_unittest.cc Tue Dec 28 10:31:10 2010
@@ -21,6 +21,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <gtest/gtest.h>
@@ -54,6 +55,9 @@
// two octets encode the length of the rest of the data. This is crucial
// for the tests below.
const uint8_t test_data[] = {0, 4, 1, 2, 3, 4};
+// TODO: Consider this margin
+const boost::posix_time::time_duration TIMER_MARGIN_MSEC =
+ boost::posix_time::milliseconds(50);
TEST(IOAddressTest, fromText) {
IOAddress io_address_v4("192.0.2.1");
@@ -710,4 +714,247 @@
EXPECT_EQ(3, num);
}
-}
+// 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_() {};
+ ~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(IntervalTimerTest* test_obj) : test_obj_(test_obj) {
+ counter_ = 0;
+ }
+ void operator()() {
+ ++counter_;
+ return;
+ }
+ int counter_;
+ private:
+ IntervalTimerTest* test_obj_;
+ };
+ class TimerCallBackCancelDeleter : public std::unary_function<void, void> {
+ public:
+ TimerCallBackCancelDeleter(IntervalTimerTest* test_obj,
+ IntervalTimer* timer,
+ TimerCallBackCounter& counter)
+ : test_obj_(test_obj), timer_(timer), counter_(counter), count_(0)
+ {}
+ void operator()() {
+ ++count_;
+ if (count_ == 1) {
+ // First time of call back.
+ // Store the value of counter_.counter_.
+ prev_counter_ = counter_.counter_;
+ delete timer_;
+ } else if (count_ == 2) {
+ // Second time of call back.
+ // Stop io_service to stop all timers.
+ test_obj_->io_service_.stop();
+ // Compare the value of counter_.counter_ with stored one.
+ // If TimerCallBackCounter was not called (expected behavior),
+ // they are same.
+ if (counter_.counter_ == prev_counter_) {
+ test_obj_->timer_cancel_success_ = true;
+ }
+ }
+ return;
+ }
+ private:
+ IntervalTimerTest* test_obj_;
+ IntervalTimer* timer_;
+ TimerCallBackCounter& counter_;
+ int count_;
+ int prev_counter_;
+ };
+ class TimerCallBackOverwriter : public std::unary_function<void, void> {
+ public:
+ TimerCallBackOverwriter(IntervalTimerTest* test_obj,
+ IntervalTimer& timer)
+ : test_obj_(test_obj), timer_(timer), count_(0)
+ {}
+ void operator()() {
+ ++count_;
+ if (count_ == 1) {
+ // First time of call back.
+ // Call setupTimer() to update callback function
+ // to TimerCallBack.
+ test_obj_->timer_called_ = false;
+ 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();
+ }
+ return;
+ }
+ private:
+ IntervalTimerTest* test_obj_;
+ IntervalTimer& timer_;
+ int count_;
+ };
+protected:
+ IOService io_service_;
+ bool timer_called_;
+ bool timer_cancel_success_;
+};
+
+TEST_F(IntervalTimerTest, invalidArgumentToIntervalTimer) {
+ // Create asio_link::IntervalTimer and setup.
+ IntervalTimer itimer(io_service_);
+ // expect throw if call back function is empty
+ EXPECT_THROW(itimer.setupTimer(IntervalTimer::Callback(), 1),
+ isc::InvalidParameter);
+ // expect throw if interval is 0
+ 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.
+ 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
+ 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 =
+ (boost::posix_time::microsec_clock::universal_time() - start)
+ - boost::posix_time::seconds(1);
+ if (delta.is_negative()) {
+ delta.invert_sign();
+ }
+ // expect TimerCallBack is called; timer_called_ is true
+ EXPECT_TRUE(timer_called_);
+ // expect interval is 1 second +/- TIMER_MARGIN_MSEC.
+ EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
+}
+
+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)
+ // - increments internal counter in callback function
+ // itimer_canceller (B)
+ // (Calls TimerCallBackCancelDeleter)
+ // - first time of callback, it stores the counter value of
+ // callback_canceller and destructs itimer_counter
+ // - second time of callback, it compares the counter value of
+ // callback_canceller with stored value
+ // if they are same the timer was not called; expected result
+ // if they are different the timer was called after destructed
+ //
+ // 0 1 2 3 4 5 6 (s)
+ // (A) i-----+--x
+ // ^
+ // |destruct itimer_counter
+ // (B) i--------+--------s
+ // ^stop io_service
+ // and test itimer_counter have been stopped
+ //
+
+ // 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(callback_canceller, 2);
+ itimer_canceller.setupTimer(
+ TimerCallBackCancelDeleter(this, itimer_counter,
+ callback_canceller),
+ 3);
+ io_service_.run();
+ EXPECT_TRUE(timer_cancel_success_);
+}
+
+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)
+ // interval: 1 second
+ // itimer_overwriter (B)
+ // (Calls TimerCallBackOverwriter)
+ // - first time of callback, it calls setupTimer() to change
+ // call back function and interval of itimer to
+ // TimerCallBack / 1 second
+ // after 3 + 1 seconds from the beginning of this test,
+ // TimerCallBack() will be called and io_service_ stops.
+ // - second time of callback, it means the test fails.
+ //
+ // 0 1 2 3 4 5 6 (s)
+ // (A) i-----+--C--s
+ // ^ ^stop io_service
+ // |change call back function
+ // (B) i--------+--------S
+ // ^(stop io_service on fail)
+ //
+
+ 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(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
+ // + 1 second for TimerCallBack (stop)
+ // = 4 seconds.
+ // otherwise (test fails), it takes
+ // 3 seconds for TimerCallBackOverwriter
+ // + 3 seconds for TimerCallBackOverwriter (stop)
+ // = 6 seconds.
+ // delta: difference between elapsed time and 3 + 1 seconds
+ boost::posix_time::time_duration delta =
+ (boost::posix_time::microsec_clock::universal_time() - start)
+ - boost::posix_time::seconds(3 + 1);
+ if (delta.is_negative()) {
+ delta.invert_sign();
+ }
+ // expect callback function is updated: TimerCallBack is called
+ EXPECT_TRUE(timer_called_);
+ // expect interval is updated
+ EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
+}
+
+}
Modified: branches/trac447/src/lib/config/module_spec.cc
==============================================================================
--- branches/trac447/src/lib/config/module_spec.cc (original)
+++ branches/trac447/src/lib/config/module_spec.cc Tue Dec 28 10:31:10 2010
@@ -330,14 +330,33 @@
ModuleSpec::validate_spec_list(ConstElementPtr spec, ConstElementPtr data,
const bool full, ElementPtr errors) const
{
+ bool validated = true;
std::string cur_item_name;
BOOST_FOREACH(ConstElementPtr cur_spec_el, spec->listValue()) {
if (!validate_spec(cur_spec_el, data, full, errors)) {
- return (false);
- }
- }
- return (true);
-}
-
-}
-}
+ validated = false;
+ }
+ }
+
+ typedef std::pair<std::string, ConstElementPtr> maptype;
+
+ BOOST_FOREACH(maptype m, data->mapValue()) {
+ bool found = false;
+ BOOST_FOREACH(ConstElementPtr cur_spec_el, spec->listValue()) {
+ if (cur_spec_el->get("item_name")->stringValue().compare(m.first) == 0) {
+ found = true;
+ }
+ }
+ if (!found) {
+ validated = false;
+ if (errors) {
+ errors->add(Element::create("Unknown item " + m.first));
+ }
+ }
+ }
+
+ return (validated);
+}
+
+}
+}
Modified: branches/trac447/src/lib/config/tests/module_spec_unittests.cc
==============================================================================
--- branches/trac447/src/lib/config/tests/module_spec_unittests.cc (original)
+++ branches/trac447/src/lib/config/tests/module_spec_unittests.cc Tue Dec 28 10:31:10 2010
@@ -166,8 +166,13 @@
EXPECT_TRUE(data_test(dd, "data22_6.data"));
EXPECT_TRUE(data_test(dd, "data22_7.data"));
EXPECT_FALSE(data_test(dd, "data22_8.data"));
+ EXPECT_FALSE(data_test(dd, "data22_9.data"));
ElementPtr errors = Element::createList();
EXPECT_FALSE(data_test_with_errors(dd, "data22_8.data", errors));
EXPECT_EQ("[ \"Type mismatch\" ]", errors->str());
+
+ errors = Element::createList();
+ EXPECT_FALSE(data_test_with_errors(dd, "data22_9.data", errors));
+ EXPECT_EQ("[ \"Unknown item value_does_not_exist\" ]", errors->str());
}
Modified: branches/trac447/src/lib/config/tests/testdata/Makefile.am
==============================================================================
--- branches/trac447/src/lib/config/tests/testdata/Makefile.am (original)
+++ branches/trac447/src/lib/config/tests/testdata/Makefile.am Tue Dec 28 10:31:10 2010
@@ -20,6 +20,7 @@
EXTRA_DIST += data22_6.data
EXTRA_DIST += data22_7.data
EXTRA_DIST += data22_8.data
+EXTRA_DIST += data22_9.data
EXTRA_DIST += spec1.spec
EXTRA_DIST += spec2.spec
EXTRA_DIST += spec3.spec
Modified: branches/trac447/src/lib/config/tests/testdata/data22_8.data
==============================================================================
--- branches/trac447/src/lib/config/tests/testdata/data22_8.data (original)
+++ branches/trac447/src/lib/config/tests/testdata/data22_8.data Tue Dec 28 10:31:10 2010
@@ -5,5 +5,6 @@
"value4": "foo",
"value5": [ 1, 2, 3 ],
"value6": { "v61": "bar", "v62": true },
- "value8": [ { "a": "d" }, { "a": 1 } ]
+ "value8": [ { "a": "d" }, { "a": 1 } ],
+ "value9": { "v91": "hi", "v92": { "v92a": "Hi", "v92b": 3 } }
}
Modified: branches/trac447/src/lib/datasrc/data_source.h
==============================================================================
--- branches/trac447/src/lib/datasrc/data_source.h (original)
+++ branches/trac447/src/lib/datasrc/data_source.h Tue Dec 28 10:31:10 2010
@@ -248,7 +248,7 @@
void addDataSrc(ConstDataSrcPtr data_src);
void removeDataSrc(ConstDataSrcPtr data_src);
size_t dataSrcCount() { return (data_sources.size()); }
-
+
void findClosestEnclosure(DataSrcMatch& match) const;
// Actual queries for data should not be sent to a MetaDataSrc object,
Modified: branches/trac447/src/lib/datasrc/memory_datasrc.cc
==============================================================================
--- branches/trac447/src/lib/datasrc/memory_datasrc.cc (original)
+++ branches/trac447/src/lib/datasrc/memory_datasrc.cc Tue Dec 28 10:31:10 2010
@@ -181,7 +181,10 @@
/// For now, \c MemoryDataSrc only contains a \c ZoneTable object, which
/// consists of (pointers to) \c MemoryZone objects, we may add more
/// member variables later for new features.
-struct MemoryDataSrc::MemoryDataSrcImpl {
+class MemoryDataSrc::MemoryDataSrcImpl {
+public:
+ MemoryDataSrcImpl() : zone_count(0) {}
+ unsigned int zone_count;
ZoneTable zone_table;
};
@@ -190,6 +193,11 @@
MemoryDataSrc::~MemoryDataSrc() {
delete impl_;
+}
+
+unsigned int
+MemoryDataSrc::getZoneCount() const {
+ return (impl_->zone_count);
}
result::Result
@@ -198,7 +206,12 @@
isc_throw(InvalidParameter,
"Null pointer is passed to MemoryDataSrc::addZone()");
}
- return (impl_->zone_table.addZone(zone));
+
+ const result::Result result = impl_->zone_table.addZone(zone);
+ if (result == result::SUCCESS) {
+ ++impl_->zone_count;
+ }
+ return (result);
}
MemoryDataSrc::FindResult
Modified: branches/trac447/src/lib/datasrc/memory_datasrc.h
==============================================================================
--- branches/trac447/src/lib/datasrc/memory_datasrc.h (original)
+++ branches/trac447/src/lib/datasrc/memory_datasrc.h Tue Dec 28 10:31:10 2010
@@ -185,6 +185,13 @@
~MemoryDataSrc();
//@}
+ /// Return the number of zones stored in the data source.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \return The number of zones stored in the data source.
+ unsigned int getZoneCount() const;
+
/// Add a \c Zone to the \c MemoryDataSrc.
///
/// \c Zone must not be associated with a NULL pointer; otherwise
@@ -221,7 +228,7 @@
FindResult findZone(const isc::dns::Name& name) const;
private:
- struct MemoryDataSrcImpl;
+ class MemoryDataSrcImpl;
MemoryDataSrcImpl* impl_;
};
}
Modified: branches/trac447/src/lib/datasrc/tests/memory_datasrc_unittest.cc
==============================================================================
--- branches/trac447/src/lib/datasrc/tests/memory_datasrc_unittest.cc (original)
+++ branches/trac447/src/lib/datasrc/tests/memory_datasrc_unittest.cc Tue Dec 28 10:31:10 2010
@@ -29,8 +29,9 @@
class MemoryDataSrcTest : public ::testing::Test {
protected:
- MemoryDataSrcTest()
+ MemoryDataSrcTest() : rrclass(RRClass::IN())
{}
+ RRClass rrclass;
MemoryDataSrc memory_datasrc;
};
@@ -111,6 +112,23 @@
memory_datasrc.findZone(Name("z.i.g.h")).code);
EXPECT_EQ(Name("i.g.h"),
memory_datasrc.findZone(Name("z.i.g.h")).zone->getOrigin());
+}
+
+TEST_F(MemoryDataSrcTest, getZoneCount) {
+ EXPECT_EQ(0, memory_datasrc.getZoneCount());
+ memory_datasrc.addZone(
+ ZonePtr(new MemoryZone(rrclass, Name("example.com"))));
+ EXPECT_EQ(1, memory_datasrc.getZoneCount());
+
+ // duplicate add. counter shouldn't change
+ memory_datasrc.addZone(
+ ZonePtr(new MemoryZone(rrclass, Name("example.com"))));
+ EXPECT_EQ(1, memory_datasrc.getZoneCount());
+
+ // add one more
+ memory_datasrc.addZone(
+ ZonePtr(new MemoryZone(rrclass, Name("example.org"))));
+ EXPECT_EQ(2, memory_datasrc.getZoneCount());
}
/// \brief Test fixture for the MemoryZone class
@@ -189,7 +207,6 @@
ASSERT_EQ(class_, zone_.getClass());
ASSERT_EQ(origin_, zone_.getOrigin());
}
-
/**
* \brief Test adding.
*
Modified: branches/trac447/src/lib/datasrc/tests/zonetable_unittest.cc
==============================================================================
--- branches/trac447/src/lib/datasrc/tests/zonetable_unittest.cc (original)
+++ branches/trac447/src/lib/datasrc/tests/zonetable_unittest.cc Tue Dec 28 10:31:10 2010
@@ -75,7 +75,7 @@
EXPECT_THROW(zone_table.addZone(ZonePtr()), isc::InvalidParameter);
}
-TEST_F(ZoneTableTest, removeZone) {
+TEST_F(ZoneTableTest, DISABLED_removeZone) {
EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone1));
EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone2));
EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone3));
Modified: branches/trac447/src/lib/datasrc/zonetable.cc
==============================================================================
--- branches/trac447/src/lib/datasrc/zonetable.cc (original)
+++ branches/trac447/src/lib/datasrc/zonetable.cc Tue Dec 28 10:31:10 2010
@@ -12,14 +12,12 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-// Note: map and utility (for 'pair') are for temporary workaround.
-// we'll soon replace them with built-in intelligent backend structure.
-#include <map>
-#include <utility>
+#include <cassert>
#include <dns/name.h>
#include <datasrc/zonetable.h>
+#include <datasrc/rbtree.h>
using namespace std;
using namespace isc::dns;
@@ -27,13 +25,79 @@
namespace isc {
namespace datasrc {
-// This is a temporary, inefficient implementation using std::map and handmade
-// iteration to realize longest match.
+/// \short Private data and implementation of ZoneTable
+struct ZoneTable::ZoneTableImpl {
+ // Type aliases to make it shorter
+ typedef RBTree<Zone> ZoneTree;
+ typedef RBNode<Zone> ZoneNode;
+ // The actual storage
+ ZoneTree zones_;
-struct ZoneTable::ZoneTableImpl {
- typedef map<Name, ZonePtr> ZoneMap;
- typedef pair<Name, ZonePtr> NameAndZone;
- ZoneMap zones;
+ /*
+ * The implementation methods are here and just wrap-called in the
+ * ZoneTable. We have variables locally (without impl_->), have
+ * type aliases, etc. And they will get inlined anyway.
+ */
+
+ // Implementation of ZoneTable::addZone
+ result::Result addZone(ZonePtr zone) {
+ // Sanity check
+ if (!zone) {
+ isc_throw(InvalidParameter,
+ "Null pointer is passed to ZoneTable::addZone()");
+ }
+
+ // Get the node where we put the zone
+ ZoneNode* node(NULL);
+ switch (zones_.insert(zone->getOrigin(), &node)) {
+ // This is OK
+ case ZoneTree::SUCCEED:
+ case ZoneTree::ALREADYEXIST:
+ break;
+ // Can Not Happen
+ default:
+ assert(0);
+ }
+ // Can Not Happen
+ assert(node);
+
+ // Is it empty? We either just created it or it might be nonterminal
+ if (node->isEmpty()) {
+ node->setData(zone);
+ return (result::SUCCESS);
+ } else { // There's something there already
+ return (result::EXIST);
+ }
+ }
+
+ // Implementation of ZoneTable::findZone
+ ZoneTable::FindResult findZone(const Name& name) const {
+ ZoneNode *node(NULL);
+ result::Result my_result;
+
+ // Translate the return codes
+ switch (zones_.find(name, &node)) {
+ case ZoneTree::EXACTMATCH:
+ my_result = result::SUCCESS;
+ break;
+ case ZoneTree::PARTIALMATCH:
+ my_result = result::PARTIALMATCH;
+ break;
+ // We have no data there, so translate the pointer to NULL as well
+ case ZoneTree::NOTFOUND:
+ return (FindResult(result::NOTFOUND, ConstZonePtr()));
+ // Can Not Happen
+ default:
+ assert(0);
+ // Because of warning
+ return (FindResult(result::NOTFOUND, ConstZonePtr()));
+ }
+
+ // Can Not Happen (remember, NOTFOUND is handled)
+ assert(node);
+
+ return (FindResult(my_result, node->getData()));
+ }
};
ZoneTable::ZoneTable() : impl_(new ZoneTableImpl)
@@ -45,40 +109,21 @@
result::Result
ZoneTable::addZone(ZonePtr zone) {
- if (!zone) {
- isc_throw(InvalidParameter,
- "Null pointer is passed to ZoneTable::addZone()");
- }
-
- if (impl_->zones.insert(
- ZoneTableImpl::NameAndZone(zone->getOrigin(), zone)).second
- == true) {
- return (result::SUCCESS);
- } else {
- return (result::EXIST);
- }
+ return (impl_->addZone(zone));
}
result::Result
-ZoneTable::removeZone(const Name& origin) {
- return (impl_->zones.erase(origin) == 1 ? result::SUCCESS :
- result::NOTFOUND);
+ZoneTable::removeZone(const Name&) {
+ // TODO Implement
+ assert(0);
+ // This should not ever be returned, the assert should kill us by now
+ return (result::SUCCESS);
}
ZoneTable::FindResult
ZoneTable::findZone(const Name& name) const {
- // Inefficient internal loop to find a longest match.
- // This will be replaced with a single call to more intelligent backend.
- for (int i = 0; i < name.getLabelCount(); ++i) {
- Name matchname(name.split(i));
- ZoneTableImpl::ZoneMap::const_iterator found =
- impl_->zones.find(matchname);
- if (found != impl_->zones.end()) {
- return (FindResult(i == 0 ? result::SUCCESS :
- result::PARTIALMATCH, (*found).second));
- }
- }
- return (FindResult(result::NOTFOUND, ConstZonePtr()));
+ return (impl_->findZone(name));
}
+
} // end of namespace datasrc
} // end of namespace isc
Modified: branches/trac447/src/lib/datasrc/zonetable.h
==============================================================================
--- branches/trac447/src/lib/datasrc/zonetable.h (original)
+++ branches/trac447/src/lib/datasrc/zonetable.h Tue Dec 28 10:31:10 2010
@@ -71,8 +71,18 @@
//@}
/// Add a \c Zone to the \c ZoneTable.
- /// See the description of <code>MemoryDataSrc::addZone()</code> for more
- /// details.
+ ///
+ /// \c Zone must not be associated with a NULL pointer; otherwise
+ /// an exception of class \c InvalidParameter will be thrown.
+ /// If internal resource allocation fails, a corresponding standard
+ /// exception will be thrown.
+ /// This method never throws an exception otherwise.
+ ///
+ /// \param zone A \c Zone object to be added.
+ /// \return \c result::SUCCESS If the zone is successfully
+ /// added to the zone table.
+ /// \return \c result::EXIST The zone table already contains
+ /// zone of the same origin.
result::Result addZone(ZonePtr zone);
/// Remove a \c Zone of the given origin name from the \c ZoneTable.
@@ -87,8 +97,23 @@
result::Result removeZone(const isc::dns::Name& origin);
/// Find a \c Zone that best matches the given name in the \c ZoneTable.
- /// See the description of <code>MemoryDataSrc::findZone()</code> for more
- /// details.
+ ///
+ /// It searches the internal storage for a \c Zone that gives the
+ /// longest match against \c name, and returns the result in the
+ /// form of a \c FindResult object as follows:
+ /// - \c code: The result code of the operation.
+ /// - \c result::SUCCESS: A zone that gives an exact match
+ /// is found
+ /// - \c result::PARTIALMATCH: A zone whose origin is a
+ /// super domain of \c name is found (but there is no exact match)
+ /// - \c result::NOTFOUND: For all other cases.
+ /// - \c zone: A <Boost> shared pointer to the found \c Zone object if one
+ /// is found; otherwise \c NULL.
+ ///
+ /// This method never throws an exception.
+ ///
+ /// \param name A domain name for which the search is performed.
+ /// \return A \c FindResult object enclosing the search result (see above).
FindResult findZone(const isc::dns::Name& name) const;
private:
Modified: branches/trac447/src/lib/dns/python/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/dns/python/tests/Makefile.am (original)
+++ branches/trac447/src/lib/dns/python/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,3 +1,4 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = edns_python_test.py
PYTESTS += message_python_test.py
PYTESTS += messagerenderer_python_test.py
@@ -22,14 +23,17 @@
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
endif
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/dns/.libs:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
TESTDATA_PATH=$(abs_top_srcdir)/src/lib/dns/tests/testdata:$(abs_top_builddir)/src/lib/dns/tests/testdata \
$(LIBRARY_PATH_PLACEHOLDER) \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/cc/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/cc/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/cc/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,16 +1,21 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
+
PYTESTS = message_test.py data_test.py session_test.py
# NOTE: test_session.py is to be run manually, so not automated.
EXTRA_DIST = $(PYTESTS)
EXTRA_DIST += sendcmd.py
EXTRA_DIST += test_session.py
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
BIND10_TEST_SOCKET_FILE=$(builddir)/test_socket.sock \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/config/ccsession.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/ccsession.py (original)
+++ branches/trac447/src/lib/python/isc/config/ccsession.py Tue Dec 28 10:31:10 2010
@@ -224,7 +224,7 @@
if not self._config_handler:
answer = create_answer(2, self._module_name + " has no config handler")
elif not self.get_module_spec().validate_config(False, new_config, errors):
- answer = create_answer(1, " ".join(errors))
+ answer = create_answer(1, ", ".join(errors))
else:
isc.cc.data.remove_identical(new_config, self.get_local_config())
answer = self._config_handler(new_config)
@@ -422,7 +422,16 @@
"""Commit all local changes, send them through b10-cmdctl to
the configuration manager"""
if self.get_local_changes():
- self._conn.send_POST('/ConfigManager/set_config', [ self.get_local_changes() ])
- # todo: check result
- self.request_current_config()
- self.clear_local_changes()
+ response = self._conn.send_POST('/ConfigManager/set_config',
+ [ self.get_local_changes() ])
+ answer = isc.cc.data.parse_value_str(response.read().decode())
+ # answer is either an empty dict (on success), or one
+ # containing errors
+ if answer == {}:
+ self.request_current_config()
+ self.clear_local_changes()
+ elif "error" in answer:
+ print("Error: " + answer["error"])
+ print("Configuration not committed")
+ else:
+ raise ModuleCCSessionError("Unknown format of answer in commit(): " + str(answer))
Modified: branches/trac447/src/lib/python/isc/config/config_data.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/config_data.py (original)
+++ branches/trac447/src/lib/python/isc/config/config_data.py Tue Dec 28 10:31:10 2010
@@ -464,12 +464,15 @@
there is a specification for the given identifier, the type
is checked."""
spec_part = self.find_spec_part(identifier)
- if spec_part is not None and value is not None:
- id, list_indices = isc.cc.data.split_identifier_list_indices(identifier)
- if list_indices is not None \
- and spec_part['item_type'] == 'list':
- spec_part = spec_part['list_item_spec']
- check_type(spec_part, value)
+ if spec_part is not None:
+ if value is not None:
+ id, list_indices = isc.cc.data.split_identifier_list_indices(identifier)
+ if list_indices is not None \
+ and spec_part['item_type'] == 'list':
+ spec_part = spec_part['list_item_spec']
+ check_type(spec_part, value)
+ else:
+ raise isc.cc.data.DataNotFoundError(identifier)
# Since we do not support list diffs (yet?), we need to
# copy the currently set list of items to _local_changes
Modified: branches/trac447/src/lib/python/isc/config/module_spec.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/module_spec.py (original)
+++ branches/trac447/src/lib/python/isc/config/module_spec.py Tue Dec 28 10:31:10 2010
@@ -328,7 +328,24 @@
return True
def _validate_spec_list(module_spec, full, data, errors):
+ # we do not return immediately, there may be more errors
+ # so we keep a boolean to keep track if we found errors
+ validated = True
+
+ # check if the known items are correct
for spec_item in module_spec:
if not _validate_spec(spec_item, full, data, errors):
- return False
- return True
+ validated = False
+
+ # check if there are items in our data that are not in the
+ # specification
+ for item_name in data:
+ found = False
+ for spec_item in module_spec:
+ if spec_item["item_name"] == item_name:
+ found = True
+ if not found:
+ if errors != None:
+ errors.append("unknown item " + item_name)
+ validated = False
+ return validated
Modified: branches/trac447/src/lib/python/isc/config/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/config/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/config/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,16 +1,20 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = ccsession_test.py cfgmgr_test.py config_data_test.py
PYTESTS += module_spec_test.py
EXTRA_DIST = $(PYTESTS)
EXTRA_DIST += unittest_fakesession.py
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/tests/testdata \
CONFIG_WR_TESTDATA_PATH=$(abs_top_builddir)/src/lib/config/tests/testdata \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/config/tests/ccsession_test.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/tests/ccsession_test.py (original)
+++ branches/trac447/src/lib/python/isc/config/tests/ccsession_test.py Tue Dec 28 10:31:10 2010
@@ -290,7 +290,7 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_ok)
self.assertEqual(len(fake_session.message_queue), 0)
- cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 2 }})
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'item1': 2 })
fake_session.group_sendmsg(cmd, 'Spec2')
self.assertEqual(len(fake_session.message_queue), 1)
mccs.check_command()
@@ -303,12 +303,12 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_err)
self.assertEqual(len(fake_session.message_queue), 0)
- cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 'aaa' }})
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'item1': 'aaa' })
fake_session.group_sendmsg(cmd, 'Spec2')
self.assertEqual(len(fake_session.message_queue), 1)
mccs.check_command()
self.assertEqual(len(fake_session.message_queue), 1)
- self.assertEqual({'result': [1, 'just an error']},
+ self.assertEqual({'result': [1, 'aaa should be an integer']},
fake_session.get_message('Spec2', None))
def test_check_command5(self):
@@ -316,12 +316,12 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_exc)
self.assertEqual(len(fake_session.message_queue), 0)
- cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 'aaa' }})
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'item1': 'aaa' })
fake_session.group_sendmsg(cmd, 'Spec2')
self.assertEqual(len(fake_session.message_queue), 1)
mccs.check_command()
self.assertEqual(len(fake_session.message_queue), 1)
- self.assertEqual({'result': [1, 'just an exception']},
+ self.assertEqual({'result': [1, 'aaa should be an integer']},
fake_session.get_message('Spec2', None))
def test_check_command6(self):
@@ -416,7 +416,7 @@
mccs = self.create_session("spec2.spec", None, None, fake_session)
mccs.set_config_handler(self.my_config_handler_ok)
self.assertEqual(len(fake_session.message_queue), 0)
- cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'Spec2': { 'item1': 2 }})
+ cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, { 'item1': 2 })
self.assertEqual(len(fake_session.message_queue), 0)
env = { 'group':'Spec2', 'from':None }
mccs.check_command_without_recvmsg(cmd, env)
@@ -559,6 +559,14 @@
mccs.check_command()
self.assertEqual(len(fake_session.message_queue), 0)
+
+class fakeData:
+ def decode(self):
+ return "{}";
+
+class fakeAnswer:
+ def read(self):
+ return fakeData();
class fakeUIConn():
def __init__(self):
@@ -581,7 +589,7 @@
if name in self.post_answers:
return self.post_answers[name]
else:
- return None
+ return fakeAnswer()
class TestUIModuleCCSession(unittest.TestCase):
Modified: branches/trac447/src/lib/python/isc/config/tests/config_data_test.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/tests/config_data_test.py (original)
+++ branches/trac447/src/lib/python/isc/config/tests/config_data_test.py Tue Dec 28 10:31:10 2010
@@ -335,6 +335,8 @@
pass
def test_get_local_value(self):
+ module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
+ self.mcd.set_specification(module_spec)
value = self.mcd.get_local_value("Spec2/item1")
self.assertEqual(None, value)
self.mcd.set_value("Spec2/item1", 2)
@@ -464,12 +466,11 @@
module_spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
self.mcd.set_specification(module_spec)
self.mcd.set_value("Spec2/item1", 2)
- self.assertRaises(isc.cc.data.DataTypeError, self.mcd.set_value, "Spec2/item1", "asdf")
-
- self.mcd.set_value("Spec2/no_such_item", 4)
- value, status = self.mcd.get_value("Spec2/no_such_item")
- self.assertEqual(value, 4)
- self.assertEqual(MultiConfigData.LOCAL, status)
+ self.assertRaises(isc.cc.data.DataTypeError,
+ self.mcd.set_value, "Spec2/item1", "asdf")
+
+ self.assertRaises(isc.cc.data.DataNotFoundError,
+ self.mcd.set_value, "Spec2/no_such_item", 4)
self.mcd.set_value("Spec2/item5[0]", "c")
value, status = self.mcd.get_value("Spec2/item5[0]")
Modified: branches/trac447/src/lib/python/isc/config/tests/module_spec_test.py
==============================================================================
--- branches/trac447/src/lib/python/isc/config/tests/module_spec_test.py (original)
+++ branches/trac447/src/lib/python/isc/config/tests/module_spec_test.py Tue Dec 28 10:31:10 2010
@@ -312,6 +312,18 @@
self.assertEqual(False, isc.config.module_spec._validate_spec(spec, True, {}, None))
self.assertEqual(False, isc.config.module_spec._validate_spec(spec, True, {}, errors))
self.assertEqual(['non-optional item an_item missing'], errors)
+
+ def test_validate_unknown_items(self):
+ spec = [{ 'item_name': "an_item",
+ 'item_type': "string",
+ 'item_optional': True,
+ 'item_default': "asdf"
+ }]
+
+ errors = []
+ self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, None))
+ self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, errors))
+ self.assertEqual(['unknown item does_not_exist'], errors)
Modified: branches/trac447/src/lib/python/isc/datasrc/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/datasrc/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/datasrc/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,16 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = master_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/log/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/log/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/log/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,16 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = log_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/net/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/net/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/net/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,16 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = addr_test.py parse_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/notify/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/notify/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/notify/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,3 +1,4 @@
+PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
PYTESTS = notify_out_test.py
EXTRA_DIST = $(PYTESTS)
@@ -8,13 +9,16 @@
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
endif
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
$(LIBRARY_PATH_PLACEHOLDER) \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
Modified: branches/trac447/src/lib/python/isc/util/tests/Makefile.am
==============================================================================
--- branches/trac447/src/lib/python/isc/util/tests/Makefile.am (original)
+++ branches/trac447/src/lib/python/isc/util/tests/Makefile.am Tue Dec 28 10:31:10 2010
@@ -1,12 +1,16 @@
+PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = process_test.py socketserver_mixin_test.py
EXTRA_DIST = $(PYTESTS)
-# later will have configure option to choose this, like: coverage run --branch
-PYCOVERAGE = $(PYTHON)
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
+if ENABLE_PYTHON_COVERAGE
+ touch $(abs_top_srcdir)/.coverage
+ rm -f .coverage
+ ${LN_S} $(abs_top_srcdir)/.coverage .coverage
+endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
- $(PYCOVERAGE) $(abs_srcdir)/$$pytest || exit ; \
+ $(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
More information about the bind10-changes
mailing list