From df416a7881c4f6d0fdfffe9956824ff2bcc5a762 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 27 May 2010 12:03:32 +0000 Subject: [PATCH 02/66] Add logging module and unittest in lib/python/isc/log, also add log in xfrout module for testing. Currently, logging module supports three channels:stderr file and syslog. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@1946 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 2 + src/bin/xfrout/xfrout.py.in | 23 ++- src/bin/xfrout/xfrout.spec.pre.in | 30 ++++ src/lib/python/isc/Makefile.am | 2 +- src/lib/python/isc/__init__.py | 1 + src/lib/python/isc/log/Makefile.am | 6 + src/lib/python/isc/log/__init__.py | 1 + src/lib/python/isc/log/log.py | 195 +++++++++++++++++++++++ src/lib/python/isc/log/tests/Makefile.am | 12 ++ src/lib/python/isc/log/tests/log_test.py | 121 ++++++++++++++ 10 files changed, 389 insertions(+), 4 deletions(-) create mode 100644 src/lib/python/isc/log/Makefile.am create mode 100644 src/lib/python/isc/log/__init__.py create mode 100644 src/lib/python/isc/log/log.py create mode 100644 src/lib/python/isc/log/tests/Makefile.am create mode 100644 src/lib/python/isc/log/tests/log_test.py diff --git a/configure.ac b/configure.ac index b441ed5f57..c98a08edd2 100644 --- a/configure.ac +++ b/configure.ac @@ -396,6 +396,8 @@ AC_CONFIG_FILES([Makefile src/lib/python/isc/cc/tests/Makefile src/lib/python/isc/config/Makefile src/lib/python/isc/config/tests/Makefile + src/lib/python/isc/log/Makefile + src/lib/python/isc/log/tests/Makefile src/lib/config/Makefile src/lib/config/tests/Makefile src/lib/dns/Makefile diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index dc5f43d4ba..435b2239aa 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -26,6 +26,7 @@ from isc.datasrc import sqlite3_ds from socketserver import * import os from isc.config.ccsession import * +from isc.log.log import * from isc.cc import SessionError import socket from optparse import OptionParser, OptionValueError @@ -276,7 +277,7 @@ class XfroutSession(BaseRequestHandler): class UnixSockServer(ThreadingUnixStreamServer): '''The unix domain socket server which accept xfr query sent from auth server.''' - def __init__(self, sock_file, handle_class, shutdown_event, config_data): + def __init__(self, sock_file, handle_class, shutdown_event, config_data, log): try: os.unlink(sock_file) except: @@ -287,23 +288,30 @@ class UnixSockServer(ThreadingUnixStreamServer): self._lock = threading.Lock() self._transfers_counter = 0 self._shutdown_event = shutdown_event + self._log = log self.update_config_data(config_data) def shutdown(self): + self._log.log_message('warning', 'Xfrout process will is shutting down') ThreadingUnixStreamServer.shutdown(self) try: os.unlink(self._sock_file) except: - pass + #pass + self._log.log_message('error', 'OS unlink sock file exception while shutting down') def update_config_data(self, new_config): '''Apply the new config setting of xfrout module. ''' + self._log.log_message('info', 'update config data start') self._lock.acquire() self._max_transfers_out = new_config.get('transfers_out') + self._log.log_message('debug', 'max transfer out : %d', self._max_transfers_out) self._db_file = new_config.get('db_file') + self._log.log_message('debug', 'db file name : %s', self._db_file) self._lock.release() + self._log.log_message('info', 'update config data complete') def get_db_file(self): self._lock.acquire() @@ -339,11 +347,15 @@ def listen_on_xfr_query(unix_socket_server): class XfroutServer: def __init__(self): self._unix_socket_server = None + self._log = None self._listen_sock_file = UNIX_SOCKET_FILE self._shutdown_event = threading.Event() self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler) self._config_data = self._cc.get_full_config() self._cc.start() + self._log = isc.log.ModuleLogger(self._config_data.get('log_name'), self._config_data.get('log_file'), + self._config_data.get('severity'), self._config_data.get('versions'), + self._config_data.get('max_bytes'), True) self._start_xfr_query_listener() @@ -351,7 +363,8 @@ class XfroutServer: '''Start a new thread to accept xfr query. ''' self._unix_socket_server = UnixSockServer(self._listen_sock_file, XfroutSession, - self._shutdown_event, self._config_data); + self._shutdown_event, self._config_data, + self._log); listener = threading.Thread(target = listen_on_xfr_query, args = (self._unix_socket_server,)) listener.start() @@ -365,6 +378,10 @@ class XfroutServer: continue self._config_data[key] = new_config[key] + if self._log: + self._log.update_config(self._config_data.get('log_file'), self._config_data.get('severity'), + self._config_data.get('max_bytes'), self._config_data.get('versions')) + if self._unix_socket_server: self._unix_socket_server.update_config_data(self._config_data) diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in index 495d3fd2a0..2b53fc01d7 100644 --- a/src/bin/xfrout/xfrout.spec.pre.in +++ b/src/bin/xfrout/xfrout.spec.pre.in @@ -13,6 +13,36 @@ "item_type": "string", "item_optional": False, "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3' + }, + { + "item_name": "log_name", + "item_type": "string", + "item_optional": False, + "item_default": "Xfrout" + }, + { + "item_name": "log_file", + "item_type": "string", + "item_optional": False, + "item_default": "/var/log/xfrout.log" + }, + { + "item_name": "severity", + "item_type": "string", + "item_optional": False, + "item_default": "debug" + }, + { + "item_name": "versions", + "item_type": "integer", + "item_optional": False, + "item_default": 5 + }, + { + "item_name": "max_bytes", + "item_type": "integer", + "item_optional": False, + "item_default": 1048576 } ], "commands": [ diff --git a/src/lib/python/isc/Makefile.am b/src/lib/python/isc/Makefile.am index 4c0ccfe5a9..307c22f4b9 100644 --- a/src/lib/python/isc/Makefile.am +++ b/src/lib/python/isc/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = datasrc cc config # Util +SUBDIRS = datasrc cc config log # Util python_PYTHON = __init__.py diff --git a/src/lib/python/isc/__init__.py b/src/lib/python/isc/__init__.py index 44dd29d088..b0a098d7d5 100644 --- a/src/lib/python/isc/__init__.py +++ b/src/lib/python/isc/__init__.py @@ -1,3 +1,4 @@ import isc.datasrc import isc.cc import isc.config +import isc.log diff --git a/src/lib/python/isc/log/Makefile.am b/src/lib/python/isc/log/Makefile.am new file mode 100644 index 0000000000..0fddc6378f --- /dev/null +++ b/src/lib/python/isc/log/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS = tests + +python_PYTHON = __init__.py log.py + +pythondir = $(pyexecdir)/isc/log + diff --git a/src/lib/python/isc/log/__init__.py b/src/lib/python/isc/log/__init__.py new file mode 100644 index 0000000000..a34e164d3f --- /dev/null +++ b/src/lib/python/isc/log/__init__.py @@ -0,0 +1 @@ +from isc.log.log import * diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py new file mode 100644 index 0000000000..2b95a35e50 --- /dev/null +++ b/src/lib/python/isc/log/log.py @@ -0,0 +1,195 @@ +# Copyright (C) 2010 Internet Systems Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os +import syslog +import logging +import logging.handlers + +######################################################################### +# LEVELS: logging levels mapping +######################################################################### +LEVELS = {'debug' : logging.DEBUG, + 'info' : logging.INFO, + 'warning' : logging.WARNING, + 'error' : logging.ERROR, + 'critical' : logging.CRITICAL} + +formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") +time_formatter = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") +######################################################################### +# NullHandler: define a do-nothing handler +######################################################################### +class NullHandler(logging.Handler): + def emit(self, record): + pass + +######################################################################### +# RotatingFileHandler: replace RotatingFileHandler with a custom handler +######################################################################### +class RotatingFileHandler(logging.handlers.RotatingFileHandler): + + def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None): + logging.handlers.RotatingFileHandler.__init__(self, filename, mode, + maxBytes, backupCount, + encoding) + ##################################################################### + # shouldRollover + # Rewrite RotatingFileHandler.shouldRollover. + # If the log file is deleted, a new file will be created. + ##################################################################### + def shouldRollover(self, record): + if self.stream is None: # delay was set... + self.stream = self._open() + + dfn = self.baseFilename # Is log file exist? + if not os.path.exists(dfn): + self.stream.close() + self.stream = self._open() + + if self.maxBytes > 0: # are we rolling over? + msg = "%s\n" % self.format(record) + self.stream.seek(0, 2) #due to non-posix-compliant Windows feature + if self.stream.tell() + len(msg) >= self.maxBytes: + return 1 + return 0 + + ###################################################################### + # handleError + # Rewrite RotatingFileHandler.handleError. + # If raiseExceptions is false, exceptions get silently ignored. + ###################################################################### + def handleError(self, record): + pass + + ###################################################################### + # update_config + # update RotatingFileHandler configuration + # input: + # new log file name + # max backup count + # predetermined log file size + ###################################################################### + def update_config(self, file_name, backup_count, max_bytes): + self.baseFilename = file_name + self.maxBytes = max_bytes + self.backupCount = backup_count + + +######################################################################### +# SLHandler: Replace SysLogHandler with a custom handler due to python3.1 +# SysLogHandler issue : http://bugs.python.org/issue8148 +######################################################################### +class SLHandler(logging.Handler): + def __init__(self, ident, logopt=0, facility=syslog.LOG_USER): + logging.Handler.__init__(self) + self.ident = ident + self.logopt = logopt + self.facility = facility + self.mappings = { + logging.DEBUG: syslog.LOG_DEBUG, + logging.INFO: syslog.LOG_INFO, + logging.WARNING: syslog.LOG_WARNING, + logging.ERROR: syslog.LOG_ERR, + logging.CRITICAL: syslog.LOG_CRIT, + } + + def encodeLevel(self, level): + return self.mappings.get(level, syslog.LOG_INFO) + + def handleError(self, record): + pass + + def emit(self, record): + syslog.openlog(self.ident, self.logopt, self.facility) + msg = self.format(record) + prio = self.encodeLevel(record.levelno) + syslog.syslog(prio, msg) + syslog.closelog() + + +######################################################################### +# ModuleLogger: rewrite logging.Logger +######################################################################### +class ModuleLogger(logging.getLoggerClass()): + def __init__(self, log_name, log_file, + severity = 'debug', backup_count = 0, max_bytes = 0, + log_to_console = True): + logging.Logger.__init__(self, log_name) + + # Set up a specific logger with our desired output level + logLevel = LEVELS.get(severity, logging.NOTSET) + self.setLevel(logLevel) + + null_handler = NullHandler() + self.addHandler(null_handler) + + self.rotating_handler = None + self.stream_handler = None + self.syslog_handler = None + self.add_rotate_handler(log_file, max_bytes, backup_count) + if log_to_console: + self.add_stream_handler() + else: + self.add_syslog_handler() + + def add_rotate_handler(self, log_file, max_bytes, backup_count): + # If logFile was specified + if(log_file != 0 and log_file != ''): + # Add the log message handler to the logger + try: + self.rotating_handler = RotatingFileHandler(filename = log_file, maxBytes = max_bytes, + backupCount = backup_count) + # add formatter to ch + self.rotating_handler.setFormatter(time_formatter) + self.addHandler(self.rotating_handler) + except IOError: + pass + + def add_stream_handler(self): + self.stream_handler = logging.StreamHandler() + self.stream_handler.setFormatter(time_formatter) + self.addHandler(self.stream_handler) + + def add_syslog_handler(self): + self.syslog_handler = SLHandler('BIND10') + self.syslog_handler.setFormatter(formatter) + #set syslog handler level info + self.syslog_handler.setLevel(logging.INFO) + self.addHandler(self.syslog_handler) + + def update_rotate_handler(self, log_file, max_bytes, backup_count): + # If logFile was specified + if (self.rotating_handler not in self.handlers): + pass + else: + if(log_file != 0 and log_file != ''): + self.rotating_handler.update_config(log_file, max_bytes, backup_count) + else: + self.rotating_handler.flush() + self.rotating_handler.close() + self.removeHandler(self.rotating_handler) + + def update_config(self, file_name, level, max_bytes, backup_count): + logLevel = LEVELS.get(level, logging.NOTSET) + if(logLevel != self.getEffectiveLevel()): + self.setLevel(logLevel) + self.update_rotate_handler(file_name, backup_count, max_bytes) + + def log_message(self, level, msg, *args, **kwargs): + logLevel = LEVELS.get(level, logging.NOTSET) + self.log(logLevel, msg, *args, **kwargs) + + diff --git a/src/lib/python/isc/log/tests/Makefile.am b/src/lib/python/isc/log/tests/Makefile.am new file mode 100644 index 0000000000..8dad207ca6 --- /dev/null +++ b/src/lib/python/isc/log/tests/Makefile.am @@ -0,0 +1,12 @@ +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: + for pytest in $(PYTESTS) ; do \ + echo Running test: $$pytest ; \ + env PYTHONPATH=$(abs_top_srcdir)/src/lib/python \ + $(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \ + done diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py new file mode 100644 index 0000000000..e5d87280f6 --- /dev/null +++ b/src/lib/python/isc/log/tests/log_test.py @@ -0,0 +1,121 @@ +from isc.log.log import * +import unittest +import os + +class TestRotateFileHandler(unittest.TestCase): + + def setUp(self): + self.handler = RotatingFileHandler('/var/log/rotate_file_handler.log', 1024, 5) + + def test_shouldRollover(self): + if(os.path.exists('/var/log/rotate_file_handler.log')): + os.remove('/var/log/rotate_file_handler.log') + record = logging.LogRecord(None, None, "", 0, "rotate file handler", (), None, None) + self.handler.shouldRollover(record) + self.assertTrue(os.path.exists('/var/log/rotate_file_handler.log')) + + def test_update_config(self): + self.handler.update_config('/var/log/rotate_file_handler2.log', 512, 3) + self.assertEqual(self.handler.baseFilename, '/var/log/rotate_file_handler2.log') + self.assertEqual(self.handler.maxBytes, 3) + self.assertEqual(self.handler.backupCount, 512) + + +class TestLogging(unittest.TestCase): + + def setUp(self): + self.file_stream_logger = ModuleLogger('File_Stream_Logger', '/var/log/FileStreamLogger.log', + 'debug', 5, 1024, True) + self.syslog_logger = ModuleLogger('SysLogger', '', 'info', 5, 1024, False) + + def test_logging_init(self): + self.assertNotEqual(self.file_stream_logger.rotating_handler, None) + self.assertNotEqual(self.file_stream_logger.stream_handler, None) + self.assertEqual(self.file_stream_logger.syslog_handler, None) + + ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.assertTrue(ret) + ret = self.file_stream_logger.stream_handler in self.file_stream_logger.handlers + self.assertTrue(ret) + ret = self.file_stream_logger.syslog_handler in self.file_stream_logger.handlers + self.assertFalse(ret) + logLevel = LEVELS.get('debug', logging.NOTSET) + self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) + + self.assertEqual(self.syslog_logger.rotating_handler, None) + self.assertEqual(self.syslog_logger.stream_handler, None) + self.assertNotEqual(self.syslog_logger.syslog_handler, None) + ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.assertFalse(ret) + ret = self.syslog_logger.stream_handler in self.syslog_logger.handlers + self.assertFalse(ret) + ret = self.syslog_logger.syslog_handler in self.syslog_logger.handlers + self.assertTrue(ret) + + logLevel = LEVELS.get('info', logging.NOTSET) + self.assertEqual(self.syslog_logger.getEffectiveLevel(), logLevel) + + def test_add_rotate_handler(self): + if(self.syslog_logger.rotating_handler in self.syslog_logger.handlers): + self.syslog_logger.removeHandler(self.syslog_logger.rotating_handler) + + self.syslog_logger.add_rotate_handler('', 1024, 5) + ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.assertFalse(ret) + + self.syslog_logger.add_rotate_handler('/var/log/RotateFile.log', 1024, 5) + ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.assertTrue(ret) + + def test_add_stream_handler(self): + if(self.file_stream_logger.stream_handler in self.file_stream_logger.handlers): + self.file_stream_logger.removeHandler(self.file_stream_logger.stream_handler) + + self.file_stream_logger.add_stream_handler() + ret = self.file_stream_logger.stream_handler in self.file_stream_logger.handlers + self.assertTrue(ret) + + def test_add_syslog_handler(self): + if(self.syslog_logger.syslog_handler in self.syslog_logger.handlers): + self.syslog_logger.removeHandler(self.syslog_logger.syslog_handler) + + self.syslog_logger.add_syslog_handler() + ret = self.syslog_logger.syslog_handler in self.syslog_logger.handlers + self.assertTrue(ret) + + def test_update_rotate_handler(self): + self.file_stream_logger.update_rotate_handler('/var/log/RotateFile', 4, 1024) + ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.assertTrue(ret) + + self.file_stream_logger.update_rotate_handler('', 5, 1024) + ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.assertFalse(ret) + + self.file_stream_logger.update_rotate_handler('/var/log/RotateFile', 4, 1024) + ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.assertFalse(ret) + + def test_update_config(self): + self.file_stream_logger.update_config('/var/log/RotateFile','error', 4, 1024) + logLevel = LEVELS.get('error', logging.NOTSET) + self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) + + def test_log_message(self): + print ('\r') + #output log message to stderr and file + self.file_stream_logger.log_message('debug', 'Debug message') + self.file_stream_logger.log_message('info', 'Info message') + self.file_stream_logger.log_message('warning', 'Warning message') + self.file_stream_logger.log_message('error', 'Error message') + self.file_stream_logger.log_message('critical', 'Critical message') + + #output log message to syslog + self.syslog_logger.log_message('debug', 'Debug message') + self.syslog_logger.log_message('info', 'Info message') + self.syslog_logger.log_message('warning', 'Warning message') + self.syslog_logger.log_message('error', 'Error message') + self.syslog_logger.log_message('critical', 'Critical message') + +if __name__ == '__main__': + unittest.main() From 46f4eadc541c5ee6bc5346e8feb03cc848a17280 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 28 May 2010 02:11:01 +0000 Subject: [PATCH 03/66] Eliminate a superfluous condition select sentense git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@1956 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/log.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index 2b95a35e50..bf239cde22 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -171,10 +171,8 @@ class ModuleLogger(logging.getLoggerClass()): self.addHandler(self.syslog_handler) def update_rotate_handler(self, log_file, max_bytes, backup_count): - # If logFile was specified - if (self.rotating_handler not in self.handlers): - pass - else: + if (self.rotating_handler in self.handlers): + # If logFile was specified if(log_file != 0 and log_file != ''): self.rotating_handler.update_config(log_file, max_bytes, backup_count) else: From c37b820bd92179d515b37b03dbf7249244e1178b Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 28 May 2010 07:17:21 +0000 Subject: [PATCH 04/66] Modified comments style and added IOError exception handle sentences. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@1962 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/log.py | 191 ++++++++++++++--------- src/lib/python/isc/log/tests/log_test.py | 15 ++ 2 files changed, 132 insertions(+), 74 deletions(-) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index bf239cde22..721e9cef8b 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -13,14 +13,20 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +""" +This module is to convert python logging module over +to log4python. +Copyright (C) 2010 Internet Systems Consortium. +To use, simply 'import isc.log.log' and log away! +""" import os import syslog import logging import logging.handlers -######################################################################### -# LEVELS: logging levels mapping -######################################################################### +""" +LEVELS: logging levels mapping +""" LEVELS = {'debug' : logging.DEBUG, 'info' : logging.INFO, 'warning' : logging.WARNING, @@ -29,72 +35,55 @@ LEVELS = {'debug' : logging.DEBUG, formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") time_formatter = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") -######################################################################### -# NullHandler: define a do-nothing handler -######################################################################### -class NullHandler(logging.Handler): - def emit(self, record): - pass -######################################################################### -# RotatingFileHandler: replace RotatingFileHandler with a custom handler -######################################################################### class RotatingFileHandler(logging.handlers.RotatingFileHandler): - - def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None): - logging.handlers.RotatingFileHandler.__init__(self, filename, mode, - maxBytes, backupCount, - encoding) - ##################################################################### - # shouldRollover - # Rewrite RotatingFileHandler.shouldRollover. - # If the log file is deleted, a new file will be created. - ##################################################################### + """ + RotatingFileHandler: replace RotatingFileHandler with a custom handler + """ def shouldRollover(self, record): - if self.stream is None: # delay was set... - self.stream = self._open() - - dfn = self.baseFilename # Is log file exist? - if not os.path.exists(dfn): + """ + Rewrite RotatingFileHandler.shouldRollover. + + If the log file is deleted at run-time, a new file will be created. + """ + dfn = self.baseFilename + if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? self.stream.close() self.stream = self._open() + super(RotatingFileHandler, self).shouldRollover(record) - if self.maxBytes > 0: # are we rolling over? - msg = "%s\n" % self.format(record) - self.stream.seek(0, 2) #due to non-posix-compliant Windows feature - if self.stream.tell() + len(msg) >= self.maxBytes: - return 1 - return 0 - - ###################################################################### - # handleError - # Rewrite RotatingFileHandler.handleError. - # If raiseExceptions is false, exceptions get silently ignored. - ###################################################################### - def handleError(self, record): - pass - - ###################################################################### - # update_config - # update RotatingFileHandler configuration - # input: - # new log file name - # max backup count - # predetermined log file size - ###################################################################### def update_config(self, file_name, backup_count, max_bytes): + """ + Update RotatingFileHandler configuration. + + input: + log file name + max backup count + predetermined log file size + """ + try: + self._open(file_name) + except IOError: + print("The file path is not exist!") + return self.baseFilename = file_name self.maxBytes = max_bytes self.backupCount = backup_count - -######################################################################### -# SLHandler: Replace SysLogHandler with a custom handler due to python3.1 -# SysLogHandler issue : http://bugs.python.org/issue8148 -######################################################################### class SLHandler(logging.Handler): + """ + Replace SysLogHandler with a custom handler + + A handler class which sends formatted logging records to a syslog + server. + """ def __init__(self, ident, logopt=0, facility=syslog.LOG_USER): - logging.Handler.__init__(self) + """ + Initialize a handler. + + If facility is not specified, LOG_USER is used. + """ + super(SLHandler, self).__init__(self) self.ident = ident self.logopt = logopt self.facility = facility @@ -107,12 +96,18 @@ class SLHandler(logging.Handler): } def encodeLevel(self, level): + """ + Encoding the priority. + """ return self.mappings.get(level, syslog.LOG_INFO) - def handleError(self, record): - pass - - def emit(self, record): + def emit(self, record): + """ + Emit a record. + + The record is formatted, and then sent to the syslog server. If + exception information is present, it is NOT sent to the server. + """ syslog.openlog(self.ident, self.logopt, self.facility) msg = self.format(record) prio = self.encodeLevel(record.levelno) @@ -120,73 +115,121 @@ class SLHandler(logging.Handler): syslog.closelog() -######################################################################### -# ModuleLogger: rewrite logging.Logger -######################################################################### class ModuleLogger(logging.getLoggerClass()): + """ + Override logging.logger behaviour + """ def __init__(self, log_name, log_file, severity = 'debug', backup_count = 0, max_bytes = 0, log_to_console = True): + """ + Initializes the logger with some specific parameters + """ logging.Logger.__init__(self, log_name) # Set up a specific logger with our desired output level logLevel = LEVELS.get(severity, logging.NOTSET) self.setLevel(logLevel) - null_handler = NullHandler() - self.addHandler(null_handler) - + self.null_handler = None self.rotating_handler = None self.stream_handler = None self.syslog_handler = None + + self.add_null_handler() self.add_rotate_handler(log_file, max_bytes, backup_count) if log_to_console: self.add_stream_handler() else: self.add_syslog_handler() + def add_null_handler(self): + """ + Add a null handler. + """ + self.null_handler = logging.NullHandler() + self.addHandler(self.null_handler) + def add_rotate_handler(self, log_file, max_bytes, backup_count): - # If logFile was specified + """ + Add a rotate file handler. + + input: + log_file : the location of log file.Handler would't be created is log_file is empty + max_bytes : limit log growth + backup_count : max backup count + """ if(log_file != 0 and log_file != ''): - # Add the log message handler to the logger try: self.rotating_handler = RotatingFileHandler(filename = log_file, maxBytes = max_bytes, backupCount = backup_count) - # add formatter to ch - self.rotating_handler.setFormatter(time_formatter) - self.addHandler(self.rotating_handler) except IOError: - pass + self.rotating_handler = None + return + self.rotating_handler.setFormatter(time_formatter) + self.addHandler(self.rotating_handler) def add_stream_handler(self): + """ + Add a stream handler. + + sys.stderr will be used for logging output. + """ self.stream_handler = logging.StreamHandler() self.stream_handler.setFormatter(time_formatter) self.addHandler(self.stream_handler) def add_syslog_handler(self): - self.syslog_handler = SLHandler('BIND10') + """ + Add a syslog handler. + + If facility is not specified, LOG_USER is used. + The default severity level is INFO. + """ + self.syslog_handler = SLHandler('BIND10', facility=syslog.LOG_USER) self.syslog_handler.setFormatter(formatter) #set syslog handler level info self.syslog_handler.setLevel(logging.INFO) self.addHandler(self.syslog_handler) def update_rotate_handler(self, log_file, max_bytes, backup_count): + """ + If rotate handler has been added to the logger, update its configuration, + else add it to logger. + + If log file is empty, the handler will be removed. + """ if (self.rotating_handler in self.handlers): - # If logFile was specified if(log_file != 0 and log_file != ''): self.rotating_handler.update_config(log_file, max_bytes, backup_count) else: self.rotating_handler.flush() self.rotating_handler.close() self.removeHandler(self.rotating_handler) + else: + self.add_rotate_handler(log_file, max_bytes, backup_count) + def update_config(self, file_name, level, max_bytes, backup_count): + """ + Update logger's configuration. + + We can update logger's log level and its rotate file handler's configuration. + """ logLevel = LEVELS.get(level, logging.NOTSET) if(logLevel != self.getEffectiveLevel()): self.setLevel(logLevel) self.update_rotate_handler(file_name, backup_count, max_bytes) def log_message(self, level, msg, *args, **kwargs): + """ + Log 'msg % args' with the integer severity 'level'. + + To pass exception information, use the keyword argument exc_info with + a true value, e.g. + + logger.log_message('info', "We have a %s", "mysterious problem", exc_info=1) + """ logLevel = LEVELS.get(level, logging.NOTSET) self.log(logLevel, msg, *args, **kwargs) diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index e5d87280f6..114ae2666b 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -29,10 +29,13 @@ class TestLogging(unittest.TestCase): self.syslog_logger = ModuleLogger('SysLogger', '', 'info', 5, 1024, False) def test_logging_init(self): + self.assertNotEqual(self.file_stream_logger.null_handler, None) self.assertNotEqual(self.file_stream_logger.rotating_handler, None) self.assertNotEqual(self.file_stream_logger.stream_handler, None) self.assertEqual(self.file_stream_logger.syslog_handler, None) + ret = self.file_stream_logger.null_handler in self.file_stream_logger.handlers + self.assertTrue(ret) ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers self.assertTrue(ret) ret = self.file_stream_logger.stream_handler in self.file_stream_logger.handlers @@ -42,9 +45,12 @@ class TestLogging(unittest.TestCase): logLevel = LEVELS.get('debug', logging.NOTSET) self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) + self.assertNotEqual(self.syslog_logger.null_handler, None) self.assertEqual(self.syslog_logger.rotating_handler, None) self.assertEqual(self.syslog_logger.stream_handler, None) self.assertNotEqual(self.syslog_logger.syslog_handler, None) + ret = self.syslog_logger.null_handler in self.syslog_logger.handlers + self.assertTrue(ret) ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers self.assertFalse(ret) ret = self.syslog_logger.stream_handler in self.syslog_logger.handlers @@ -55,6 +61,15 @@ class TestLogging(unittest.TestCase): logLevel = LEVELS.get('info', logging.NOTSET) self.assertEqual(self.syslog_logger.getEffectiveLevel(), logLevel) + def test_add_null_handler(self): + if(self.syslog_logger.null_handler in self.syslog_logger.handlers): + self.syslog_logger.removeHandler(self.syslog_logger.null_handler) + + self.syslog_logger.add_null_handler() + ret = self.syslog_logger.null_handler in self.syslog_logger.handlers + self.assertTrue(ret) + + def test_add_rotate_handler(self): if(self.syslog_logger.rotating_handler in self.syslog_logger.handlers): self.syslog_logger.removeHandler(self.syslog_logger.rotating_handler) From 8cd3eaf955e2eb3e319983edb6cee058d0d38b12 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 28 May 2010 08:28:59 +0000 Subject: [PATCH 05/66] Modified exception handler git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@1963 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/log.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index 721e9cef8b..a255f366e5 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -56,19 +56,17 @@ class RotatingFileHandler(logging.handlers.RotatingFileHandler): """ Update RotatingFileHandler configuration. + If the file path is not exists, we will use the old configuration. input: log file name max backup count predetermined log file size """ - try: - self._open(file_name) - except IOError: - print("The file path is not exist!") - return - self.baseFilename = file_name - self.maxBytes = max_bytes - self.backupCount = backup_count + dir = os.path.split(file_name) + if(os.path.exists(dir[0])): + self.baseFilename = file_name + self.maxBytes = max_bytes + self.backupCount = backup_count class SLHandler(logging.Handler): """ @@ -194,8 +192,8 @@ class ModuleLogger(logging.getLoggerClass()): def update_rotate_handler(self, log_file, max_bytes, backup_count): """ - If rotate handler has been added to the logger, update its configuration, - else add it to logger. + If the rotate handler has been added to the logger, update its configuration, + else add it to the logger. If log file is empty, the handler will be removed. """ From e50d232affede6f1dbb192f7bb6d304ccffa28cd Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 28 May 2010 15:02:40 +0000 Subject: [PATCH 06/66] Fixed rotate file handler issue. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@1966 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.py.in | 2 +- src/lib/python/isc/log/log.py | 43 ++++++++++++++---------- src/lib/python/isc/log/tests/log_test.py | 20 +++++++---- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 435b2239aa..d36418bac1 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -380,7 +380,7 @@ class XfroutServer: if self._log: self._log.update_config(self._config_data.get('log_file'), self._config_data.get('severity'), - self._config_data.get('max_bytes'), self._config_data.get('versions')) + self._config_data.get('versions'), self._config_data.get('max_bytes')) if self._unix_socket_server: self._unix_socket_server.update_config_data(self._config_data) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index a255f366e5..152329c87a 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -50,13 +50,13 @@ class RotatingFileHandler(logging.handlers.RotatingFileHandler): if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? self.stream.close() self.stream = self._open() - super(RotatingFileHandler, self).shouldRollover(record) - + return super(RotatingFileHandler, self).shouldRollover(record) + def update_config(self, file_name, backup_count, max_bytes): """ Update RotatingFileHandler configuration. - If the file path is not exists, we will use the old configuration. + If the file path is not exist, we will use the old log file. input: log file name max backup count @@ -65,8 +65,8 @@ class RotatingFileHandler(logging.handlers.RotatingFileHandler): dir = os.path.split(file_name) if(os.path.exists(dir[0])): self.baseFilename = file_name - self.maxBytes = max_bytes - self.backupCount = backup_count + self.maxBytes = max_bytes + self.backupCount = backup_count class SLHandler(logging.Handler): """ @@ -122,8 +122,11 @@ class ModuleLogger(logging.getLoggerClass()): log_to_console = True): """ Initializes the logger with some specific parameters + + If log_to_console is Ture, stream handler will be used; + else syslog handler will be used. """ - logging.Logger.__init__(self, log_name) + super(ModuleLogger, self).__init__(log_name) # Set up a specific logger with our desired output level logLevel = LEVELS.get(severity, logging.NOTSET) @@ -135,7 +138,7 @@ class ModuleLogger(logging.getLoggerClass()): self.syslog_handler = None self.add_null_handler() - self.add_rotate_handler(log_file, max_bytes, backup_count) + self.add_rotate_handler(log_file, backup_count, max_bytes) if log_to_console: self.add_stream_handler() else: @@ -148,18 +151,20 @@ class ModuleLogger(logging.getLoggerClass()): self.null_handler = logging.NullHandler() self.addHandler(self.null_handler) - def add_rotate_handler(self, log_file, max_bytes, backup_count): + def add_rotate_handler(self, log_file, backup_count, max_bytes): """ Add a rotate file handler. input: - log_file : the location of log file.Handler would't be created is log_file is empty + log_file : the location of log file. Handler wouldn't be created + if log_file is not specified max_bytes : limit log growth backup_count : max backup count """ if(log_file != 0 and log_file != ''): try: - self.rotating_handler = RotatingFileHandler(filename = log_file, maxBytes = max_bytes, + self.rotating_handler = RotatingFileHandler(filename = log_file, + maxBytes = max_bytes, backupCount = backup_count) except IOError: self.rotating_handler = None @@ -186,29 +191,31 @@ class ModuleLogger(logging.getLoggerClass()): """ self.syslog_handler = SLHandler('BIND10', facility=syslog.LOG_USER) self.syslog_handler.setFormatter(formatter) - #set syslog handler level info + #set syslog handler severity level INFO self.syslog_handler.setLevel(logging.INFO) self.addHandler(self.syslog_handler) - def update_rotate_handler(self, log_file, max_bytes, backup_count): + def update_rotate_handler(self, log_file, backup_count, max_bytes): """ - If the rotate handler has been added to the logger, update its configuration, - else add it to the logger. + If the rotate file handler has been added to the logger, update its + configuration, or add it to the logger. - If log file is empty, the handler will be removed. """ if (self.rotating_handler in self.handlers): if(log_file != 0 and log_file != ''): - self.rotating_handler.update_config(log_file, max_bytes, backup_count) + self.rotating_handler.update_config(log_file, backup_count, max_bytes) else: + """ + If log file is empty, the handler will be removed. + """ self.rotating_handler.flush() self.rotating_handler.close() self.removeHandler(self.rotating_handler) else: - self.add_rotate_handler(log_file, max_bytes, backup_count) + self.add_rotate_handler(log_file, backup_count, max_bytes) - def update_config(self, file_name, level, max_bytes, backup_count): + def update_config(self, file_name, level, backup_count, max_bytes): """ Update logger's configuration. diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index 114ae2666b..109d2cc98a 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -5,7 +5,8 @@ import os class TestRotateFileHandler(unittest.TestCase): def setUp(self): - self.handler = RotatingFileHandler('/var/log/rotate_file_handler.log', 1024, 5) + self.handler = RotatingFileHandler(filename = '/var/log/rotate_file_handler.log', + maxBytes = 1024, backupCount = 5) def test_shouldRollover(self): if(os.path.exists('/var/log/rotate_file_handler.log')): @@ -15,10 +16,15 @@ class TestRotateFileHandler(unittest.TestCase): self.assertTrue(os.path.exists('/var/log/rotate_file_handler.log')) def test_update_config(self): - self.handler.update_config('/var/log/rotate_file_handler2.log', 512, 3) + self.handler.update_config('/var/log/rotate_file_handler2.log', 3, 512) self.assertEqual(self.handler.baseFilename, '/var/log/rotate_file_handler2.log') - self.assertEqual(self.handler.maxBytes, 3) - self.assertEqual(self.handler.backupCount, 512) + self.assertEqual(self.handler.maxBytes, 512) + self.assertEqual(self.handler.backupCount, 3) + + self.handler.update_config('/var/ZZZXXX/rotate_file_handler2.log', 4, 1024) + self.assertEqual(self.handler.baseFilename, '/var/log/rotate_file_handler2.log') + self.assertEqual(self.handler.maxBytes, 1024) + self.assertEqual(self.handler.backupCount, 4) class TestLogging(unittest.TestCase): @@ -74,11 +80,11 @@ class TestLogging(unittest.TestCase): if(self.syslog_logger.rotating_handler in self.syslog_logger.handlers): self.syslog_logger.removeHandler(self.syslog_logger.rotating_handler) - self.syslog_logger.add_rotate_handler('', 1024, 5) + self.syslog_logger.add_rotate_handler('', 5, 1024) ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers self.assertFalse(ret) - self.syslog_logger.add_rotate_handler('/var/log/RotateFile.log', 1024, 5) + self.syslog_logger.add_rotate_handler('/var/log/RotateFile.log', 5, 1024) ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers self.assertTrue(ret) @@ -109,7 +115,7 @@ class TestLogging(unittest.TestCase): self.file_stream_logger.update_rotate_handler('/var/log/RotateFile', 4, 1024) ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers - self.assertFalse(ret) + self.assertTrue(ret) def test_update_config(self): self.file_stream_logger.update_config('/var/log/RotateFile','error', 4, 1024) From 5ebd3daa01bfbeac8e6ad54191a50bea21cc486c Mon Sep 17 00:00:00 2001 From: Jerry Date: Mon, 31 May 2010 09:36:27 +0000 Subject: [PATCH 07/66] Add unittest shell script Add __init__ function to RotatingFileHandler class git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2006 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 1 + src/lib/python/isc/log/Makefile.am | 2 ++ src/lib/python/isc/log/log.py | 15 ++++++++------ src/lib/python/isc/log/tests/Makefile.am | 2 +- src/lib/python/isc/log/tests/log_test.in | 26 ++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 src/lib/python/isc/log/tests/log_test.in diff --git a/configure.ac b/configure.ac index c98a08edd2..4653a41399 100644 --- a/configure.ac +++ b/configure.ac @@ -437,6 +437,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py src/lib/config/tests/data_def_unittests_config.h src/lib/python/isc/config/tests/config_test src/lib/python/isc/cc/tests/cc_test + src/lib/python/isc/log/tests/log_test src/lib/dns/gen-rdatacode.py src/lib/dns/tests/testdata/gen-wiredata.py ], [ diff --git a/src/lib/python/isc/log/Makefile.am b/src/lib/python/isc/log/Makefile.am index 0fddc6378f..301dc6b2c8 100644 --- a/src/lib/python/isc/log/Makefile.am +++ b/src/lib/python/isc/log/Makefile.am @@ -4,3 +4,5 @@ python_PYTHON = __init__.py log.py pythondir = $(pyexecdir)/isc/log +pytest: + $(SHELL) tests/log_test diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index 152329c87a..e04afd65e0 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -37,6 +37,10 @@ formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") time_formatter = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") class RotatingFileHandler(logging.handlers.RotatingFileHandler): + + def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0): + super(RotatingFileHandler, self).__init__(filename, mode, maxBytes, + backupCount, encoding, delay) """ RotatingFileHandler: replace RotatingFileHandler with a custom handler """ @@ -44,7 +48,7 @@ class RotatingFileHandler(logging.handlers.RotatingFileHandler): """ Rewrite RotatingFileHandler.shouldRollover. - If the log file is deleted at run-time, a new file will be created. + If the log file is deleted at runtime, a new file will be created. """ dfn = self.baseFilename if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? @@ -81,7 +85,7 @@ class SLHandler(logging.Handler): If facility is not specified, LOG_USER is used. """ - super(SLHandler, self).__init__(self) + super(SLHandler, self).__init__() self.ident = ident self.logopt = logopt self.facility = facility @@ -118,8 +122,8 @@ class ModuleLogger(logging.getLoggerClass()): Override logging.logger behaviour """ def __init__(self, log_name, log_file, - severity = 'debug', backup_count = 0, max_bytes = 0, - log_to_console = True): + severity='debug', backup_count=0, max_bytes=0, + log_to_console=True): """ Initializes the logger with some specific parameters @@ -164,8 +168,7 @@ class ModuleLogger(logging.getLoggerClass()): if(log_file != 0 and log_file != ''): try: self.rotating_handler = RotatingFileHandler(filename = log_file, - maxBytes = max_bytes, - backupCount = backup_count) + maxBytes = max_bytes, backupCount = backup_count) except IOError: self.rotating_handler = None return diff --git a/src/lib/python/isc/log/tests/Makefile.am b/src/lib/python/isc/log/tests/Makefile.am index 8dad207ca6..82fa1ed65b 100644 --- a/src/lib/python/isc/log/tests/Makefile.am +++ b/src/lib/python/isc/log/tests/Makefile.am @@ -7,6 +7,6 @@ PYCOVERAGE = $(PYTHON) check-local: for pytest in $(PYTESTS) ; do \ echo Running test: $$pytest ; \ - env PYTHONPATH=$(abs_top_srcdir)/src/lib/python \ + env PYTHONPATH=$(abs_top_srcdir)/src/lib/python::$(abs_top_builddir)/src/lib/python/isc/log \ $(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \ done diff --git a/src/lib/python/isc/log/tests/log_test.in b/src/lib/python/isc/log/tests/log_test.in new file mode 100644 index 0000000000..099bf197a1 --- /dev/null +++ b/src/lib/python/isc/log/tests/log_test.in @@ -0,0 +1,26 @@ +#! /bin/sh + +# Copyright (C) 2010 Internet Systems Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} +export PYTHON_EXEC + +TEST_PATH=@abs_top_srcdir@/src/lib/python/isc/log/tests +PYTHONPATH=@abs_top_srcdir@/src/lib/python +export PYTHONPATH + +cd ${TEST_PATH} +exec ${PYTHON_EXEC} -O log_test.py $* From aeeb89b2950a54265fb72edb92b6b92d31a6134d Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 3 Jun 2010 07:38:49 +0000 Subject: [PATCH 08/66] Python coding style fix: -block comments style -class and variable naming Modified unittest to enhance readability. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2071 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.py.in | 16 +- src/lib/python/isc/log/log.py | 214 +++++++++++------------ src/lib/python/isc/log/tests/log_test.py | 155 ++++++++-------- 3 files changed, 190 insertions(+), 195 deletions(-) diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index d36418bac1..983233cd88 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -298,7 +298,6 @@ class UnixSockServer(ThreadingUnixStreamServer): try: os.unlink(self._sock_file) except: - #pass self._log.log_message('error', 'OS unlink sock file exception while shutting down') def update_config_data(self, new_config): @@ -353,7 +352,7 @@ class XfroutServer: self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler) self._config_data = self._cc.get_full_config() self._cc.start() - self._log = isc.log.ModuleLogger(self._config_data.get('log_name'), self._config_data.get('log_file'), + self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'), self._config_data.get('severity'), self._config_data.get('versions'), self._config_data.get('max_bytes'), True) self._start_xfr_query_listener() @@ -379,8 +378,7 @@ class XfroutServer: self._config_data[key] = new_config[key] if self._log: - self._log.update_config(self._config_data.get('log_file'), self._config_data.get('severity'), - self._config_data.get('versions'), self._config_data.get('max_bytes')) + self._log.update_config(new_config) if self._unix_socket_server: self._unix_socket_server.update_config_data(self._config_data) @@ -408,7 +406,7 @@ class XfroutServer: def command_handler(self, cmd, args): if cmd == "shutdown": if verbose_mode: - log_msg("Received shutdown command") + self._log.log_message("info", "Received shutdown command") self.shutdown() answer = create_answer(0) else: @@ -449,12 +447,12 @@ if '__main__' == __name__: xfrout_server = XfroutServer() xfrout_server.run() except KeyboardInterrupt: - print("[b10-xfrout] exit xfrout process") + sys.stderr.write("[b10-xfrout] exit xfrout process") except SessionError as e: - print('[b10-xfrout] Error creating xfrout, ' - 'is the command channel daemon running?' ) + sys.stderr.write("[b10-xfrout] Error creating xfrout," + "is the command channel daemon running?") except ModuleCCSessionError as e: - print('[b10-xfrout] exit xfrout process:', e) + sys.stderr.write("info", '[b10-xfrout] exit xfrout process:', e) if xfrout_server: xfrout_server.shutdown() diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index e04afd65e0..e9e0b3b66e 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -13,8 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -""" -This module is to convert python logging module over +"""This module is to convert python logging module over to log4python. Copyright (C) 2010 Internet Systems Consortium. To use, simply 'import isc.log.log' and log away! @@ -24,8 +23,7 @@ import syslog import logging import logging.handlers -""" -LEVELS: logging levels mapping +"""LEVELS: logging levels mapping """ LEVELS = {'debug' : logging.DEBUG, 'info' : logging.INFO, @@ -33,32 +31,29 @@ LEVELS = {'debug' : logging.DEBUG, 'error' : logging.ERROR, 'critical' : logging.CRITICAL} -formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s") -time_formatter = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") +FORMATTER = logging.Formatter("%(name)s: %(levelname)s: %(message)s") +TIME_FORMATTER = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") -class RotatingFileHandler(logging.handlers.RotatingFileHandler): +class NSFileLogHandler(logging.handlers.RotatingFileHandler): + """RotatingFileHandler: replace RotatingFileHandler with a custom handler""" def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0): - super(RotatingFileHandler, self).__init__(filename, mode, maxBytes, - backupCount, encoding, delay) - """ - RotatingFileHandler: replace RotatingFileHandler with a custom handler - """ + super(NSFileLogHandler, self).__init__(filename, mode, maxBytes, + backupCount, encoding, delay) + def shouldRollover(self, record): - """ - Rewrite RotatingFileHandler.shouldRollover. + """Rewrite RotatingFileHandler.shouldRollover. - If the log file is deleted at runtime, a new file will be created. + If the log file is deleted at runtime, a new file will be created. """ dfn = self.baseFilename if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? self.stream.close() self.stream = self._open() - return super(RotatingFileHandler, self).shouldRollover(record) + return super(NSFileLogHandler, self).shouldRollover(record) def update_config(self, file_name, backup_count, max_bytes): - """ - Update RotatingFileHandler configuration. + """Update RotatingFileHandler configuration. If the file path is not exist, we will use the old log file. input: @@ -72,24 +67,22 @@ class RotatingFileHandler(logging.handlers.RotatingFileHandler): self.maxBytes = max_bytes self.backupCount = backup_count -class SLHandler(logging.Handler): - """ - Replace SysLogHandler with a custom handler +class NSSysLogHandler(logging.Handler): + """Replace SysLogHandler with a custom handler A handler class which sends formatted logging records to a syslog - server. + server. """ def __init__(self, ident, logopt=0, facility=syslog.LOG_USER): - """ - Initialize a handler. + """Initialize a handler. If facility is not specified, LOG_USER is used. """ - super(SLHandler, self).__init__() - self.ident = ident - self.logopt = logopt - self.facility = facility - self.mappings = { + super(NSSysLogHandler, self).__init__() + self._ident = ident + self._logopt = logopt + self._facility = facility + self._mappings = { logging.DEBUG: syslog.LOG_DEBUG, logging.INFO: syslog.LOG_INFO, logging.WARNING: syslog.LOG_WARNING, @@ -97,146 +90,149 @@ class SLHandler(logging.Handler): logging.CRITICAL: syslog.LOG_CRIT, } - def encodeLevel(self, level): - """ - Encoding the priority. - """ - return self.mappings.get(level, syslog.LOG_INFO) + def _encodeLevel(self, level): + """Encoding the priority.""" + return self._mappings.get(level, syslog.LOG_INFO) def emit(self, record): - """ - Emit a record. + """Emit a record. The record is formatted, and then sent to the syslog server. If exception information is present, it is NOT sent to the server. """ - syslog.openlog(self.ident, self.logopt, self.facility) + syslog.openlog(self._ident, self._logopt, self._facility) msg = self.format(record) - prio = self.encodeLevel(record.levelno) + prio = self._encodeLevel(record.levelno) syslog.syslog(prio, msg) syslog.closelog() -class ModuleLogger(logging.getLoggerClass()): - """ - Override logging.logger behaviour - """ - def __init__(self, log_name, log_file, - severity='debug', backup_count=0, max_bytes=0, - log_to_console=True): - """ - Initializes the logger with some specific parameters +class NSLogger(logging.getLoggerClass()): + """Override logging.logger behaviour.""" + def __init__(self, log_name, log_file, severity='debug', versions=0, + max_bytes=0, log_to_console=True): + """Initializes the logger with some specific parameters - If log_to_console is Ture, stream handler will be used; + If log_to_console is True, stream handler will be used; else syslog handler will be used. + + To disable file handler, set log_file = ''. """ - super(ModuleLogger, self).__init__(log_name) + self._log_name = log_name + self._log_file = log_file + self._severity = severity + self._versions = versions + self._max_bytes = max_bytes + + super(NSLogger, self).__init__(self._log_name) # Set up a specific logger with our desired output level - logLevel = LEVELS.get(severity, logging.NOTSET) + logLevel = LEVELS.get(self._severity, logging.NOTSET) self.setLevel(logLevel) - - self.null_handler = None - self.rotating_handler = None - self.stream_handler = None - self.syslog_handler = None - self.add_null_handler() - self.add_rotate_handler(log_file, backup_count, max_bytes) + self._file_handler = None + self._stream_handler = None + self._syslog_handler = None + + self._add_rotate_handler(self._log_file, self._versions, self._max_bytes) if log_to_console: - self.add_stream_handler() + self._add_stream_handler() else: - self.add_syslog_handler() + self._add_syslog_handler() - def add_null_handler(self): - """ - Add a null handler. - """ - self.null_handler = logging.NullHandler() - self.addHandler(self.null_handler) - - def add_rotate_handler(self, log_file, backup_count, max_bytes): - """ - Add a rotate file handler. + def _add_rotate_handler(self, log_file, backup_count, max_bytes): + """Add a rotate file handler. input: log_file : the location of log file. Handler wouldn't be created - if log_file is not specified + if log_file='' max_bytes : limit log growth backup_count : max backup count """ if(log_file != 0 and log_file != ''): try: - self.rotating_handler = RotatingFileHandler(filename = log_file, - maxBytes = max_bytes, backupCount = backup_count) + self._file_handler = NSFileLogHandler(filename = log_file, + maxBytes = max_bytes, backupCount = backup_count) except IOError: - self.rotating_handler = None + self._file_handler = None return - self.rotating_handler.setFormatter(time_formatter) - self.addHandler(self.rotating_handler) + self._file_handler.setFormatter(TIME_FORMATTER) + self.addHandler(self._file_handler) - def add_stream_handler(self): - """ - Add a stream handler. + def _add_stream_handler(self): + """Add a stream handler. sys.stderr will be used for logging output. """ - self.stream_handler = logging.StreamHandler() - self.stream_handler.setFormatter(time_formatter) - self.addHandler(self.stream_handler) + self._stream_handler = logging.StreamHandler() + self._stream_handler.setFormatter(TIME_FORMATTER) + self.addHandler(self._stream_handler) - def add_syslog_handler(self): - """ - Add a syslog handler. + def _add_syslog_handler(self, facility=syslog.LOG_USER): + """Add a syslog handler. If facility is not specified, LOG_USER is used. The default severity level is INFO. """ - self.syslog_handler = SLHandler('BIND10', facility=syslog.LOG_USER) - self.syslog_handler.setFormatter(formatter) + self._syslog_handler = NSSysLogHandler('BIND10', facility) + self._syslog_handler.setFormatter(FORMATTER) #set syslog handler severity level INFO - self.syslog_handler.setLevel(logging.INFO) - self.addHandler(self.syslog_handler) + self._syslog_handler.setLevel(logging.INFO) + self.addHandler(self._syslog_handler) - def update_rotate_handler(self, log_file, backup_count, max_bytes): - """ - If the rotate file handler has been added to the logger, update its + def _update_rotate_handler(self, log_file, backup_count, max_bytes): + """If the rotate file handler has been added to the logger, update its configuration, or add it to the logger. - """ - if (self.rotating_handler in self.handlers): + if (self._file_handler in self.handlers): if(log_file != 0 and log_file != ''): - self.rotating_handler.update_config(log_file, backup_count, max_bytes) + self._file_handler.update_config(log_file, backup_count, max_bytes) else: - """ - If log file is empty, the handler will be removed. - """ - self.rotating_handler.flush() - self.rotating_handler.close() - self.removeHandler(self.rotating_handler) + """If log file is empty, the handler will be removed.""" + self._file_handler.flush() + self._file_handler.close() + self.removeHandler(self._file_handler) else: - self.add_rotate_handler(log_file, backup_count, max_bytes) + self._add_rotate_handler(log_file, backup_count, max_bytes) + def _get_config(self, config_data): + """Get config data from module configration""" + + log_file_str = config_data.get('log_file') + if(log_file_str): + self._log_file = log_file_str + + severity_str = config_data.get('severity') + if(severity_str): + self._severity = severity_str - def update_config(self, file_name, level, backup_count, max_bytes): - """ - Update logger's configuration. + versions_str = config_data.get('versions') + if(versions_str): + self._versions = int(versions_str) + + max_bytes_str = config_data.get('max_bytes') + if(max_bytes_str): + self._max_bytes = int(max_bytes_str) + + def update_config(self, config_data): + """Update logger's configuration. We can update logger's log level and its rotate file handler's configuration. """ - logLevel = LEVELS.get(level, logging.NOTSET) + self._get_config(config_data) + + logLevel = LEVELS.get(self._severity, logging.NOTSET) if(logLevel != self.getEffectiveLevel()): self.setLevel(logLevel) - self.update_rotate_handler(file_name, backup_count, max_bytes) + self._update_rotate_handler(self._log_file, self._versions, self._max_bytes) def log_message(self, level, msg, *args, **kwargs): - """ - Log 'msg % args' with the integer severity 'level'. + """Log 'msg % args' with the integer severity 'level'. To pass exception information, use the keyword argument exc_info with a true value, e.g. - logger.log_message('info', "We have a %s", "mysterious problem", exc_info=1) + logger.log_message('info', "We have a %s", "mysterious problem"). """ logLevel = LEVELS.get(level, logging.NOTSET) self.log(logLevel, msg, *args, **kwargs) diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index 109d2cc98a..912a58f48d 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -1,142 +1,143 @@ from isc.log.log import * import unittest import os +import sys + +FILE_LOG1 = '/tmp/b10_file1.log' +FILE_LOG2 = '/tmp/b10_file2.log' +FILE_LOG3 = '/tmp/ZZZZ/b10_file2.log' + +FILE_STREAM_LOG1 = '/tmp/b10_file_stream1.log' +FILE_STREAM_LOG2 = '/tmp/b10_file_stream2.log' +FILE_STREAM_LOG3 = '/tmp/b10_file_stream2.log' + class TestRotateFileHandler(unittest.TestCase): def setUp(self): - self.handler = RotatingFileHandler(filename = '/var/log/rotate_file_handler.log', - maxBytes = 1024, backupCount = 5) + self.handler = NSFileLogHandler(filename = FILE_LOG1, maxBytes = 1024, backupCount = 5) def test_shouldRollover(self): - if(os.path.exists('/var/log/rotate_file_handler.log')): - os.remove('/var/log/rotate_file_handler.log') + if(os.path.exists(FILE_LOG1)): + os.remove(FILE_LOG1) record = logging.LogRecord(None, None, "", 0, "rotate file handler", (), None, None) self.handler.shouldRollover(record) - self.assertTrue(os.path.exists('/var/log/rotate_file_handler.log')) + self.assertTrue(os.path.exists(FILE_LOG1)) def test_update_config(self): - self.handler.update_config('/var/log/rotate_file_handler2.log', 3, 512) - self.assertEqual(self.handler.baseFilename, '/var/log/rotate_file_handler2.log') + self.handler.update_config(FILE_LOG2, 3, 512) + self.assertEqual(self.handler.baseFilename, FILE_LOG2) self.assertEqual(self.handler.maxBytes, 512) self.assertEqual(self.handler.backupCount, 3) - self.handler.update_config('/var/ZZZXXX/rotate_file_handler2.log', 4, 1024) - self.assertEqual(self.handler.baseFilename, '/var/log/rotate_file_handler2.log') + self.handler.update_config(FILE_LOG3, 4, 1024) + self.assertEqual(self.handler.baseFilename, FILE_LOG2) self.assertEqual(self.handler.maxBytes, 1024) self.assertEqual(self.handler.backupCount, 4) + def tearDown(self): + self.handler.flush() + self.handler.close() + class TestLogging(unittest.TestCase): - + def setUp(self): - self.file_stream_logger = ModuleLogger('File_Stream_Logger', '/var/log/FileStreamLogger.log', - 'debug', 5, 1024, True) - self.syslog_logger = ModuleLogger('SysLogger', '', 'info', 5, 1024, False) - + self.file_stream_logger = NSLogger('File_Stream_Logger', FILE_STREAM_LOG1, + 'debug', 5, 1024, True) + self.syslog_logger = NSLogger('SysLogger', '', 'info', 5, 1024, False) + def test_logging_init(self): - self.assertNotEqual(self.file_stream_logger.null_handler, None) - self.assertNotEqual(self.file_stream_logger.rotating_handler, None) - self.assertNotEqual(self.file_stream_logger.stream_handler, None) - self.assertEqual(self.file_stream_logger.syslog_handler, None) + self.assertNotEqual(self.file_stream_logger._file_handler, None) + self.assertNotEqual(self.file_stream_logger._stream_handler, None) + self.assertEqual(self.file_stream_logger._syslog_handler, None) - ret = self.file_stream_logger.null_handler in self.file_stream_logger.handlers + ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) - ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + ret = self.file_stream_logger._stream_handler in self.file_stream_logger.handlers self.assertTrue(ret) - ret = self.file_stream_logger.stream_handler in self.file_stream_logger.handlers - self.assertTrue(ret) - ret = self.file_stream_logger.syslog_handler in self.file_stream_logger.handlers + ret = self.file_stream_logger._syslog_handler in self.file_stream_logger.handlers self.assertFalse(ret) logLevel = LEVELS.get('debug', logging.NOTSET) self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) - self.assertNotEqual(self.syslog_logger.null_handler, None) - self.assertEqual(self.syslog_logger.rotating_handler, None) - self.assertEqual(self.syslog_logger.stream_handler, None) - self.assertNotEqual(self.syslog_logger.syslog_handler, None) - ret = self.syslog_logger.null_handler in self.syslog_logger.handlers - self.assertTrue(ret) - ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.assertEqual(self.syslog_logger._file_handler, None) + self.assertEqual(self.syslog_logger._stream_handler, None) + self.assertNotEqual(self.syslog_logger._syslog_handler, None) + ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertFalse(ret) - ret = self.syslog_logger.stream_handler in self.syslog_logger.handlers + ret = self.syslog_logger._stream_handler in self.syslog_logger.handlers self.assertFalse(ret) - ret = self.syslog_logger.syslog_handler in self.syslog_logger.handlers + ret = self.syslog_logger._syslog_handler in self.syslog_logger.handlers self.assertTrue(ret) logLevel = LEVELS.get('info', logging.NOTSET) self.assertEqual(self.syslog_logger.getEffectiveLevel(), logLevel) - def test_add_null_handler(self): - if(self.syslog_logger.null_handler in self.syslog_logger.handlers): - self.syslog_logger.removeHandler(self.syslog_logger.null_handler) - - self.syslog_logger.add_null_handler() - ret = self.syslog_logger.null_handler in self.syslog_logger.handlers - self.assertTrue(ret) - - def test_add_rotate_handler(self): - if(self.syslog_logger.rotating_handler in self.syslog_logger.handlers): - self.syslog_logger.removeHandler(self.syslog_logger.rotating_handler) + if(self.syslog_logger._file_handler in self.syslog_logger.handlers): + self.syslog_logger.removeHandler(self.syslog_logger._file_handler) - self.syslog_logger.add_rotate_handler('', 5, 1024) - ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.syslog_logger._add_rotate_handler('', 5, 1024) + ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertFalse(ret) - self.syslog_logger.add_rotate_handler('/var/log/RotateFile.log', 5, 1024) - ret = self.syslog_logger.rotating_handler in self.syslog_logger.handlers + self.syslog_logger._add_rotate_handler(FILE_STREAM_LOG1, 5, 1024) + ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertTrue(ret) - def test_add_stream_handler(self): - if(self.file_stream_logger.stream_handler in self.file_stream_logger.handlers): - self.file_stream_logger.removeHandler(self.file_stream_logger.stream_handler) + def test_add__stream_handler(self): + if(self.file_stream_logger._stream_handler in self.file_stream_logger.handlers): + self.file_stream_logger.removeHandler(self.file_stream_logger._stream_handler) - self.file_stream_logger.add_stream_handler() - ret = self.file_stream_logger.stream_handler in self.file_stream_logger.handlers + self.file_stream_logger._add_stream_handler() + ret = self.file_stream_logger._stream_handler in self.file_stream_logger.handlers self.assertTrue(ret) def test_add_syslog_handler(self): - if(self.syslog_logger.syslog_handler in self.syslog_logger.handlers): - self.syslog_logger.removeHandler(self.syslog_logger.syslog_handler) + if(self.syslog_logger._syslog_handler in self.syslog_logger.handlers): + self.syslog_logger.removeHandler(self.syslog_logger._syslog_handler) - self.syslog_logger.add_syslog_handler() - ret = self.syslog_logger.syslog_handler in self.syslog_logger.handlers + self.syslog_logger._add_syslog_handler() + ret = self.syslog_logger._syslog_handler in self.syslog_logger.handlers self.assertTrue(ret) def test_update_rotate_handler(self): - self.file_stream_logger.update_rotate_handler('/var/log/RotateFile', 4, 1024) - ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.file_stream_logger._update_rotate_handler(FILE_STREAM_LOG2, 4, 1024) + ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) - self.file_stream_logger.update_rotate_handler('', 5, 1024) - ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.file_stream_logger._update_rotate_handler('', 5, 1024) + ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertFalse(ret) - self.file_stream_logger.update_rotate_handler('/var/log/RotateFile', 4, 1024) - ret = self.file_stream_logger.rotating_handler in self.file_stream_logger.handlers + self.file_stream_logger._update_rotate_handler(FILE_STREAM_LOG1, 4, 1024) + ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) def test_update_config(self): - self.file_stream_logger.update_config('/var/log/RotateFile','error', 4, 1024) + update_config = {'log_file' : FILE_STREAM_LOG1, + 'severity' : 'error', + 'versions' : 4, + 'max_bytes' : 1024} + self.file_stream_logger.update_config(update_config) logLevel = LEVELS.get('error', logging.NOTSET) self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) def test_log_message(self): - print ('\r') - #output log message to stderr and file - self.file_stream_logger.log_message('debug', 'Debug message') - self.file_stream_logger.log_message('info', 'Info message') - self.file_stream_logger.log_message('warning', 'Warning message') - self.file_stream_logger.log_message('error', 'Error message') - self.file_stream_logger.log_message('critical', 'Critical message') - - #output log message to syslog - self.syslog_logger.log_message('debug', 'Debug message') - self.syslog_logger.log_message('info', 'Info message') - self.syslog_logger.log_message('warning', 'Warning message') - self.syslog_logger.log_message('error', 'Error message') - self.syslog_logger.log_message('critical', 'Critical message') + update_config = {'log_file' : FILE_STREAM_LOG3, + 'severity' : 'critical', + 'versions' : 4, + 'max_bytes' : 1024} + self.file_stream_logger.update_config(update_config) + self.file_stream_logger.log_message('debug', 'debug message') + self.file_stream_logger.log_message('info', 'info message') + self.file_stream_logger.log_message('warning', 'warning message') + self.file_stream_logger.log_message('error', 'error message') + self.assertFalse(os.path.exists(FILE_STREAM_LOG3)) + + def tearDown(self): + pass if __name__ == '__main__': unittest.main() From 96963fc84855f4f6e21f9be4f68ef58c88dc3780 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 8 Jun 2010 02:34:54 +0000 Subject: [PATCH 09/66] Refine python logging test cases git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2087 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.py.in | 44 +++++++++++++----------- src/bin/xfrout/xfrout.spec.pre.in | 2 +- src/lib/python/isc/log/tests/log_test.py | 10 +++--- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 983233cd88..33050a2967 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -48,13 +48,17 @@ SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec" UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn" MAX_TRANSFERS_OUT = 10 -verbose_mode = False +VERBOSE_MODE = False class XfroutException(Exception): pass class XfroutSession(BaseRequestHandler): + def __init__(self, request, client_address, server, log): + BaseRequestHandler.__init__(self, request, client_address, server) + self._log = log + def handle(self): fd = recv_fd(self.request.fileno()) if fd < 0: @@ -66,11 +70,13 @@ class XfroutSession(BaseRequestHandler): try: self.dns_xfrout_start(sock, msgdata) except Exception as e: - if verbose_mode: - self.log_msg(str(e)) + self._log.log_message("error", str(e)) sock.close() + def setLogger(self, logger): + self._log = logger + def _parse_query_message(self, mdata): ''' parse query message to [socket,message]''' #TODO, need to add parseHeader() in case the message header is invalid @@ -78,8 +84,7 @@ class XfroutSession(BaseRequestHandler): msg = message(message_mode.PARSE) msg.from_wire(input_buffer(mdata)) except Exception as err: - if verbose_mode: - self.log_msg(str(err)) + self._log.log_message("error", str(err)) return rcode.FORMERR(), None return rcode.NOERROR(), msg @@ -168,16 +173,11 @@ class XfroutSession(BaseRequestHandler): return self. _reply_query_with_error_rcode(msg, sock, rcode_) try: - if verbose_mode: - self.log_msg("transfer of '%s/IN': AXFR started" % zone_name) - + self._log.log_message("info", "transfer of '%s/IN': AXFR started" % zone_name) self._reply_xfrout_query(msg, sock, zone_name) - - if verbose_mode: - self.log_msg("transfer of '%s/IN': AXFR end" % zone_name) + self._log.log_message("info", "transfer of '%s/IN': AXFR end" % zone_name) except Exception as err: - if verbose_mode: - sys.stderr.write(str(err)) + self._log.log_message("error", str(err)) self.server.decrease_transfers_counter() return @@ -291,9 +291,12 @@ class UnixSockServer(ThreadingUnixStreamServer): self._log = log self.update_config_data(config_data) + def finish_request(self, request, client_address): + '''Finish one request by instantiating RequestHandlerClass.''' + self.RequestHandlerClass(request, client_address, self, self._log) def shutdown(self): - self._log.log_message('warning', 'Xfrout process will is shutting down') + self._log.log_message('warning', 'Xfrout process is shutting down!') ThreadingUnixStreamServer.shutdown(self) try: os.unlink(self._sock_file) @@ -303,14 +306,14 @@ class UnixSockServer(ThreadingUnixStreamServer): def update_config_data(self, new_config): '''Apply the new config setting of xfrout module. ''' - self._log.log_message('info', 'update config data start') + self._log.log_message('info', 'update config data start.') self._lock.acquire() self._max_transfers_out = new_config.get('transfers_out') - self._log.log_message('debug', 'max transfer out : %d', self._max_transfers_out) + self._log.log_message('info', 'max transfer out : %d', self._max_transfers_out) self._db_file = new_config.get('db_file') - self._log.log_message('debug', 'db file name : %s', self._db_file) + self._log.log_message('info', 'db file name : %s', self._db_file) self._lock.release() - self._log.log_message('info', 'update config data complete') + self._log.log_message('info', 'update config data complete.') def get_db_file(self): self._lock.acquire() @@ -405,8 +408,7 @@ class XfroutServer: def command_handler(self, cmd, args): if cmd == "shutdown": - if verbose_mode: - self._log.log_message("info", "Received shutdown command") + self._log.log_message("info", "Received shut down command.") self.shutdown() answer = create_answer(0) else: @@ -441,7 +443,7 @@ if '__main__' == __name__: parser = OptionParser() set_cmd_options(parser) (options, args) = parser.parse_args() - verbose_mode = options.verbose + VERBOSE_MODE = options.verbose set_signal_handler() xfrout_server = XfroutServer() diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in index 2b53fc01d7..e33efdb4f3 100644 --- a/src/bin/xfrout/xfrout.spec.pre.in +++ b/src/bin/xfrout/xfrout.spec.pre.in @@ -24,7 +24,7 @@ "item_name": "log_file", "item_type": "string", "item_optional": False, - "item_default": "/var/log/xfrout.log" + "item_default": '@@LOCALSTATEDIR@@/Xfrout.log' }, { "item_name": "severity", diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index 912a58f48d..b513cbdc5b 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -30,10 +30,12 @@ class TestRotateFileHandler(unittest.TestCase): self.assertEqual(self.handler.maxBytes, 512) self.assertEqual(self.handler.backupCount, 3) - self.handler.update_config(FILE_LOG3, 4, 1024) - self.assertEqual(self.handler.baseFilename, FILE_LOG2) - self.assertEqual(self.handler.maxBytes, 1024) - self.assertEqual(self.handler.backupCount, 4) + dir = os.path.split(FILE_LOG3) + if not os.path.exists(dir[0]): + self.handler.update_config(FILE_LOG3, 4, 1024) + self.assertEqual(self.handler.baseFilename, FILE_LOG2) + self.assertEqual(self.handler.maxBytes, 1024) + self.assertEqual(self.handler.backupCount, 4) def tearDown(self): self.handler.flush() From 187844f29a0d39f758c40d57f9a9fb3cbb6315db Mon Sep 17 00:00:00 2001 From: Likun Zhang Date: Thu, 10 Jun 2010 02:13:18 +0000 Subject: [PATCH 10/66] Enable b10-xfrout can be launched in source code tree.(Reviewed by Jelte) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2103 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 5 +++++ src/bin/auth/asio_link.cc | 8 +++++++- src/bin/xfrout/xfrout.py.in | 5 +++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06fc0db75c..8c276b6bbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + 54. [bug] zhanglikun + bin/xfrout: Enable b10-xfrout can be launched in source + code tree. + (Trac #224, svn r2103) + 53. [bug] zhanglikun bin/bindctl: Generate a unique session ID by using socket.gethostname() instead of socket.gethostbyname(), diff --git a/src/bin/auth/asio_link.cc b/src/bin/auth/asio_link.cc index 1c0b8a83c8..15f4cf8172 100644 --- a/src/bin/auth/asio_link.cc +++ b/src/bin/auth/asio_link.cc @@ -68,7 +68,13 @@ void dispatch_axfr_query(const int tcp_sock, char const axfr_query[], const uint16_t query_len) { - string path(UNIX_SOCKET_FILE); + string path; + if (getenv("B10_FROM_BUILD")) { + path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn"; + } else { + path = UNIX_SOCKET_FILE; + } + XfroutClient xfr_client(path); try { xfr_client.connect(); diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index d0580553ab..7a659ffeb7 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -40,13 +40,14 @@ except ImportError as e: if "B10_FROM_BUILD" in os.environ: SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/xfrout" + UNIX_SOCKET_FILE= os.environ["B10_FROM_BUILD"] + "/auth_xfrout_conn" else: PREFIX = "@prefix@" DATAROOTDIR = "@datarootdir@" SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX) -SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec" -UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn" + UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn" +SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec" MAX_TRANSFERS_OUT = 10 verbose_mode = False From 81a9d98f0d8929844db5fe1ef50ec300b5dec2fc Mon Sep 17 00:00:00 2001 From: "Jeremy C. Reed" Date: Thu, 10 Jun 2010 15:41:48 +0000 Subject: [PATCH 11/66] Check for pkg-config itself so we don't try the m4 macro without pkg-config. This helps workaround problem noted on bind10-users list last week and this was discussed on jabber last week. Note that if the m4 macro doesn't exist. Then even if pkg-config is installed later, the configure script will still fail. autoconf will need to be ran again. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2106 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 5a7ac699e3..519d483ff3 100644 --- a/configure.ac +++ b/configure.ac @@ -310,6 +310,11 @@ AC_SUBST(GTEST_INCLUDES) AC_SUBST(GTEST_LDFLAGS) AC_SUBST(GTEST_LDADD) +dnl check for pkg-config itself so we don't try the m4 macro without pkg-config +AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes, no) +if test "x$HAVE_PKG_CONFIG" = "xno" ; then + AC_MSG_ERROR(Please install pkg-config) +fi PKG_CHECK_MODULES(SQLITE, sqlite3 >= 3.3.9, enable_features="$enable_features SQLite3") # I can't get some of the #include right without this From 4c2fafb0ee82482a801175f4181ac57592dea60b Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 15 Jun 2010 19:01:38 +0000 Subject: [PATCH 12/66] removed a redundant white space at EOL (trivial style fix, skipping review) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2117 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/bindctl/bindcmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/bindctl/bindcmd.py b/src/bin/bindctl/bindcmd.py index 138024f05f..7c87d46d6b 100644 --- a/src/bin/bindctl/bindcmd.py +++ b/src/bin/bindctl/bindcmd.py @@ -87,7 +87,7 @@ class BindCmdInterpreter(Cmd): '''Generate one session id for the connection. ''' rand = os.urandom(16) now = time.time() - session_id = sha1(("%s%s%s" %(rand, now, + session_id = sha1(("%s%s%s" %(rand, now, socket.gethostname())).encode()) digest = session_id.hexdigest() return digest From 6e04eb7a3746b8cea33e914c79569cabf86d39f0 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 15 Jun 2010 21:11:13 +0000 Subject: [PATCH 14/66] removed an awkward colon from a log message. okayed on jabber. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2119 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/cmdctl/cmdctl.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in index 4e5a73351d..1ca0c37b97 100644 --- a/src/bin/cmdctl/cmdctl.py.in +++ b/src/bin/cmdctl/cmdctl.py.in @@ -416,7 +416,7 @@ def set_signal_handler(): def run(addr = 'localhost', port = 8080, idle_timeout = 1200, verbose = False): ''' Start cmdctl as one https server. ''' if verbose: - sys.stdout.write("[b10-cmdctl] starting on :%s port:%d\n" %(addr, port)) + sys.stdout.write("[b10-cmdctl] starting on %s port:%d\n" %(addr, port)) httpd = SecureHTTPServer((addr, port), SecureHTTPRequestHandler, idle_timeout, verbose) httpd.serve_forever() From ff88bdd4870981b41aa33a7960613d21c52b240c Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 15 Jun 2010 22:03:56 +0000 Subject: [PATCH 15/66] s/libdns/libdns++/ git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac190@2120 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/Makefile.am | 2 +- src/bin/auth/tests/Makefile.am | 2 +- src/bin/host/Makefile.am | 2 +- src/lib/cc/Makefile.am | 2 +- src/lib/datasrc/tests/Makefile.am | 2 +- src/lib/dns/Makefile.am | 49 ++++++++++++++++--------------- src/lib/dns/tests/Makefile.am | 2 +- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am index 4d8400196b..28d2bfc464 100644 --- a/src/bin/auth/Makefile.am +++ b/src/bin/auth/Makefile.am @@ -45,7 +45,7 @@ b10_auth_SOURCES = auth_srv.cc auth_srv.h b10_auth_SOURCES += common.h b10_auth_SOURCES += main.cc b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a -b10_auth_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a +b10_auth_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a b10_auth_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.a b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am index ed9deb552f..3405f43543 100644 --- a/src/bin/auth/tests/Makefile.am +++ b/src/bin/auth/tests/Makefile.am @@ -20,7 +20,7 @@ run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) run_unittests_LDADD = $(GTEST_LDADD) run_unittests_LDADD += $(SQLITE_LIBS) run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a -run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a +run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a diff --git a/src/bin/host/Makefile.am b/src/bin/host/Makefile.am index 39e4b8928b..ac703b42c9 100644 --- a/src/bin/host/Makefile.am +++ b/src/bin/host/Makefile.am @@ -7,7 +7,7 @@ CLEANFILES = *.gcno *.gcda bin_PROGRAMS = host host_SOURCES = host.cc -host_LDADD = $(top_builddir)/src/lib/dns/.libs/libdns.a +host_LDADD = $(top_builddir)/src/lib/dns/.libs/libdns++.a host_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a #man_MANS = host.1 diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index fe61cd25f2..6b6d72bf47 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -28,7 +28,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(PTHREAD_LDFLAGS) run_unittests_LDADD = libcc.a $(GTEST_LDADD) -run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a +run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a endif diff --git a/src/lib/datasrc/tests/Makefile.am b/src/lib/datasrc/tests/Makefile.am index 382e4885ab..a2912b8862 100644 --- a/src/lib/datasrc/tests/Makefile.am +++ b/src/lib/datasrc/tests/Makefile.am @@ -22,7 +22,7 @@ run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) run_unittests_LDADD = $(GTEST_LDADD) run_unittests_LDADD += $(SQLITE_LIBS) run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a -run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a +run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a endif diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index 168714a381..e500a68fbf 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -55,27 +55,27 @@ EXTRA_DIST += rdata/hs_4/a_1.h BUILT_SOURCES = rrclass.h rrtype.h rrparamregistry.cc #TODO: check this###BUILT_SOURCES = rdataclass.h rdataclass.cc -lib_LTLIBRARIES = libdns.la +lib_LTLIBRARIES = libdns++.la -libdns_la_SOURCES = base32.h base32.cc -libdns_la_SOURCES += base64.h base64.cc -libdns_la_SOURCES += buffer.h -libdns_la_SOURCES += dnssectime.h dnssectime.cc -libdns_la_SOURCES += exceptions.h exceptions.cc -libdns_la_SOURCES += hex.h hex.cc -libdns_la_SOURCES += message.h message.cc -libdns_la_SOURCES += messagerenderer.h messagerenderer.cc -libdns_la_SOURCES += name.h name.cc -libdns_la_SOURCES += rdata.h rdata.cc -libdns_la_SOURCES += rrclass.cc -libdns_la_SOURCES += rrparamregistry.h -libdns_la_SOURCES += rrset.h rrset.cc -libdns_la_SOURCES += rrsetlist.h rrsetlist.cc -libdns_la_SOURCES += rrttl.h rrttl.cc -libdns_la_SOURCES += rrtype.cc -libdns_la_SOURCES += question.h question.cc -libdns_la_SOURCES += sha1.h sha1.cc -libdns_la_SOURCES += tsig.h tsig.cc +libdns___la_SOURCES = base32.h base32.cc +libdns___la_SOURCES += base64.h base64.cc +libdns___la_SOURCES += buffer.h +libdns___la_SOURCES += dnssectime.h dnssectime.cc +libdns___la_SOURCES += exceptions.h exceptions.cc +libdns___la_SOURCES += hex.h hex.cc +libdns___la_SOURCES += message.h message.cc +libdns___la_SOURCES += messagerenderer.h messagerenderer.cc +libdns___la_SOURCES += name.h name.cc +libdns___la_SOURCES += rdata.h rdata.cc +libdns___la_SOURCES += rrclass.cc +libdns___la_SOURCES += rrparamregistry.h +libdns___la_SOURCES += rrset.h rrset.cc +libdns___la_SOURCES += rrsetlist.h rrsetlist.cc +libdns___la_SOURCES += rrttl.h rrttl.cc +libdns___la_SOURCES += rrtype.cc +libdns___la_SOURCES += question.h question.cc +libdns___la_SOURCES += sha1.h sha1.cc +libdns___la_SOURCES += tsig.h tsig.cc if HAVE_BOOST_PYTHON # This is a loadable module for python scripts, so we use the prefix "pyexec" @@ -94,12 +94,13 @@ bind10_dns_la_LDFLAGS = $(BOOST_LDFLAGS) $(PYTHON_LDFLAGS) # Python prefers .so, while some OSes (specifically MacOS) use a different # suffix for dynamic objects. -module is necessary to work this around. bind10_dns_la_LDFLAGS += -module -bind10_dns_la_LIBADD = $(top_builddir)/src/lib/dns/libdns.la +bind10_dns_la_LIBADD = $(top_builddir)/src/lib/dns/libdns++.la bind10_dns_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la bind10_dns_la_LIBADD += $(BOOST_PYTHON_LIB) $(PYTHON_LIB) endif -nodist_libdns_la_SOURCES = rdataclass.cc rrclass.h rrtype.h rrparamregistry.cc +nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h +nodist_libdns___la_SOURCES += rrparamregistry.cc rrclass.h: rrclass-placeholder.h rrtype.h: rrtype-placeholder.h @@ -107,8 +108,8 @@ rrparamregistry.cc: rrparamregistry-placeholder.cc rrclass.h rrtype.h rrparamregistry.cc rdataclass.h rdataclass.cc: Makefile ./gen-rdatacode.py -libdns_includedir = $(includedir)/dns -libdns_include_HEADERS = \ +libdns++_includedir = $(includedir)/dns +libdns++_include_HEADERS = \ buffer.h \ dnssectime.h \ exceptions.h \ diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 29a174755b..ab765bc834 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -40,7 +40,7 @@ run_unittests_SOURCES += run_unittests.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) run_unittests_LDADD = $(GTEST_LDADD) -run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a +run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a endif From b9cd36cbf75fda432ce82cf3058c89ef25dff2f6 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Wed, 16 Jun 2010 16:10:49 +0000 Subject: [PATCH 17/66] unit tests for b10-cfgmgr moved a little bit of code into a main() function (instead of calling it directly), for easier testing module magic happening in the test. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac238@2127 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 2 + src/bin/cfgmgr/Makefile.am | 2 + src/bin/cfgmgr/b10-cfgmgr.py.in | 6 +- src/bin/cfgmgr/tests/Makefile.am | 13 +++ src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in | 95 ++++++++++++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/bin/cfgmgr/tests/Makefile.am create mode 100644 src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in diff --git a/configure.ac b/configure.ac index 519d483ff3..e6c7f38c52 100644 --- a/configure.ac +++ b/configure.ac @@ -393,6 +393,7 @@ AC_CONFIG_FILES([Makefile src/bin/bindctl/Makefile src/bin/bindctl/tests/Makefile src/bin/cfgmgr/Makefile + src/bin/cfgmgr/tests/Makefile src/bin/host/Makefile src/bin/loadzone/Makefile src/bin/msgq/Makefile @@ -423,6 +424,7 @@ AC_CONFIG_FILES([Makefile src/lib/xfr/Makefile ]) AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py + src/bin/cfgmgr/tests/b10-cfgmgr_test.py src/bin/cmdctl/cmdctl.py src/bin/cmdctl/run_b10-cmdctl.sh src/bin/cmdctl/tests/cmdctl_test diff --git a/src/bin/cfgmgr/Makefile.am b/src/bin/cfgmgr/Makefile.am index 695d371ff8..b3dffd07ae 100644 --- a/src/bin/cfgmgr/Makefile.am +++ b/src/bin/cfgmgr/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS = tests + pkglibexecdir = $(libexecdir)/@PACKAGE@ pkglibexec_SCRIPTS = b10-cfgmgr diff --git a/src/bin/cfgmgr/b10-cfgmgr.py.in b/src/bin/cfgmgr/b10-cfgmgr.py.in index 563bbcdf7e..1c524c3d55 100644 --- a/src/bin/cfgmgr/b10-cfgmgr.py.in +++ b/src/bin/cfgmgr/b10-cfgmgr.py.in @@ -38,7 +38,8 @@ def signal_handler(signal, frame): if cm: cm.running = False -if __name__ == "__main__": +def main(): + global cm try: cm = ConfigManager(DATA_PATH) signal.signal(signal.SIGINT, signal_handler) @@ -53,3 +54,6 @@ if __name__ == "__main__": print("[b10-cfgmgr] Interrupted, exiting") if cm: cm.write_config() + +if __name__ == "__main__": + main() diff --git a/src/bin/cfgmgr/tests/Makefile.am b/src/bin/cfgmgr/tests/Makefile.am new file mode 100644 index 0000000000..fc71023ef0 --- /dev/null +++ b/src/bin/cfgmgr/tests/Makefile.am @@ -0,0 +1,13 @@ +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: + 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_srcdir)/$$pytest ; \ + done diff --git a/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in new file mode 100644 index 0000000000..81bceee7df --- /dev/null +++ b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in @@ -0,0 +1,95 @@ +# Copyright (C) 2010 Internet Systems Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# $Id: cfgmgr_test.py 2126 2010-06-16 14:40:22Z jelte $ + +# +# Tests for the configuration manager run script +# + +import unittest +import os +import sys + +class MyConfigManager: + def __init__(self, path): + self._path = path + self.read_config_called = False + self.notify_boss_called = False + self.run_called = False + self.write_config_called = False + self.running = True + + def read_config(self): + self.read_config_called = True + + def notify_boss(self): + self.notify_boss_called = True + + def run(self): + self.run_called = True + + def write_config(self): + self.write_config_called = True + +class TestConfigManagerStartup(unittest.TestCase): + def test_cfgmgr(self): + # some creative module use; + # b10-cfgmgr has a hypen, so we use __import__ + # this also gives us the chance to override the imported + # moculde ConfigManager in it. + b = __import__("b10-cfgmgr") + b.ConfigManager = MyConfigManager + + b.main() + + self.assertTrue(b.cm.read_config_called) + self.assertTrue(b.cm.notify_boss_called) + self.assertTrue(b.cm.run_called) + self.assertTrue(b.cm.write_config_called) + + self.assertTrue(b.cm.running) + b.signal_handler(None, None) + self.assertFalse(b.cm.running) + + # TODO: take value from the 'global config module' + # (and rename the .in aay from this file again) + data_path = "@localstatedir@/@PACKAGE@".replace("${prefix}", "@prefix@") + self.assertEqual(data_path, b.DATA_PATH) + + # remove the 'module' again, or later tests may fail + # (if it is already present it won't be loaded again) + sys.modules.pop("b10-cfgmgr") + + def test_cfgmgr_from_source(self): + tmp_env_var = "/just/some/dir" + env_var = None + if "B10_FROM_SOURCE" in os.environ: + env_var = os.environ["B10_FROM_SOURCE"] + + os.environ["B10_FROM_SOURCE"] = tmp_env_var + b = __import__("b10-cfgmgr", globals(), locals()) + b.ConfigManager = MyConfigManager + self.assertEqual(tmp_env_var, b.DATA_PATH) + + if env_var != None: + os.environ["B10_FROM_SOURCE"] = env_var + + sys.modules.pop("b10-cfgmgr") + + +if __name__ == '__main__': + unittest.main() + From 9cd0b5b30143913daa142da692a7836f4ae7f44f Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 17 Jun 2010 00:52:46 +0000 Subject: [PATCH 18/66] propset git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2136 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/cfgmgr/b10-cfgmgr.py.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bin/cfgmgr/b10-cfgmgr.py.in b/src/bin/cfgmgr/b10-cfgmgr.py.in index 563bbcdf7e..24517271cd 100644 --- a/src/bin/cfgmgr/b10-cfgmgr.py.in +++ b/src/bin/cfgmgr/b10-cfgmgr.py.in @@ -15,6 +15,8 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# $Id$ + import sys; sys.path.append ('@@PYTHONPATH@@') from isc.config.cfgmgr import ConfigManager From 17bd03fee44970e0421c473e1856a2a33baec94a Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 17 Jun 2010 06:49:54 +0000 Subject: [PATCH 19/66] -Modified logging formatter -Modified logging configuration names, all of them prefixed with "log_" -Modified Xfrout unittest, add log in __init__() method -Using mkstemp in logging unittest git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2141 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/tests/xfrout_test.py | 8 +-- src/bin/xfrout/xfrout.py.in | 27 +++------ src/bin/xfrout/xfrout.spec.pre.in | 8 +-- src/lib/python/isc/log/log.py | 13 ++-- src/lib/python/isc/log/tests/log_test.py | 77 ++++++++++++++---------- 5 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/bin/xfrout/tests/xfrout_test.py b/src/bin/xfrout/tests/xfrout_test.py index 20ef79b967..47ad618817 100644 --- a/src/bin/xfrout/tests/xfrout_test.py +++ b/src/bin/xfrout/tests/xfrout_test.py @@ -75,7 +75,8 @@ class TestXfroutSession(unittest.TestCase): def setUp(self): request = MySocket(socket.AF_INET,socket.SOCK_STREAM) - self.xfrsess = MyXfroutSession(request, None, None) + self.log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False ) + self.xfrsess = MyXfroutSession(request, None, None, self.log) self.xfrsess.server = Dbserver() self.mdata = b'\xd6=\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\xfc\x00\x01' self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM) @@ -238,10 +239,6 @@ class TestXfroutSession(unittest.TestCase): reply_msg = self.sock.read_msg() self.assertEqual(reply_msg.get_rr_count(section.ANSWER()), 2) - # set event - self.xfrsess.server._shutdown_event.set() - self.assertRaises(XfroutException, self.xfrsess._reply_xfrout_query, self.getmsg(), self.sock, "example.com.") - class MyUnixSockServer(UnixSockServer): def __init__(self): self._lock = threading.Lock() @@ -249,6 +246,7 @@ class MyUnixSockServer(UnixSockServer): self._shutdown_event = threading.Event() self._db_file = "initdb.file" self._max_transfers_out = 10 + self._log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False ) class TestUnixSockServer(unittest.TestCase): def setUp(self): diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 33050a2967..3e4b3ec949 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -50,10 +50,6 @@ UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn" MAX_TRANSFERS_OUT = 10 VERBOSE_MODE = False - -class XfroutException(Exception): pass - - class XfroutSession(BaseRequestHandler): def __init__(self, request, client_address, server, log): BaseRequestHandler.__init__(self, request, client_address, server) @@ -62,7 +58,7 @@ class XfroutSession(BaseRequestHandler): def handle(self): fd = recv_fd(self.request.fileno()) if fd < 0: - raise XfroutException("failed to receive the FD for XFR connection") + self._log.log_message("error", "Failed to receive the FD for XFR connection") data_len = self.request.recv(2) msg_len = struct.unpack('!H', data_len)[0] msgdata = self.request.recv(msg_len) @@ -74,9 +70,6 @@ class XfroutSession(BaseRequestHandler): sock.close() - def setLogger(self, logger): - self._log = logger - def _parse_query_message(self, mdata): ''' parse query message to [socket,message]''' #TODO, need to add parseHeader() in case the message header is invalid @@ -251,7 +244,7 @@ class XfroutSession(BaseRequestHandler): # the message length to know if the rrset has been added sucessfully. for rr_data in sqlite3_ds.get_zone_datas(zone_name, self.server.get_db_file()): if self.server._shutdown_event.is_set(): # Check if xfrout is shutdown - raise XfroutException("shutdown!") + self._log.log_message("error", "shutdown!") if rr_type(rr_data[5]) == rr_type.SOA(): #ignore soa record continue @@ -270,9 +263,6 @@ class XfroutSession(BaseRequestHandler): self._send_message_with_last_soa(msg, sock, rrset_soa) - def log_msg(self, msg): - print('[b10-xfrout] ', msg) - class UnixSockServer(ThreadingUnixStreamServer): '''The unix domain socket server which accept xfr query sent from auth server.''' @@ -280,8 +270,8 @@ class UnixSockServer(ThreadingUnixStreamServer): def __init__(self, sock_file, handle_class, shutdown_event, config_data, log): try: os.unlink(sock_file) - except: - pass + except Exception as e: + self._log.log_message("error", str(e)) self._sock_file = sock_file ThreadingUnixStreamServer.__init__(self, sock_file, handle_class) @@ -296,12 +286,11 @@ class UnixSockServer(ThreadingUnixStreamServer): self.RequestHandlerClass(request, client_address, self, self._log) def shutdown(self): - self._log.log_message('warning', 'Xfrout process is shutting down!') ThreadingUnixStreamServer.shutdown(self) try: os.unlink(self._sock_file) - except: - self._log.log_message('error', 'OS unlink sock file exception while shutting down') + except Exception as e: + self._log.log_message("error", str(e)) def update_config_data(self, new_config): '''Apply the new config setting of xfrout module. ''' @@ -356,8 +345,8 @@ class XfroutServer: self._config_data = self._cc.get_full_config() self._cc.start() self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'), - self._config_data.get('severity'), self._config_data.get('versions'), - self._config_data.get('max_bytes'), True) + self._config_data.get('log_severity'), self._config_data.get('log_versions'), + self._config_data.get('log_max_bytes'), True) self._start_xfr_query_listener() diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in index e33efdb4f3..974593071b 100644 --- a/src/bin/xfrout/xfrout.spec.pre.in +++ b/src/bin/xfrout/xfrout.spec.pre.in @@ -24,22 +24,22 @@ "item_name": "log_file", "item_type": "string", "item_optional": False, - "item_default": '@@LOCALSTATEDIR@@/Xfrout.log' + "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log' }, { - "item_name": "severity", + "item_name": "log_severity", "item_type": "string", "item_optional": False, "item_default": "debug" }, { - "item_name": "versions", + "item_name": "log_versions", "item_type": "integer", "item_optional": False, "item_default": 5 }, { - "item_name": "max_bytes", + "item_name": "log_max_bytes", "item_type": "integer", "item_optional": False, "item_default": 1048576 diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index e9e0b3b66e..2364c3d8d2 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -31,13 +31,18 @@ LEVELS = {'debug' : logging.DEBUG, 'error' : logging.ERROR, 'critical' : logging.CRITICAL} + FORMATTER = logging.Formatter("%(name)s: %(levelname)s: %(message)s") -TIME_FORMATTER = logging.Formatter("%(asctime)s: %(name)s: %(levelname)s: %(message)s") +TIME_FORMATTER = logging.Formatter("%(asctime)s.%(msecs)03d %(name)s: %(levelname)s: %(message)s", + "%d-%b-%Y %H:%M:%S") class NSFileLogHandler(logging.handlers.RotatingFileHandler): """RotatingFileHandler: replace RotatingFileHandler with a custom handler""" def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0): + dir = os.path.split(filename) + if not (os.path.exists(dir[0])): + os.makedirs(dir[0]) super(NSFileLogHandler, self).__init__(filename, mode, maxBytes, backupCount, encoding, delay) @@ -202,15 +207,15 @@ class NSLogger(logging.getLoggerClass()): if(log_file_str): self._log_file = log_file_str - severity_str = config_data.get('severity') + severity_str = config_data.get('log_severity') if(severity_str): self._severity = severity_str - versions_str = config_data.get('versions') + versions_str = config_data.get('log_versions') if(versions_str): self._versions = int(versions_str) - max_bytes_str = config_data.get('max_bytes') + max_bytes_str = config_data.get('log_max_bytes') if(max_bytes_str): self._max_bytes = int(max_bytes_str) diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index b513cbdc5b..c94959684e 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -2,42 +2,45 @@ from isc.log.log import * import unittest import os import sys - -FILE_LOG1 = '/tmp/b10_file1.log' -FILE_LOG2 = '/tmp/b10_file2.log' -FILE_LOG3 = '/tmp/ZZZZ/b10_file2.log' - -FILE_STREAM_LOG1 = '/tmp/b10_file_stream1.log' -FILE_STREAM_LOG2 = '/tmp/b10_file_stream2.log' -FILE_STREAM_LOG3 = '/tmp/b10_file_stream2.log' +import tempfile class TestRotateFileHandler(unittest.TestCase): def setUp(self): - self.handler = NSFileLogHandler(filename = FILE_LOG1, maxBytes = 1024, backupCount = 5) + self.FILE_LOG1 = tempfile.mkstemp() + self.FILE_LOG2 = tempfile.mkstemp() + self.FILE_LOG3 = tempfile.mkstemp() + self.handler = NSFileLogHandler(filename = self.FILE_LOG1[1], maxBytes = 1024, backupCount = 5) def test_shouldRollover(self): - if(os.path.exists(FILE_LOG1)): - os.remove(FILE_LOG1) + if(os.path.exists(self.FILE_LOG1[1])): + os.remove(self.FILE_LOG1[1]) record = logging.LogRecord(None, None, "", 0, "rotate file handler", (), None, None) self.handler.shouldRollover(record) - self.assertTrue(os.path.exists(FILE_LOG1)) + self.assertTrue(os.path.exists(self.FILE_LOG1[1])) def test_update_config(self): - self.handler.update_config(FILE_LOG2, 3, 512) - self.assertEqual(self.handler.baseFilename, FILE_LOG2) + self.handler.update_config(self.FILE_LOG2[1], 3, 512) + self.assertEqual(self.handler.baseFilename, self.FILE_LOG2[1]) self.assertEqual(self.handler.maxBytes, 512) self.assertEqual(self.handler.backupCount, 3) - dir = os.path.split(FILE_LOG3) - if not os.path.exists(dir[0]): - self.handler.update_config(FILE_LOG3, 4, 1024) - self.assertEqual(self.handler.baseFilename, FILE_LOG2) + dir = os.path.split(self.FILE_LOG3[1]) + path = dir[0] + "path_not_exists" + update_file = os.path.join(path, dir[1]) + + if not os.path.exists(path): + self.handler.update_config(update_file, 4, 1024) + self.assertEqual(self.handler.baseFilename, self.FILE_LOG2[1]) self.assertEqual(self.handler.maxBytes, 1024) self.assertEqual(self.handler.backupCount, 4) def tearDown(self): + os.close(self.FILE_LOG1[0]) + os.close(self.FILE_LOG2[0]) + os.unlink(self.FILE_LOG1[1]) + os.unlink(self.FILE_LOG2[1]) self.handler.flush() self.handler.close() @@ -45,7 +48,10 @@ class TestRotateFileHandler(unittest.TestCase): class TestLogging(unittest.TestCase): def setUp(self): - self.file_stream_logger = NSLogger('File_Stream_Logger', FILE_STREAM_LOG1, + self.FILE_STREAM_LOG1 = tempfile.mkstemp() + self.FILE_STREAM_LOG2 = tempfile.mkstemp() + self.FILE_STREAM_LOG3 = tempfile.mkstemp() + self.file_stream_logger = NSLogger('File_Stream_Logger', self.FILE_STREAM_LOG1[1], 'debug', 5, 1024, True) self.syslog_logger = NSLogger('SysLogger', '', 'info', 5, 1024, False) @@ -84,11 +90,11 @@ class TestLogging(unittest.TestCase): ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertFalse(ret) - self.syslog_logger._add_rotate_handler(FILE_STREAM_LOG1, 5, 1024) + self.syslog_logger._add_rotate_handler(self.FILE_STREAM_LOG1[1], 5, 1024) ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertTrue(ret) - def test_add__stream_handler(self): + def test_add_stream_handler(self): if(self.file_stream_logger._stream_handler in self.file_stream_logger.handlers): self.file_stream_logger.removeHandler(self.file_stream_logger._stream_handler) @@ -105,7 +111,7 @@ class TestLogging(unittest.TestCase): self.assertTrue(ret) def test_update_rotate_handler(self): - self.file_stream_logger._update_rotate_handler(FILE_STREAM_LOG2, 4, 1024) + self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG2[1], 4, 1024) ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) @@ -113,33 +119,38 @@ class TestLogging(unittest.TestCase): ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertFalse(ret) - self.file_stream_logger._update_rotate_handler(FILE_STREAM_LOG1, 4, 1024) + self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG1[1], 4, 1024) ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) def test_update_config(self): - update_config = {'log_file' : FILE_STREAM_LOG1, - 'severity' : 'error', - 'versions' : 4, - 'max_bytes' : 1024} + update_config = {'log_file' : self.FILE_STREAM_LOG1[1], + 'log_severity' : 'error', + 'log_versions' : 4, + 'log_max_bytes' : 1024} self.file_stream_logger.update_config(update_config) logLevel = LEVELS.get('error', logging.NOTSET) self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) def test_log_message(self): - update_config = {'log_file' : FILE_STREAM_LOG3, - 'severity' : 'critical', - 'versions' : 4, - 'max_bytes' : 1024} + update_config = {'log_file' : self.FILE_STREAM_LOG3[1], + 'log_severity' : 'critical', + 'log_versions' : 4, + 'log_max_bytes' : 1024} self.file_stream_logger.update_config(update_config) self.file_stream_logger.log_message('debug', 'debug message') self.file_stream_logger.log_message('info', 'info message') self.file_stream_logger.log_message('warning', 'warning message') self.file_stream_logger.log_message('error', 'error message') - self.assertFalse(os.path.exists(FILE_STREAM_LOG3)) + self.assertTrue(os.path.exists(self.FILE_STREAM_LOG3[1])) def tearDown(self): - pass + os.close(self.FILE_STREAM_LOG1[0]) + os.unlink(self.FILE_STREAM_LOG1[1]) + os.close(self.FILE_STREAM_LOG2[0]) + os.unlink(self.FILE_STREAM_LOG2[1]) + os.close(self.FILE_STREAM_LOG3[0]) + os.unlink(self.FILE_STREAM_LOG3[1]) if __name__ == '__main__': unittest.main() From e818104708f608e4cec54d8a2836dba6dc640fc9 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 17 Jun 2010 09:22:57 +0000 Subject: [PATCH 20/66] Fix a bug : user remove log subdirectory at runtime git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2142 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.spec.pre.in | 4 ++-- src/lib/python/isc/log/log.py | 4 ++++ src/lib/python/isc/log/tests/log_test.py | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in index 974593071b..c1a5303107 100644 --- a/src/bin/xfrout/xfrout.spec.pre.in +++ b/src/bin/xfrout/xfrout.spec.pre.in @@ -12,7 +12,7 @@ "item_name": "db_file", "item_type": "string", "item_optional": False, - "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3' + "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3" }, { "item_name": "log_name", @@ -24,7 +24,7 @@ "item_name": "log_file", "item_type": "string", "item_optional": False, - "item_default": '@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log' + "item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log" }, { "item_name": "log_severity", diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index 2364c3d8d2..a50c6c493f 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -54,6 +54,9 @@ class NSFileLogHandler(logging.handlers.RotatingFileHandler): dfn = self.baseFilename if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? self.stream.close() + dir = os.path.split(dfn) + if not (os.path.exists(dir[0])): #Is log subdirectory exist? + os.makedirs(dir[0]) self.stream = self._open() return super(NSFileLogHandler, self).shouldRollover(record) @@ -72,6 +75,7 @@ class NSFileLogHandler(logging.handlers.RotatingFileHandler): self.maxBytes = max_bytes self.backupCount = backup_count + class NSSysLogHandler(logging.Handler): """Replace SysLogHandler with a custom handler diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index c94959684e..44d2b75ff4 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -1,7 +1,6 @@ from isc.log.log import * import unittest import os -import sys import tempfile @@ -38,9 +37,11 @@ class TestRotateFileHandler(unittest.TestCase): def tearDown(self): os.close(self.FILE_LOG1[0]) - os.close(self.FILE_LOG2[0]) os.unlink(self.FILE_LOG1[1]) + os.close(self.FILE_LOG2[0]) os.unlink(self.FILE_LOG2[1]) + os.close(self.FILE_LOG3[0]) + os.unlink(self.FILE_LOG3[1]) self.handler.flush() self.handler.close() From 4f3cbc6c6e94c1196d1e0e6e2418637538dc9dd4 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Thu, 17 Jun 2010 09:30:13 +0000 Subject: [PATCH 21/66] fixed typo's git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac238@2143 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in index 81bceee7df..05339a15b3 100644 --- a/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in +++ b/src/bin/cfgmgr/tests/b10-cfgmgr_test.py.in @@ -49,7 +49,7 @@ class TestConfigManagerStartup(unittest.TestCase): # some creative module use; # b10-cfgmgr has a hypen, so we use __import__ # this also gives us the chance to override the imported - # moculde ConfigManager in it. + # module ConfigManager in it. b = __import__("b10-cfgmgr") b.ConfigManager = MyConfigManager @@ -65,7 +65,7 @@ class TestConfigManagerStartup(unittest.TestCase): self.assertFalse(b.cm.running) # TODO: take value from the 'global config module' - # (and rename the .in aay from this file again) + # (and rename the .in away from this file again) data_path = "@localstatedir@/@PACKAGE@".replace("${prefix}", "@prefix@") self.assertEqual(data_path, b.DATA_PATH) From 6b6d6659ad2dd004641156bd2e18835d99c4c329 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Thu, 17 Jun 2010 11:20:26 +0000 Subject: [PATCH 22/66] fixed a distcheck problem (there may be another but i can't replicate here) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2146 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/cfgmgr/Makefile.am | 2 +- src/bin/cfgmgr/tests/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/cfgmgr/Makefile.am b/src/bin/cfgmgr/Makefile.am index b3dffd07ae..ef9523d263 100644 --- a/src/bin/cfgmgr/Makefile.am +++ b/src/bin/cfgmgr/Makefile.am @@ -4,7 +4,7 @@ pkglibexecdir = $(libexecdir)/@PACKAGE@ pkglibexec_SCRIPTS = b10-cfgmgr -CLEANFILES = b10-cfgmgr +CLEANFILES = b10-cfgmgr b10-cfgmgr.pyc b10_cfgmgrdir = @localstatedir@/@PACKAGE@ #B10_cfgmgr_DATA = diff --git a/src/bin/cfgmgr/tests/Makefile.am b/src/bin/cfgmgr/tests/Makefile.am index fc71023ef0..0a504bb6b2 100644 --- a/src/bin/cfgmgr/tests/Makefile.am +++ b/src/bin/cfgmgr/tests/Makefile.am @@ -9,5 +9,5 @@ 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/cfgmgr \ - $(PYCOVERAGE) $(abs_srcdir)/$$pytest ; \ + $(PYCOVERAGE) $(abs_builddir)/$$pytest ; \ done From bba1a4f6783d344e439008a0b7cbe76c447b9ac2 Mon Sep 17 00:00:00 2001 From: Shane Kerr Date: Thu, 17 Jun 2010 12:08:41 +0000 Subject: [PATCH 23/66] Ctrl-C was causing xfrout to get an exception. This was serve_forever() using select(), and getting EINTR on the system call. This patch fixes that. See Trac #146 for the full history: http://bind10.isc.org/ticket/146 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2147 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.py.in | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 7a659ffeb7..1643946504 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -28,6 +28,7 @@ import os from isc.config.ccsession import * from isc.cc import SessionError import socket +import select import errno from optparse import OptionParser, OptionValueError try: @@ -363,11 +364,22 @@ class UnixSockServer(ThreadingUnixStreamServer): self._lock.release() def listen_on_xfr_query(unix_socket_server): - '''Listen xfr query in one single thread. Polls for shutdown every 0.1 seconds, is there a better time? ''' - unix_socket_server.serve_forever(poll_interval = 0.1) + + while True: + try: + unix_socket_server.serve_forever(poll_interval = 0.1) + except select.error as err: + # serve_forever() calls select.select(), which can be + # interrupted. + # If it is interrupted, it raises select.error with the + # errno set to EINTR. We ignore this case, and let the + # normal program flow continue by trying serve_forever() + # again. + if err.args[0] != errno.EINTR: raise + class XfroutServer: From 24b93f20539aab8d474dcc731b5419b1b6bcde45 Mon Sep 17 00:00:00 2001 From: Shane Kerr Date: Thu, 17 Jun 2010 12:10:32 +0000 Subject: [PATCH 24/66] Updating ChangeLog for bug fix. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2148 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8c276b6bbe..83b931305c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + 55. [bug] shane + bin/xfrout: xfrout exception on Ctrl-C now no longer generates + exception for 'Interrupted system call' + (Track #136, svn r2147) + 54. [bug] zhanglikun bin/xfrout: Enable b10-xfrout can be launched in source code tree. From dcba62a4e55545800ed344f5b08a55f1bebf0210 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 17 Jun 2010 13:56:06 +0000 Subject: [PATCH 25/66] Modified unittest tempfile git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2151 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/tests/log_test.py | 75 +++++++++++++----------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index 44d2b75ff4..2af4f18098 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -7,52 +7,64 @@ import tempfile class TestRotateFileHandler(unittest.TestCase): def setUp(self): - self.FILE_LOG1 = tempfile.mkstemp() - self.FILE_LOG2 = tempfile.mkstemp() - self.FILE_LOG3 = tempfile.mkstemp() - self.handler = NSFileLogHandler(filename = self.FILE_LOG1[1], maxBytes = 1024, backupCount = 5) + self.FILE_LOG1 = tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.FILE_LOG2 = tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.FILE_LOG3 = tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.handler = NSFileLogHandler(filename = self.FILE_LOG1.name, + maxBytes = 1024, + backupCount = 5) def test_shouldRollover(self): - if(os.path.exists(self.FILE_LOG1[1])): - os.remove(self.FILE_LOG1[1]) + if(os.path.exists(self.FILE_LOG1.name)): + os.remove(self.FILE_LOG1.name) record = logging.LogRecord(None, None, "", 0, "rotate file handler", (), None, None) self.handler.shouldRollover(record) - self.assertTrue(os.path.exists(self.FILE_LOG1[1])) + self.assertTrue(os.path.exists(self.FILE_LOG1.name)) def test_update_config(self): - self.handler.update_config(self.FILE_LOG2[1], 3, 512) - self.assertEqual(self.handler.baseFilename, self.FILE_LOG2[1]) + self.handler.update_config(self.FILE_LOG2.name, 3, 512) + self.assertEqual(self.handler.baseFilename, self.FILE_LOG2.name) self.assertEqual(self.handler.maxBytes, 512) self.assertEqual(self.handler.backupCount, 3) - dir = os.path.split(self.FILE_LOG3[1]) + dir = os.path.split(self.FILE_LOG3.name) path = dir[0] + "path_not_exists" update_file = os.path.join(path, dir[1]) if not os.path.exists(path): self.handler.update_config(update_file, 4, 1024) - self.assertEqual(self.handler.baseFilename, self.FILE_LOG2[1]) + self.assertEqual(self.handler.baseFilename, self.FILE_LOG2.name) self.assertEqual(self.handler.maxBytes, 1024) self.assertEqual(self.handler.backupCount, 4) def tearDown(self): - os.close(self.FILE_LOG1[0]) - os.unlink(self.FILE_LOG1[1]) - os.close(self.FILE_LOG2[0]) - os.unlink(self.FILE_LOG2[1]) - os.close(self.FILE_LOG3[0]) - os.unlink(self.FILE_LOG3[1]) self.handler.flush() self.handler.close() + self.FILE_LOG1.close() + self.FILE_LOG2.close() + self.FILE_LOG3.close() class TestLogging(unittest.TestCase): def setUp(self): - self.FILE_STREAM_LOG1 = tempfile.mkstemp() - self.FILE_STREAM_LOG2 = tempfile.mkstemp() - self.FILE_STREAM_LOG3 = tempfile.mkstemp() - self.file_stream_logger = NSLogger('File_Stream_Logger', self.FILE_STREAM_LOG1[1], + self.FILE_STREAM_LOG1= tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.FILE_STREAM_LOG2= tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.FILE_STREAM_LOG3= tempfile.NamedTemporaryFile(mode='w', + prefix="b10", + delete=True) + self.file_stream_logger = NSLogger('File_Stream_Logger', + self.FILE_STREAM_LOG1.name, 'debug', 5, 1024, True) self.syslog_logger = NSLogger('SysLogger', '', 'info', 5, 1024, False) @@ -91,7 +103,7 @@ class TestLogging(unittest.TestCase): ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertFalse(ret) - self.syslog_logger._add_rotate_handler(self.FILE_STREAM_LOG1[1], 5, 1024) + self.syslog_logger._add_rotate_handler(self.FILE_STREAM_LOG1.name, 5, 1024) ret = self.syslog_logger._file_handler in self.syslog_logger.handlers self.assertTrue(ret) @@ -112,7 +124,7 @@ class TestLogging(unittest.TestCase): self.assertTrue(ret) def test_update_rotate_handler(self): - self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG2[1], 4, 1024) + self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG2.name, 4, 1024) ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) @@ -120,12 +132,12 @@ class TestLogging(unittest.TestCase): ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertFalse(ret) - self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG1[1], 4, 1024) + self.file_stream_logger._update_rotate_handler(self.FILE_STREAM_LOG1.name, 4, 1024) ret = self.file_stream_logger._file_handler in self.file_stream_logger.handlers self.assertTrue(ret) def test_update_config(self): - update_config = {'log_file' : self.FILE_STREAM_LOG1[1], + update_config = {'log_file' : self.FILE_STREAM_LOG1.name, 'log_severity' : 'error', 'log_versions' : 4, 'log_max_bytes' : 1024} @@ -134,7 +146,7 @@ class TestLogging(unittest.TestCase): self.assertEqual(self.file_stream_logger.getEffectiveLevel(), logLevel) def test_log_message(self): - update_config = {'log_file' : self.FILE_STREAM_LOG3[1], + update_config = {'log_file' : self.FILE_STREAM_LOG3.name, 'log_severity' : 'critical', 'log_versions' : 4, 'log_max_bytes' : 1024} @@ -143,15 +155,12 @@ class TestLogging(unittest.TestCase): self.file_stream_logger.log_message('info', 'info message') self.file_stream_logger.log_message('warning', 'warning message') self.file_stream_logger.log_message('error', 'error message') - self.assertTrue(os.path.exists(self.FILE_STREAM_LOG3[1])) + self.assertTrue(os.path.exists(self.FILE_STREAM_LOG3.name)) def tearDown(self): - os.close(self.FILE_STREAM_LOG1[0]) - os.unlink(self.FILE_STREAM_LOG1[1]) - os.close(self.FILE_STREAM_LOG2[0]) - os.unlink(self.FILE_STREAM_LOG2[1]) - os.close(self.FILE_STREAM_LOG3[0]) - os.unlink(self.FILE_STREAM_LOG3[1]) + self.FILE_STREAM_LOG1.close() + self.FILE_STREAM_LOG2.close() + self.FILE_STREAM_LOG3.close() if __name__ == '__main__': unittest.main() From e25a9be8bae2c3380fa9e0b4df24193bf2de8984 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 17 Jun 2010 21:51:18 +0000 Subject: [PATCH 26/66] 56. [func]* jinmei lib/dns: renamed the library name to libdns++ to avoid confusion with the same name of library of BIND 9. (Trac #190, svn r2153) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2154 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83b931305c..006ec4d162 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,21 +1,26 @@ - 55. [bug] shane - bin/xfrout: xfrout exception on Ctrl-C now no longer generates - exception for 'Interrupted system call' - (Track #136, svn r2147) + 56. [func]* jinmei + lib/dns: renamed the library name to libdns++ to avoid confusion + with the same name of library of BIND 9. + (Trac #190, svn r2153) - 54. [bug] zhanglikun + 55. [bug] shane + bin/xfrout: xfrout exception on Ctrl-C now no longer generates + exception for 'Interrupted system call' + (Track #136, svn r2147) + + 54. [bug] zhanglikun bin/xfrout: Enable b10-xfrout can be launched in source code tree. (Trac #224, svn r2103) - 53. [bug] zhanglikun + 53. [bug] zhanglikun bin/bindctl: Generate a unique session ID by using socket.gethostname() instead of socket.gethostbyname(), since the latter one could make bindctl stall if its own host name can't be resolved. (Trac #228, svn r2096) - 52. [func] zhanglikun + 52. [func] zhanglikun bin/xfrout: When xfrout is launched, check whether the socket file is being used by one running xfrout process, if it is, exit from python. If the file isn't a socket file From cb89dbe502da95acb6f89781710c07bd4802bb8d Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Fri, 18 Jun 2010 01:09:44 +0000 Subject: [PATCH 27/66] use simpler version of Name::split() for better readability (trac #200) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2159 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/data_source.cc | 24 ++++++++---------- src/lib/datasrc/sqlite3_datasrc.cc | 6 ++--- src/lib/datasrc/tests/datasrc_unittest.cc | 9 +++++++ src/lib/datasrc/tests/testdata/example.org | 1 + .../tests/testdata/example.org.sqlite3 | Bin 13312 -> 14336 bytes 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/lib/datasrc/data_source.cc b/src/lib/datasrc/data_source.cc index 61a11b62f8..6914d243ff 100644 --- a/src/lib/datasrc/data_source.cc +++ b/src/lib/datasrc/data_source.cc @@ -202,18 +202,18 @@ refQuery(const Name& name, const RRClass& qclass, const DataSrc* ds, } // Match downward, from the zone apex to the query name, looking for -// referrals. +// referrals. Note that we exclude the apex name and query name themselves; +// they'll be handled in a normal lookup in the zone. inline bool hasDelegation(const DataSrc* ds, const Name* zonename, Query& q, QueryTaskPtr task) { - const int nlen = task->qname.getLabelCount(); - const int diff = nlen - zonename->getLabelCount(); + const int diff = task->qname.getLabelCount() - zonename->getLabelCount(); if (diff > 1) { bool found = false; RRsetList ref; - for (int i = diff; i > 1; --i) { - const Name sub(task->qname.split(i - 1, nlen - i)); + for (int i = diff - 1; i > 0; --i) { + const Name sub(task->qname.split(i)); if (refQuery(sub, q.qclass(), ds, zonename, ref)) { found = true; break; @@ -360,11 +360,11 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, // Find the closest provable enclosing name for QNAME Name enclosure(zonename); - const int nlen = task->qname.getLabelCount(); - const int diff = nlen - enclosure.getLabelCount(); + const int diff = task->qname.getLabelCount() - + enclosure.getLabelCount(); string hash2; for (int i = 1; i <= diff; ++i) { - enclosure = task->qname.split(i, nlen - i); + enclosure = task->qname.split(i); string nodehash(nsec3->getHash(enclosure)); if (nodehash == hash1) { break; @@ -434,8 +434,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, return (DataSrc::SUCCESS); } - const int nlen = task->qname.getLabelCount(); - const int diff = nlen - zonename->getLabelCount(); + const int diff = task->qname.getLabelCount() - zonename->getLabelCount(); if (diff < 1) { return (DataSrc::SUCCESS); } @@ -445,7 +444,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool cname = false; for (int i = 1; i <= diff; ++i) { - const Name& wname(star.concatenate(task->qname.split(i, nlen - i))); + const Name& wname(star.concatenate(task->qname.split(i))); QueryTask newtask(wname, task->qclass, task->qtype, Section::ANSWER(), QueryTask::AUTH_QUERY); result = doQueryTask(ds, zonename, newtask, wild); @@ -541,8 +540,7 @@ DataSrc::doQuery(Query& q) { // (Note that RRtype DS queries need to go to the parent.) const int nlabels = task->qname.getLabelCount() - 1; NameMatch match(nlabels != 0 && task->qtype == RRType::DS() ? - task->qname.split(1, task->qname.getLabelCount() - 1) : - task->qname); + task->qname.split(1) : task->qname); findClosestEnclosure(match, task->qclass); const DataSrc* datasource = match.bestDataSrc(); const Name* zonename = match.closestName(); diff --git a/src/lib/datasrc/sqlite3_datasrc.cc b/src/lib/datasrc/sqlite3_datasrc.cc index 4b68590743..6d5edeb1df 100644 --- a/src/lib/datasrc/sqlite3_datasrc.cc +++ b/src/lib/datasrc/sqlite3_datasrc.cc @@ -330,7 +330,7 @@ int Sqlite3DataSrc::findClosest(const Name& name, unsigned int* position) const { const unsigned int nlabels = name.getLabelCount(); for (unsigned int i = 0; i < nlabels; ++i) { - const Name matchname(name.split(i, nlabels - i)); + const Name matchname(name.split(i)); const int rc = hasExactZone(matchname.toText().c_str()); if (rc >= 0) { if (position != NULL) { @@ -356,9 +356,7 @@ Sqlite3DataSrc::findClosestEnclosure(NameMatch& match, return; } - match.update(*this, match.qname().split(position, - match.qname().getLabelCount() - - position)); + match.update(*this, match.qname().split(position)); } DataSrc::Result diff --git a/src/lib/datasrc/tests/datasrc_unittest.cc b/src/lib/datasrc/tests/datasrc_unittest.cc index bee83a18e1..43cbdab2bf 100644 --- a/src/lib/datasrc/tests/datasrc_unittest.cc +++ b/src/lib/datasrc/tests/datasrc_unittest.cc @@ -540,6 +540,15 @@ TEST_F(DataSrcTest, Dname) { EXPECT_TRUE(it->isLast()); } +TEST_F(DataSrcTest, DnameExact) { + // The example.org test zone has a DNAME RR for dname2.foo.example.org. + // A query for that name with a different RR type than DNAME shouldn't + // confuse delegation processing. + createAndProcessQuery(Name("dname2.foo.example.org"), RRClass::IN(), + RRType::A()); + headerCheck(msg, Rcode::NOERROR(), true, true, true, 0, 1, 0); +} + TEST_F(DataSrcTest, Cname) { readAndProcessQuery("q_cname"); diff --git a/src/lib/datasrc/tests/testdata/example.org b/src/lib/datasrc/tests/testdata/example.org index 822a8a22c4..e60f877f2b 100644 --- a/src/lib/datasrc/tests/testdata/example.org +++ b/src/lib/datasrc/tests/testdata/example.org @@ -11,3 +11,4 @@ mail.example.org. A 192.0.2.10 sub.example.org. NS ns.sub.example.org. ns.sub.example.org. A 192.0.2.101 dname.example.org. DNAME dname.example.info. +dname2.foo.example.org. DNAME dname2.example.info. diff --git a/src/lib/datasrc/tests/testdata/example.org.sqlite3 b/src/lib/datasrc/tests/testdata/example.org.sqlite3 index 060de78decc9abef8ad45b17f069502b1c5f5a24..070012f72d37d511a453e7a057bcdaa35adc23d5 100644 GIT binary patch delta 1621 zcmaKsO-vI(6oBWa8zWoV-SQ`3+CnL|z;4;yphAs61fnEzAx0DQP-8*lr$l1v#ZXRO zG>}Z>;?biqMo2tqU4fBT)7V$3dhe@{QPSnq3>JUz+ zNdsEfHC8ci>DiM4n8?ytG8Silj7a!wPXJnaZ(ts0PatTh&xZpV+l)E71#`7RRe54=do(F*`ZF$uOlw^aR8NTcQ zcO25f<370;o2Oj>`8-aTjeLR&u*UzdR5TlgEs%XXMN&>%=Rf9a%u(->8+@^$`YTC=AL#7?go9 zC<9?o2Ew2WcyeoyoiL~_2!k>dHibc%@@$1c8480k5C&x+406!s*H{>oLo(aRkdcof z57CeGDV?NsWS3kg3H$@U#;Z7w5qggv!LocQU10d=ZV}UiP37GG+E0Vhrz~CVV~3kv qR973~;jS4CE3NhB&aOLxjoMZSjJ$z|;W$30$8@r8>0}<$$^HR{<(p>! delta 1295 zcmbW1&ubGw6o6;uO_AnDvr9JFP12f}G}S}1v2GhNNU>7XmZE}q6C}k@m8LD08u5}8 zylRETi+_MO4>q9Sp~RcVqIea-li-Nxz@b>G!@nu zxn7<4dW3&&>GBfiJ=6tLP11W8tV1B`!1Sre>j>vlf<23Dt}`2$KCg-W23MyXe=l18DD zMuCz>fs*EdWVf+O8r@=SXQY-H5N!tU;W5lZfSdyxyv%;GH>~FBa;`go7ygc9|AFm} WbEMRN-us;m!T&f Date: Fri, 18 Jun 2010 01:10:40 +0000 Subject: [PATCH 28/66] update for trac #200 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2160 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 006ec4d162..fddff31050 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ + 57. [func] jinmei + lib/datasrc: used a simpler version of Name::split (change 31) for + better readability. No behavior change. (Trac #200, svn r2159) + 56. [func]* jinmei lib/dns: renamed the library name to libdns++ to avoid confusion with the same name of library of BIND 9. From a5ccbb050066310ee050f202c00d41efffcbebc5 Mon Sep 17 00:00:00 2001 From: Likun Zhang Date: Fri, 18 Jun 2010 02:11:54 +0000 Subject: [PATCH 29/66] Add a short description to change(item 38). git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2162 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index fddff31050..2b5d7fdbb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -86,6 +86,10 @@ bind10-devel-20100602 released on June 2, 2010 Renamed libauth to libdatasrc. 38. [bug] zhanglikun + Send command 'shutdown' to Xfrin and Xfrout when boss receive SIGINT. + Remove unused socket file when Xfrout process exits. Make sure Xfrout + exit by itself when it receives SIGINT, instead of being killed by the + signal SIGTERM or SIGKILL sent from boss. (Trac #135, #151, #134, svn r1797) 37. [build] jinmei From 905e15266db2fac8560a0a684de14d62c67ec66c Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Fri, 18 Jun 2010 03:20:31 +0000 Subject: [PATCH 30/66] minor style fix: fold a long line. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2163 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/main.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc index 2e7073699f..6e3ba0e000 100644 --- a/src/bin/auth/main.cc +++ b/src/bin/auth/main.cc @@ -148,7 +148,8 @@ main(int argc, char* argv[]) { io_service = new asio_link::IOService(auth_server, port, use_ipv4, use_ipv6); - ModuleCCSession cs(specfile, io_service->get_io_service(), my_config_handler, my_command_handler); + ModuleCCSession cs(specfile, io_service->get_io_service(), + my_config_handler, my_command_handler); auth_server->setConfigSession(&cs); auth_server->updateConfig(ElementPtr()); From 994abd957309461765719b1e1ac14c32e53e39fd Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Fri, 18 Jun 2010 06:53:21 +0000 Subject: [PATCH 31/66] removed unnecessary const's from declarations. trivial cleanup, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2164 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/asio_link.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/auth/asio_link.h b/src/bin/auth/asio_link.h index b5c9153f83..55809516b4 100644 --- a/src/bin/auth/asio_link.h +++ b/src/bin/auth/asio_link.h @@ -24,8 +24,8 @@ struct IOServiceImpl; class IOService { public: - IOService(AuthSrv* auth_server, const char* port, - const bool use_ipv4, const bool use_ipv6); + IOService(AuthSrv* auth_server, const char* port, bool use_ipv4, + bool use_ipv6); ~IOService(); void run(); void stop(); From 0fb9d9d88907d52f2c43a995565e8c0014b825aa Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 19 Jun 2010 17:27:41 +0000 Subject: [PATCH 32/66] style cleanup: removed a redundant blank line. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2173 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/main.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc index 6e3ba0e000..bfd97253ee 100644 --- a/src/bin/auth/main.cc +++ b/src/bin/auth/main.cc @@ -154,7 +154,6 @@ main(int argc, char* argv[]) { auth_server->setConfigSession(&cs); auth_server->updateConfig(ElementPtr()); - cout << "[b10-auth] Server started." << endl; io_service->run(); } catch (const std::exception& ex) { From 2a8263d8d92c9f05f96528e609b87d48c915d836 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 19 Jun 2010 22:50:55 +0000 Subject: [PATCH 33/66] style fix: removed redundant spaces in a blank line. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2174 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/dns/name.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/dns/name.cc b/src/lib/dns/name.cc index e27255526b..4f02e715b0 100644 --- a/src/lib/dns/name.cc +++ b/src/lib/dns/name.cc @@ -267,7 +267,7 @@ Name::Name(const std::string &namestring, bool downcase) { if (state == ft_ordinary) { assert(count != 0); ndata.at(offsets.back()) = count; - + offsets.push_back(ndata.size()); // add a trailing \0 ndata.push_back('\0'); From 9a4b12c8916dcaeb0e0e1e33510af3afadcd2d3e Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Mon, 21 Jun 2010 02:21:38 +0000 Subject: [PATCH 34/66] workaround for ASIO/stdblib interaction (trac #248, partially merged from branches/trac221) git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2187 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/cc/session.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc index 66bc2717ab..1293c169cc 100644 --- a/src/lib/cc/session.cc +++ b/src/lib/cc/session.cc @@ -19,6 +19,16 @@ #include +// XXX: there seems to be a strange dependency between ASIO and std library +// definitions. On some platforms if we include std headers before ASIO +// headers unexpected behaviors will happen. +// A middle term solution is to generalize our local wrapper interface +// (currently only available for the auth server), where all such portability +// issues are hidden, and to have other modules use the wrapper. +#include +#include +#include + #include #include #include @@ -29,10 +39,6 @@ #include #include -#include -#include -#include - #include #include "data.h" From 501fccc53da4c8fdc87dc1083004687103dcf7a9 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Mon, 21 Jun 2010 06:11:17 +0000 Subject: [PATCH 35/66] include asio.hpp first. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2190 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/cc/session_unittests.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/cc/session_unittests.cc b/src/lib/cc/session_unittests.cc index e67363efda..7bccbb1d56 100644 --- a/src/lib/cc/session_unittests.cc +++ b/src/lib/cc/session_unittests.cc @@ -15,10 +15,13 @@ // $Id: data_unittests.cc 1899 2010-05-21 12:03:59Z jelte $ #include "config.h" + +// XXX: the ASIO header must be included before others. See session.cc. +#include + #include #include -#include #include using namespace isc::cc; From 097322c495d6582ec6fe683ebed68147dfedccb6 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Mon, 21 Jun 2010 06:14:06 +0000 Subject: [PATCH 36/66] change for trac #248 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2191 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2b5d7fdbb8..bc1835aed0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ + 58. [bug] jinmei + Worked around an interaction issue between ASIO and standard C++ + library headers. Without this ASIO didn't work: sometimes the + application crashes, sometimes it blocked in the ASIO module. + (Trac #248, svn r2187, r2190) + 57. [func] jinmei lib/datasrc: used a simpler version of Name::split (change 31) for better readability. No behavior change. (Trac #200, svn r2159) From 8af151017185e98b9e11fa5ec7336f0fe40ba78b Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 22 Jun 2010 01:46:44 +0000 Subject: [PATCH 37/66] style: folded a long line. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2206 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/auth_srv.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc index dee60ef3b2..71810ae906 100644 --- a/src/bin/auth/auth_srv.cc +++ b/src/bin/auth/auth_srv.cc @@ -243,7 +243,8 @@ AuthSrv::processMessage(InputBuffer& request_buffer, Message& message, impl_->data_sources_.doQuery(query); } catch (const Exception& ex) { if (impl_->verbose_mode_) { - cerr << "[b10-auth] Internal error, returning SERVFAIL: " << ex.what() << endl; + cerr << "[b10-auth] Internal error, returning SERVFAIL: " << + ex.what() << endl; } makeErrorMessage(message, response_renderer, Rcode::SERVFAIL(), impl_->verbose_mode_); From 28c40039b3b5b63b50d2f391669dd4f50dd9d66f Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 22 Jun 2010 03:57:22 +0000 Subject: [PATCH 38/66] mark a failed test as DISABLED, rather than commeting it out. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2207 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/tests/datasrc_unittest.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/datasrc/tests/datasrc_unittest.cc b/src/lib/datasrc/tests/datasrc_unittest.cc index 43cbdab2bf..1268c65d07 100644 --- a/src/lib/datasrc/tests/datasrc_unittest.cc +++ b/src/lib/datasrc/tests/datasrc_unittest.cc @@ -852,8 +852,8 @@ TEST_F(DataSrcTest, AddRemoveDataSrc) { EXPECT_EQ(0, ds.dataSrcCount()); } -#if 0 // currently fails -TEST_F(DataSrcTest, synthesizedCnameTooLong) { +// currently fails +TEST_F(DataSrcTest, DISABLED_synthesizedCnameTooLong) { // qname has the possible max length (255 octets). it matches a DNAME, // and the synthesized CNAME would exceed the valid length. createAndProcessQuery( @@ -863,6 +863,5 @@ TEST_F(DataSrcTest, synthesizedCnameTooLong) { "0123456789abcdef0123456789abcdef0123456789a.dname.example.org."), RRClass::IN(), RRType::A()); } -#endif } From 3905211a1b7b102dde262d5102e9674a9d826cf9 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 22 Jun 2010 04:06:52 +0000 Subject: [PATCH 39/66] minor style fix: removed redundant white spaces in a black line. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2208 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/data_source.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/datasrc/data_source.cc b/src/lib/datasrc/data_source.cc index 6914d243ff..4b934a3194 100644 --- a/src/lib/datasrc/data_source.cc +++ b/src/lib/datasrc/data_source.cc @@ -192,7 +192,7 @@ refQuery(const Name& name, const RRClass& qclass, const DataSrc* ds, // Lookup failed return (false); } - + // Referral bit is expected, so clear it when checking flags if ((newtask.flags & ~DataSrc::REFERRAL) != 0) { return (false); From 2679e310976217cddd092935813be520de1fa303 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 22 Jun 2010 04:24:46 +0000 Subject: [PATCH 40/66] minor style fixes on brace positions. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2209 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/dns/rrsetlist.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/dns/rrsetlist.cc b/src/lib/dns/rrsetlist.cc index 976f420220..1000799829 100644 --- a/src/lib/dns/rrsetlist.cc +++ b/src/lib/dns/rrsetlist.cc @@ -29,8 +29,7 @@ namespace isc { namespace dns { void -RRsetList::addRRset(RRsetPtr rrsetptr) -{ +RRsetList::addRRset(RRsetPtr rrsetptr) { ConstRRsetPtr rrset_found = findRRset(rrsetptr->getType(), rrsetptr->getClass()); if (rrset_found != NULL) { @@ -42,8 +41,7 @@ RRsetList::addRRset(RRsetPtr rrsetptr) } RRsetPtr -RRsetList::findRRset(const RRType& rrtype, const RRClass& rrclass) -{ +RRsetList::findRRset(const RRType& rrtype, const RRClass& rrclass) { BOOST_FOREACH(RRsetPtr rrsetptr, rrsets_) { if ((rrsetptr->getClass() == rrclass) && (rrsetptr->getType() == rrtype)) { From 17214367b5b80e16bb68766a7f1b0bf90c91e190 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Tue, 22 Jun 2010 18:21:24 +0000 Subject: [PATCH 41/66] delete import_boost.sh. we don't need it any more. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2222 e5f2f494-b856-4b98-b285-d166d9295462 --- tools/import_boost.sh | 73 ------------------------------------------- 1 file changed, 73 deletions(-) delete mode 100755 tools/import_boost.sh diff --git a/tools/import_boost.sh b/tools/import_boost.sh deleted file mode 100755 index e3d3f2359d..0000000000 --- a/tools/import_boost.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# given a directory, copy all needed parts from boost into the -# current branch - -# only run this to update boost! (i.e. almost never) - -# usage example: -# cd /tmp -# tar xzvf /location/of/boost/tarball -# cd /home/user/svn/bind10/trunk -# tools/import_boost.sh /tmp/boost-version -# svn commit - -# need new boost stuff? -# TODO: LICENSE_1_0.txt -# add files to list 'ere -FILES=" -boost/*.hpp -boost/algorithm -boost/asio -boost/assign/list_inserter.hpp -boost/assign/std/vector.hpp -boost/bind -boost/config -boost/concept -boost/detail -boost/exception -boost/function -boost/iterator -boost/mpl -boost/preprocessor -boost/range -boost/smart_ptr -boost/type_traits -boost/utility -" - -TARGET="ext" - -if [ $# -ne 1 ] -then - echo "Usage: boost_import.sh " - exit -fi - -if [ ! -d $TARGET/boost ] -then - echo "This does not appear to be the main trunk/branch directory" - exit -fi - - -DIR=$1 - -do_cmd() -{ - echo $@ - $@ -} - - -#echo "cp ${DIR}/boost/shared_ptr.hpp boost/" -for FILE in ${FILES} -do -TGT=`echo ${FILE} | sed 's/[^\/]*$//'` -cmd="mkdir -p ${TARGET}/${TGT}" -do_cmd ${cmd} -cmd="cp -r ${DIR}/${FILE} ${TARGET}/${TGT}" -do_cmd ${cmd} -done - - From fa6eb99b73ddb75a47136846c9c8a8abbe874788 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Wed, 23 Jun 2010 06:25:14 +0000 Subject: [PATCH 43/66] minimal fixes for SunStudio support git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac251@2227 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 24 ++++++++++++++++-------- src/bin/auth/Makefile.am | 5 ++++- src/bin/auth/asio_link.cc | 1 + src/bin/auth/asio_link.h | 4 ++-- src/bin/host/host.cc | 2 ++ src/lib/cc/Makefile.am | 2 ++ src/lib/cc/session.cc | 1 + src/lib/dns/message.cc | 2 +- 8 files changed, 29 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index e6c7f38c52..c23c466e2a 100644 --- a/configure.ac +++ b/configure.ac @@ -9,12 +9,20 @@ AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CXX -AC_PROG_CC AC_PROG_LIBTOOL +AM_CONDITIONAL(USE_GXX, test "X${GXX}" = "Xyes") + # Use C++ language AC_LANG_CPLUSPLUS +# OS dependent compiler flags +case "$host" in + *-solaris*) + CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__" + ;; +esac + m4_define([_AM_PYTHON_INTERPRETER_LIST], [python python3 python3.1]) AC_ARG_WITH([pythonpath], AC_HELP_STRING([--with-pythonpath=PATH], @@ -98,16 +106,16 @@ AC_SUBST(PYTHON_LIB) # specify the default warning flags in CXXFLAGS and let specific modules # "override" the default. # -B10_CXXFLAGS= +B10_CXXFLAGS=-g -if test "X$GCC" = "Xyes"; then -B10_CXXFLAGS="-g -Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare" +werror_ok=0 +if test "X$GXX" = "Xyes"; then +B10_CXXFLAGS="-Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare" UNUSED_PARAM_ATTRIBUTE='__attribute__((unused))' # Certain versions of gcc (g++) have a bug that incorrectly warns about # the use of anonymous name spaces even if they're closed in a single # translation unit. For these versions we have to disable -Werror. -werror_ok=0 CXXFLAGS_SAVED="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $B10_CXXFLAGS -Werror" AC_MSG_CHECKING(for in-TU anonymous namespace breakage) @@ -118,13 +126,13 @@ namespace isc {class Bar {Foo foo_;};} ],, B10_CXXFLAGS="$B10_CXXFLAGS -Werror"], [AC_MSG_RESULT(yes)]) CXXFLAGS="$CXXFLAGS_SAVED" -fi dnl GCC = yes +fi dnl GXX = yes AM_CONDITIONAL(GCC_WERROR_OK, test $werror_ok = 1) AC_DEFINE_UNQUOTED(UNUSED_PARAM, $UNUSED_PARAM_ATTRIBUTE, Define to compiler keyword indicating a function argument is intentionally unused) # produce PIC unless we disable shared libraries. need this for python bindings. -if test $enable_shared != "no" -a "X$GCC" = "Xyes"; then +if test $enable_shared != "no" -a "X$GXX" = "Xyes"; then B10_CXXFLAGS="$B10_CXXFLAGS -fPIC" fi @@ -364,7 +372,7 @@ fi # run time performance. Hpefully we can find a better solution or the ASIO # code will be updated by the time we really need it. AC_CHECK_HEADERS(sys/devpoll.h, ac_cv_have_devpoll=yes, ac_cv_have_devpoll=no) -if test "X$ac_cv_have_devpoll" = "Xyes" -a "X$GCC" = "Xyes"; then +if test "X$ac_cv_have_devpoll" = "Xyes" -a "X$GXX" = "Xyes"; then CPPFLAGS="$CPPFLAGS -DASIO_DISABLE_DEV_POLL=1" fi diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am index 28d2bfc464..4ab64ee640 100644 --- a/src/bin/auth/Makefile.am +++ b/src/bin/auth/Makefile.am @@ -36,7 +36,10 @@ lib_LIBRARIES = libasio_link.a libasio_link_a_SOURCES = asio_link.cc asio_link.h # Note: the ordering matters: -Wno-... must follow -Wextra (defined in # B10_CXXFLAGS) -libasio_link_a_CXXFLAGS = $(AM_CXXFLAGS) -Wno-unused-parameter +libasio_link_a_CXXFLAGS = $(AM_CXXFLAGS) +if USE_GXX +libasio_link_a_CXXFLAGS += -Wno-unused-parameter +endif libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS) BUILT_SOURCES = spec_config.h diff --git a/src/bin/auth/asio_link.cc b/src/bin/auth/asio_link.cc index 15f4cf8172..12f99a4a90 100644 --- a/src/bin/auth/asio_link.cc +++ b/src/bin/auth/asio_link.cc @@ -16,6 +16,7 @@ #include +#include #include #include diff --git a/src/bin/auth/asio_link.h b/src/bin/auth/asio_link.h index 55809516b4..af35de5ef8 100644 --- a/src/bin/auth/asio_link.h +++ b/src/bin/auth/asio_link.h @@ -24,8 +24,8 @@ struct IOServiceImpl; class IOService { public: - IOService(AuthSrv* auth_server, const char* port, bool use_ipv4, - bool use_ipv6); + IOService(AuthSrv* auth_server, const char* const port, const bool use_ipv4, + const bool use_ipv6); ~IOService(); void run(); void stop(); diff --git a/src/bin/host/host.cc b/src/bin/host/host.cc index 35eebc7de9..07dd659b72 100644 --- a/src/bin/host/host.cc +++ b/src/bin/host/host.cc @@ -19,6 +19,8 @@ #include // for gettimeofday #include // networking functions and definitions on FreeBSD +#include + #include #include diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index 6b6d72bf47..c7a7249641 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -6,7 +6,9 @@ AM_CXXFLAGS = $(B10_CXXFLAGS) # error. Unfortunately there doesn't seem to be an easy way to selectively # avoid the error. As a short term workaround we suppress this warning # for the entire this module. See also src/bin/auth/Makefile.am. +if USE_GXX AM_CXXFLAGS += -Wno-unused-parameter +endif lib_LIBRARIES = libcc.a libcc_a_SOURCES = data.cc data.h session.cc session.h diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc index 1293c169cc..674f5845f7 100644 --- a/src/lib/cc/session.cc +++ b/src/lib/cc/session.cc @@ -25,6 +25,7 @@ // A middle term solution is to generalize our local wrapper interface // (currently only available for the auth server), where all such portability // issues are hidden, and to have other modules use the wrapper. +#include #include #include #include diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc index 0de7905778..1a45fe5035 100644 --- a/src/lib/dns/message.cc +++ b/src/lib/dns/message.cc @@ -923,7 +923,7 @@ SectionIterator::operator*() const { template const T* SectionIterator::operator->() const { - return (impl_->it_.operator->()); + return (&(operator*())); } template From e01cb8ad5b7499e7a6d8dd95aaf1067f1f5e6281 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 24 Jun 2010 01:00:15 +0000 Subject: [PATCH 44/66] another fix to operator-> just like the one made in message.cc added some comments on the intent git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac251@2249 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 8 +++++--- src/bin/auth/asio_link.cc | 2 +- src/bin/auth/asio_link.h | 4 ++-- src/lib/cc/session.cc | 2 +- src/lib/dns/rrsetlist.h | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index c23c466e2a..ae5ab98737 100644 --- a/configure.ac +++ b/configure.ac @@ -18,9 +18,11 @@ AC_LANG_CPLUSPLUS # OS dependent compiler flags case "$host" in - *-solaris*) - CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__" - ;; +*-solaris*) + # Solaris requires special definitions to get some standard libraries + # (e.g. getopt(3)) available with common used header files. + CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__" + ;; esac m4_define([_AM_PYTHON_INTERPRETER_LIST], [python python3 python3.1]) diff --git a/src/bin/auth/asio_link.cc b/src/bin/auth/asio_link.cc index 12f99a4a90..449613a7d1 100644 --- a/src/bin/auth/asio_link.cc +++ b/src/bin/auth/asio_link.cc @@ -16,7 +16,7 @@ #include -#include +#include // for some IPC/network system calls #include #include diff --git a/src/bin/auth/asio_link.h b/src/bin/auth/asio_link.h index af35de5ef8..dcb7d8f94f 100644 --- a/src/bin/auth/asio_link.h +++ b/src/bin/auth/asio_link.h @@ -24,8 +24,8 @@ struct IOServiceImpl; class IOService { public: - IOService(AuthSrv* auth_server, const char* const port, const bool use_ipv4, - const bool use_ipv6); + IOService(AuthSrv* auth_server, const char* const port, + const bool use_ipv4, const bool use_ipv6); ~IOService(); void run(); void stop(); diff --git a/src/lib/cc/session.cc b/src/lib/cc/session.cc index 674f5845f7..3d5d42b75d 100644 --- a/src/lib/cc/session.cc +++ b/src/lib/cc/session.cc @@ -25,7 +25,7 @@ // A middle term solution is to generalize our local wrapper interface // (currently only available for the auth server), where all such portability // issues are hidden, and to have other modules use the wrapper. -#include +#include // for some IPC/network system calls #include #include #include diff --git a/src/lib/dns/rrsetlist.h b/src/lib/dns/rrsetlist.h index 9e1c52334f..a8c3769d9b 100644 --- a/src/lib/dns/rrsetlist.h +++ b/src/lib/dns/rrsetlist.h @@ -60,7 +60,7 @@ public: } P operator->() const { - return (it_.operator->()); + return (&(operator*())); } bool operator==(const RRsetListIterator& other) { From 0ba9a0f7bf512ac815d4823b164d77904faf7db0 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 24 Jun 2010 01:33:47 +0000 Subject: [PATCH 45/66] set SunStudio specific options automatically. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac251@2250 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index ae5ab98737..4780297742 100644 --- a/configure.ac +++ b/configure.ac @@ -12,6 +12,7 @@ AC_PROG_CXX AC_PROG_LIBTOOL AM_CONDITIONAL(USE_GXX, test "X${GXX}" = "Xyes") +AC_CHECK_DECL([__SUNPRO_CC], [SUNCXX="yes"], [SUNCXX="no"]) # Use C++ language AC_LANG_CPLUSPLUS @@ -97,8 +98,8 @@ AC_SUBST(PYTHON_LIB) # TODO: check for _sqlite3.py module -# -# B10_CXXFLAGS is the default C++ compiler flags. This will (and should) be +# Compiler dependent settings: define some mandatory CXXFLAGS here. +# We also use a separate variable B10_CXXFLAGS. This will (and should) be # used as the default value for each specifc AM_CXXFLAGS: # AM_CXXFLAGS = $(B10_CXXFLAGS) # AM_CXXFLAGS += ... # add module specific flags @@ -107,10 +108,17 @@ AC_SUBST(PYTHON_LIB) # gcc's -Wno-XXX option must be specified after -Wall or -Wextra, we cannot # specify the default warning flags in CXXFLAGS and let specific modules # "override" the default. -# -B10_CXXFLAGS=-g +CXXFLAGS=-g werror_ok=0 + +# SunStudio compiler requires special compiler options for boost +# (http://blogs.sun.com/sga/entry/boost_mini_howto) +if test "$SUNCXX" = "yes"; then +CXXFLAGS="$CXXFLAGS -library=stlport4 -features=tmplife -features=tmplrefstatic" +fi + +# gcc specific settings: if test "X$GXX" = "Xyes"; then B10_CXXFLAGS="-Wall -Wextra -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare" UNUSED_PARAM_ATTRIBUTE='__attribute__((unused))' From 078d183c411790af4ec32b2be255deee4e1d7e5f Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 24 Jun 2010 01:41:29 +0000 Subject: [PATCH 46/66] adjusted the position of AC_CHECK_DECL git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac251@2251 e5f2f494-b856-4b98-b285-d166d9295462 --- configure.ac | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4780297742..db544ef205 100644 --- a/configure.ac +++ b/configure.ac @@ -11,12 +11,13 @@ AC_CONFIG_HEADERS([config.h]) AC_PROG_CXX AC_PROG_LIBTOOL +# Use C++ language +AC_LANG([C++]) + +# Identify the compiler: this check must be after AC_PROG_CXX and AC_LANG. AM_CONDITIONAL(USE_GXX, test "X${GXX}" = "Xyes") AC_CHECK_DECL([__SUNPRO_CC], [SUNCXX="yes"], [SUNCXX="no"]) -# Use C++ language -AC_LANG_CPLUSPLUS - # OS dependent compiler flags case "$host" in *-solaris*) From afff755e8887a251fd4b7872bf851c19ead9ba1f Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 24 Jun 2010 01:59:16 +0000 Subject: [PATCH 47/66] added a Trac # to an old change. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2252 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bc1835aed0..ebd8e3629e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -156,7 +156,7 @@ bind10-devel-20100421 released on April 21, 2010 24. [func] Support case-sensitive name compression in MessageRenderer. - (svn r1704) + (Trac #142, svn r1704) 23. [func] Support a simple name with possible compression. (svn r1701) From 48896de154e593f50d0c9a326b04709915a649be Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 26 Jun 2010 06:54:13 +0000 Subject: [PATCH 48/66] merged branches/trac249: throw an exception if the apex SOA/NS is missing. also refactored datasrc test mock. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2286 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/data_source.cc | 14 +- src/lib/datasrc/tests/datasrc_unittest.cc | 20 +- src/lib/datasrc/tests/test_datasrc.cc | 1127 ++++++++------------- src/lib/datasrc/tests/test_datasrc.h | 1 + 4 files changed, 474 insertions(+), 688 deletions(-) diff --git a/src/lib/datasrc/data_source.cc b/src/lib/datasrc/data_source.cc index 4b934a3194..b8240e9775 100644 --- a/src/lib/datasrc/data_source.cc +++ b/src/lib/datasrc/data_source.cc @@ -613,9 +613,12 @@ DataSrc::doQuery(Query& q) { // the authority section. RRsetList auth; if (!refQuery(*zonename, q.qclass(), datasource, zonename, - auth)) { - m.setRcode(Rcode::SERVFAIL()); - return; + auth) || + !auth.findRRset(RRType::NS(), + datasource->getClass())) { + isc_throw(DataSourceError, + "NS RR not found in " << *zonename << "/" << + datasource->getClass()); } copyAuth(q, auth); @@ -704,8 +707,9 @@ DataSrc::doQuery(Query& q) { result = addSOA(q, zonename, datasource); if (result != SUCCESS) { - m.setRcode(Rcode::SERVFAIL()); - return; + isc_throw(DataSourceError, + "SOA RR not found in" << *zonename << + "/" << datasource->getClass()); } } diff --git a/src/lib/datasrc/tests/datasrc_unittest.cc b/src/lib/datasrc/tests/datasrc_unittest.cc index 1268c65d07..b6385ca4ed 100644 --- a/src/lib/datasrc/tests/datasrc_unittest.cc +++ b/src/lib/datasrc/tests/datasrc_unittest.cc @@ -770,7 +770,7 @@ TEST_F(DataSrcTest, DS) { } TEST_F(DataSrcTest, CNAMELoop) { - createAndProcessQuery(Name("loop1.example.com"), RRClass::IN(), + createAndProcessQuery(Name("one.loop.example"), RRClass::IN(), RRType::A()); } @@ -864,4 +864,22 @@ TEST_F(DataSrcTest, DISABLED_synthesizedCnameTooLong) { RRClass::IN(), RRType::A()); } +TEST_F(DataSrcTest, noNSZone) { + EXPECT_THROW(createAndProcessQuery(Name("www.nons.example"), + RRClass::IN(), RRType::A()), + DataSourceError); +} + +TEST_F(DataSrcTest, noNSButDnameZone) { + EXPECT_THROW(createAndProcessQuery(Name("www.nons-dname.example"), + RRClass::IN(), RRType::A()), + DataSourceError); +} + +TEST_F(DataSrcTest, noSOAZone) { + EXPECT_THROW(createAndProcessQuery(Name("notexist.nosoa.example"), + RRClass::IN(), RRType::A()), + DataSourceError); +} + } diff --git a/src/lib/datasrc/tests/test_datasrc.cc b/src/lib/datasrc/tests/test_datasrc.cc index 39cb40bd54..d5de85b2a8 100644 --- a/src/lib/datasrc/tests/test_datasrc.cc +++ b/src/lib/datasrc/tests/test_datasrc.cc @@ -18,6 +18,8 @@ #include +#include + #include #include "test_datasrc.h" @@ -45,63 +47,258 @@ namespace isc { namespace datasrc { namespace { -const Name example("example.com"); -const Name sql1("sql1.example.com"); -const Name www_sql1("www.sql1.example.com"); -const Name www("www.example.com"); -const Name foo("foo.example.com"); -const Name dns01("dns01.example.com"); -const Name dns02("dns02.example.com"); -const Name dns03("dns03.example.com"); -const Name cnameint("cname-int.example.com"); -const Name cnameext("cname-ext.example.com"); -const Name dname("dname.example.com"); -const Name wild("*.wild.example.com"); -const Name wild2("*.wild2.example.com"); -const Name wild3("*.wild3.example.com"); -const Name subzone("subzone.example.com"); -const Name loop1("loop1.example.com"); -const Name loop2("loop2.example.com"); -RRsetPtr example_ns; -RRsetPtr example_soa; -RRsetPtr example_nsec; -RRsetPtr www_a; -RRsetPtr www_nsec; -RRsetPtr foo_cname; -RRsetPtr foo_nsec; -RRsetPtr cnameint_cname; -RRsetPtr cnameint_nsec; -RRsetPtr cnameext_cname; -RRsetPtr cnameext_nsec; -RRsetPtr dns01_a; -RRsetPtr dns01_nsec; -RRsetPtr dns02_a; -RRsetPtr dns02_nsec; -RRsetPtr dns03_a; -RRsetPtr dns03_nsec; -RRsetPtr wild_a; -RRsetPtr wild_nsec; -RRsetPtr wild2_cname; -RRsetPtr wild2_nsec; -RRsetPtr wild3_cname; -RRsetPtr wild3_nsec; -RRsetPtr dname_dname; -RRsetPtr dname_nsec; -RRsetPtr sql1_ns; -RRsetPtr sql1_soa; -RRsetPtr sql1_nsec; -RRsetPtr sql1_ds; -RRsetPtr sql1_ds_nsec; -RRsetPtr www_sql1_a; -RRsetPtr www_sql1_nsec; -RRsetPtr subzone_ns; -RRsetPtr subzone_nsec; -RRsetPtr subzone_glue1; -RRsetPtr subzone_glue2; -RRsetPtr subzone_ds; -RRsetPtr loop1_cname; -RRsetPtr loop2_cname; +// This is a mock data source for testing. It can contain multiple zones. +// The content of each zone should be configured in the form of RRData{}. +// Each RRData element is a tuple of char strings, representing +// "name, RRtype, RDATA". For simplicity we use the same single TTL for +// RRs (TEST_TTL) defined below. +// Multiple RRs of the same pair of (name, RRtype) can be defined, but +// they must not be interleaved with other types of pair. For example, +// This is okay: +// {"example.com", "AAAA", "2001:db8::1"}, +// {"example.com", "AAAA", "2001:db8::2"}, +// ... +// but this is invalid: +// {"example.com", "AAAA", "2001:db8::1"}, +// {"example.com", "A", "192.0.2.1"}, +// {"example.com", "AAAA", "2001:db8::2"}, +// ... +// If an RRset is associated with an RRSIG, the RRSIG must immediately follow +// the RRset to be signed. Currently, only one (or zero) RRSIG can be +// specified per RRset. +// +// Names are sorted internally, and don't have to be sorted in the data. +// +// A zone is defined in the form of ZoneData{}, which contains: +// zone name (character string) +// RRclass (character string) +// A pointer to in-zone RRs in the form of RRData{} +// A pointer to glue RRs in the form of RRData{} +// Glues can be omitted, in which case a convenient constant "empty_records" +// can be specified. + +// For simplicity we use the same single TTL for all test RRs. +const uint32_t TEST_TTL = 3600; + +struct RRData { + const char* const name; + const char* const rrtype; + const char* const rdata; +}; + +struct ZoneData { + const char* const zone_name; + const char* const rrclass; + const struct RRData* records; + const struct RRData* glue_records; +}; + +// +// zone data for example.com +// +const struct RRData example_com_records[] = { + // example.com + {"example.com", "NS", "dns01.example.com"}, + {"example.com", "NS", "dns02.example.com"}, + {"example.com", "NS", "dns03.example.com"}, + {"example.com", "RRSIG", "NS 5 2 3600 20100322084538 20100220084538 33495 example.com. ClcrfjkQZUY5L6ZlCkU3cJHzcrEGrofKSVeeoeZ+w6yeEowFNVXs2YBo3tom53DiCrdD9rs3feVSLGW5rjsz/O6lDuomgQG+EVSnWa7GTIPBXj1BmDXXp3XxeldYmhf4UzaN5BA+RUA5E8NChNKuNNof76j2S9tilfN/kvpy4fw="}, + {"example.com", "SOA", "master.example.com. admin.example.com. 1234 3600 1800 2419200 7200"}, + {"example.com", "RRSIG", "SOA 5 2 3600 20100322084538 20100220084538 33495 example.com. KUun66Qaw36osk2BJS6U1fAy3PPDkNo2QK4meGNbDBY8q8b+f2o+IXJ14YCvssGl1ORW0CcLnDRxssnk8V/Svmj5iFhO+8HC2hnVBdi2zewvdVtwRb+lWwKN7pkXXwuy6g1t9WCd/j5FCc/wgxqtZUTPb6XgZcnHrORDMOTqLs4="}, + {"example.com", "NSEC", "cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY"}, + {"example.com", "RRSIG", "NSEC 5 2 7200 20100322084538 20100220084538 33495 example.com. KxuVaPPKNPJzr/q+cJPiNlkHVTQK0LVsgTbSqruXQc25lAd0wn5oKUtxL1bEAchHkfA8eLzcYCj2ZqqAv9OJubw53mfskTad7UHs4Uj2RTrIsNGMCiZGgOpvNb9JcWpQtoyXVT1uNse+Qsbeir0eyeYIufUynFU041jtNrlJMio="}, + + // dns01.example.com + {"dns01.example.com", "A", "192.0.2.1"}, + {"dns01.example.com", "RRSIG", "A 5 3 3600 20100322084538 20100220084538 33495 example.com. NIawlZLk8WZAjNux7oQM2mslfW52OZFFkWt++7FHu2SU98XqEeKfCMnpgtWe5T8Nr9cS8df901iEOJoWQzGTEaHYUBtEhsSjBVn7mKp3fz6473a2xxy75SUKZ0rxjNXSZ8Q5rnFmkX0HTH2Sg51mtjH6aC2pfheQnA2t193BnSg="}, + {"dns01.example.com", "NSEC", "dns02.example.com. A RRSIG NSEC"}, + {"dns01.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. EkyeshmMNP9xiAz6mDFDIwksTdmkF9zsFzLuVKAgK6eUk7St6tp5PSvjA8nWol0vdvvz4LK85a4ffTFEiNRyvWeYP2vOhEkyDcrwuCd8Vc3jh/8Sm1Js+nX7hJStrZGFvp2TWPpt9nKH5p3MxXvTb/YVurnue0xSeFAE17O3+I0="}, + + // dns02.example.com + {"dns02.example.com", "A", "192.0.2.2"}, + {"dns02.example.com", "RRSIG", "A 5 3 3600 20100322084538 20100220084538 33495 example.com. XJtVMbUIRE0mk6Hn/Nx6k36jaxaBDPK2/IYB6vCQjJETz6gW4T6q/H/eY9/Lsw5iYPFhoBRDxT4XFj575t98kELXnJe1WhuMbRPlOhyOjxkLECaUne/sbFPOtbGFx9ohuojI0RgxxZiCFaO8wJuv6nfPuzmlLajWS6z9NZeOMIk="}, + {"dns02.example.com", "NSEC", "dns03.example.com. A RRSIG NSEC"}, + {"dns02.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. imBNTMB3sPU4kblcaAH6V7lCVt5xgtAybi3DA/SbLEulLaV2NE6vcoEn/AieaM4mOJicQnUDj/H+1hSEhzxU2tRM8zfVlvztxQWn6eh7ZR4mKfNDSvRUGU9ykhpwMyC7wjOt1j5bcSA/OTnLRAilslnJyOM4bSaxVEFo8YPjncY="}, + + // dns03.example.com + {"dns03.example.com", "A", "192.0.2.3"}, + {"dns03.example.com", "RRSIG", "A 5 3 3600 20100322084538 20100220084538 33495 example.com. Ubrcm1H+F6m8khle7P9zU8eO+Jtuj+1Vx1MM5KAkmZPJwQe9uTcoCpQa6DXOGG9kajDTnNN1Be1gkZuJDTZJG4SmJLXLbNY3RDnxpGmWta3qs/VgDq78/YM8ropt1/s7YKyrCfGE2ff+FUB0mLObiG01ZV2gu5HJzgE7SEWLEiI="}, + {"dns03.example.com", "NSEC", "foo.example.com. A RRSIG NSEC"}, + {"dns03.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. nn829Xw5CJFnPHwI9WHeT5epQv+odtCkHnjlPFGoPTLOyiks+041UmMqtq3uiSp4d2meMSe9UuDvoROT0L6NTtQQvVqiDhTn0irTFw1uw7fO8ZTG7eyu6Ypfz0+HvfbNvd4kMoD2OTgADRXPVsCTwK+PBOIIG9YTEQfl8pCqW5g="}, + + // www.example.com + {"www.example.com", "A", "192.0.2.1"}, + {"www.example.com", "RRSIG", "A 5 3 3600 20100322084538 20100220084538 33495 example.com. qyFyyV/mE8x4pdhudr5iycwhDsva31MzwO1kBR+bDKvzJg8mN8KxlPZrOlNNUhd3YRXQVwieMyxOTWRPXoxrNEDkNwimXkfe3rrHY7ibV9eNS4OIBUjb44VjCNr9CmQSzfuQ2yxO2r+YIuPYHRCjieD4xh6t9ay4IaCN/tDAJ+Q="}, + {"www.example.com", "NSEC", "example.com. A RRSIG NSEC"}, + {"www.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. ZLZlSVBa2oe4U+7SZASnypP2VkI5gg1/1cVGqYUvfYNIUkcVMWDgn7DZCfpmo+2vdlV/4VhAc+sjDd+X+e57XGnW8+lqZHvG6NMMhmSGmeATD3D+8lEJJGo0dxoN4rHJQyp/eT2S4nChz+D/ze+YRagYxGF7pXm9zcrw3kKZGTs="}, + + // *.wild.example.com + {"*.wild.example.com", "A", "192.0.2.2"}, + {"*.wild.example.com", "RRSIG", "A 5 3 3600 20100322084538 20100220084538 33495 example.com. FdO+UWONgtLKFxUzzygGunw67F9y8SzsP7yOLEYVJclRR8X3Ii62L0gtQHq2y0TcKsXttRsD6XY+tM5P/pgXlTNi7Bk4Fgb0PIDPjOsfT4DrS80kWn0YbinM/4/FA1j5ru5sTTboOY5UGhvDnoA9ogNuQQYb2/3wkoH0PrA2Q/0="}, + {"*.wild.example.com", "NSEC", "*.wild2.example.com. A RRSIG NSEC"}, + {"*.wild.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. OoGYslRj4xjZnBuzgOqsrvkDAHWycmQzbUxCRmgWnCbXiobJK7/ynONH3jm8G3vGlU0lwpHkhNs6cUK+6Nu8W49X3MT0Xksl/brroLcXYLi3vfxnYUNMMpXdeFl6WNNfoJRo90F/f/TWXAClRrDS29qiG3G1PEJZikIxZsZ0tyM="}, + + // *.wild2.example.com + {"*.wild2.example.com", "CNAME", "www.example.com"}, + {"*.wild2.example.com", "RRSIG", "CNAME 5 3 3600 20100410212307 20100311212307 33495 example.com. pGHtGdRBi4GKFSKszi6SsKvuBLDX8dFhZubU0tMojQ9SJuiFNF+WtxvdAYuUaoWP/9VLUaYmiw5u7JnzmR84DiXZPEs6DtD+UJdOZhaS7V7RTpE+tMOfVQBLpUnRWYtlTTmiBpFquzf3DdIxgUFhEPEuJJyp3LFRxJObCaq9 nvI="}, + {"*.wild2.example.com", "NSEC", "*.wild3.example.com. CNAME RRSIG NSEC"}, + {"*.wild2.example.com", "RRSIG", "NSEC 5 3 7200 20100410212307 20100311212307 33495 example.com. EuSzh6or8mbvwru2H7fyYeMpW6J8YZ528rabU38V/lMN0TdamghIuCneAvSNaZgwk2MSN1bWpZqB2kAipaM/ZI9/piLlTvVjjOQ8pjk0auwCEqT7Z7Qng3E92O9yVzO+WHT9QZn/fR6t60392In4IvcBGjZyjzQk8njIwbui xGA="}, + + // *.wild3.example.com -- a wildcard record with a lame CNAME + {"*.wild3.example.com", "CNAME", "spork.example.com"}, + {"*.wild3.example.com", "RRSIG", "CNAME 5 3 3600 20100410212307 20100311212307 33495 example.com. pGHtGdRBi4GKFSKszi6SsKvuBLDX8dFhZubU0tMojQ9SJuiFNF+WtxvdAYuUaoWP/9VLUaYmiw5u7JnzmR84DiXZPEs6DtD+UJdOZhaS7V7RTpE+tMOfVQBLpUnRWYtlTTmiBpFquzf3DdIxgUFhEPEuJJyp3LFRxJObCaq9 nvI="}, + {"*.wild3.example.com", "NSEC", "www.example.com. CNAME RRSIG NSEC"}, + {"*.wild3.example.com", "RRSIG", "NSEC 5 3 7200 20100410212307 20100311212307 33495 example.com. EuSzh6or8mbvwru2H7fyYeMpW6J8YZ528rabU38V/lMN0TdamghIuCneAvSNaZgwk2MSN1bWpZqB2kAipaM/ZI9/piLlTvVjjOQ8pjk0auwCEqT7Z7Qng3E92O9yVzO+WHT9QZn/fR6t60392In4IvcBGjZyjzQk8njIwbui xGA="}, + + // foo.example.com + {"foo.example.com", "CNAME", "cnametest.flame.org"}, + {"foo.example.com", "RRSIG", "CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. DSqkLnsh0gCeCPVW/Q8viy9GNP+KHmFGfWqyVG1S6koBtGN/VQQ16M4PHZ9Zssmf/JcDVJNIhAChHPE2WJiaPCNGTprsaUshf1Q2vMPVnkrJKgDY8SVRYMptmT8eaT0gGri4KhqRoFpMT5OYfesybwDgfhFSQQAh6ps3bIUsy4o="}, + {"foo.example.com", "NSEC", "mail.example.com. CNAME RRSIG NSEC"}, + {"foo.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. RTQwlSqui6StUYye1KCSOEr1d3irndWFqHBpwP7g7n+w8EDXJ8I7lYgwzHvlQt6BLAxe5fUDi7ct8M5hXvsm7FoWPZ5wXH+2/eJUCYxIw4vezKMkMwBP6M/YkJ2CMqY8DppYf60QaLDONQAr7AcK/naSyioeI5h6eaoVitUDMso="}, + + // cname-int.example.com + {"cname-int.example.com", "CNAME", "www.example.com."}, + {"cname-int.example.com", "RRSIG", "CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. U1wjt0XY9xjTwvUmWSUcfLGMhCjfX2ylWfHrycy50x2oxcK9z94E1ejen9wDTIEBSGYgi6wpZ8RK0+02N1DWTGpDqNXd7aFRfDrWQJ/q/XJHDx0vlcmhkWhrT82LBfKxkrptOzchuSo/c0mpK+mpiIMc1VOwY+yuQ2ALfcD6EHw="}, + {"cname-int.example.com", "NSEC", "dname.example.com. CNAME RRSIG NSEC"}, + {"cname-int.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. rbV+gaxfrsoha59NOLF4EFyWQ+GuFCVK/8D77x1atan3HNlXBlZ1smgudKTaJ3CtlobIDt0MEdPxY1yn2Tskw/5mlP1PWf8oaP3BwGSQdn4gLI8+sMpNOPFEdXpxqxngm2F6/7fqniL1QuSAQBEdO+5UiCAgnncPmAsSJg3u1zg="}, + + // cname-ext.example.com + {"cname-ext.example.com", "CNAME", "www.sql1.example.com"}, + {"cname-ext.example.com", "RRSIG", "CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. bGPIuZilyygvTThK4BrdECuaBcnZUgW/0d09iN2CrNjckchQl3dtbnMNirFsVs9hShDSldRNlQpiAVMpnPgXHhReNum7jmX6yqIH6s8GKIo91zr3VL/ramlezie5w4MilDHrxXLK2pb8IHmP+ZHivQ2EtdYQZgETWBWxr5FDfwk="}, + {"cname-ext.example.com", "NSEC", "cname-int.example.com. CNAME RRSIG NSEC"}, + {"cname-ext.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. inWsFwSDWG7TakjwbUTzTRpXz0WifelA5Kn3ABk6BVirIPmd+yQoNj2QZBDFAQwhnLPlNws2Oo4vgMsBMyx1Fv5eHgMUuCN3DUDaLlzlPtUb42CjOUa+jZBeTV/Hd7WZrirluASE1QFDprLdSSqoPPfAKvN3pORtW7y580dMOIM="}, + + // dname.example.com + {"dname.example.com", "DNAME", "sql1.example.com."}, + {"dname.example.com", "RRSIG", "DNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. ae8U47oaiwWdurkSyzcsCAF6DxBqjukizwF7K7U6lQVMtfoUE14oiAqfj1fjH8YLDOO/Hd1twrd/u0vgjnI1Gg32YTi7cYOzwE912SV1u2B/y0awaQKWPBwOW0aI7vxelt1vMUF81xosiQD04gOIdDBTqbHKcDxum87iWbhk4Ug="}, + {"dname.example.com", "NSEC", "dns01.example.com. DNAME RRSIG NSEC"}, + {"dname.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. c21Fff2D8vBrLzohBnUeflkaRdUAnUxAFGp+UQ0miACDCMOFBlCS9v9g/2+orOnKfd3l4vyz55C310t8JXgXb119ofaZWj2zkdUe+X8Bax+sMS0Y5K/sUhSNvbJbozr9UYPdvjSVBiWgh3s9fsb+etKq9uFukAzGU/FuGYpO0r0="}, + + // subzone.example.com + {"subzone.example.com", "NS", "ns1.subzone.example.com"}, + {"subzone.example.com", "NS", "ns2.subzone.example.com"}, + {"subzone.example.com", "NSEC", "*.wild.example.com. NS DS RRSIG NSEC"}, + {"subzone.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. Oe2kgIhsLtPJ4+lDZDxznV8/vEVoXKOBFN9lwWyebaKa19BaSXlQ+YVejmulmKDDjEucMvEfuItfn6w7bnU+DzOLk5D1lJCjwDlKz8u3xOAx16TiuQn4bgQAOiFtBQygmGGqO3BVpX+jxsmw7eH3emofy8uUqr/C4aopnwuf28g="}, + {"subzone.example.com", "DS", "33313 5 1 0FDD7A2C11AA7F55D50FBF9B7EDDA2322C541A8D"}, + {"subzone.example.com", "DS", "33313 5 2 00B99B7006F496D135B01AB17EDB469B4BE9E1973884DEA757BC4E3015A8C3AB"}, + {"subzone.example.com", "RRSIG", "DS 5 3 3600 20100322084538 20100220084538 33495 example.com. dIqZKvpkJN1l92SOiWgJh3KbjErIN+EfojMsm4pEdV5xQdZwj6DNNEu6Kw4rRwdvrZIu0TyqPr3jSJb7o6R7vZgZzmLfVV/ojQah7rwuYHCFcfyZ4JyK2311fMhRR1QAvMsdcjdyA1XC140Cm6AnL3cH5rh/KUks/0ec3Ca7GNQ="}, + + // subset of child zone: sql1 + {"sql1.example.com", "NS", "dns01.example.com"}, + {"sql1.example.com", "NS", "dns02.example.com"}, + {"sql1.example.com", "NS", "dns03.example.com"}, + + {"sql1.example.com", "DS", "33313 5 1 0FDD7A2C11AA7F55D50FBF9B7EDDA2322C541A8D"}, + {"sql1.example.com", "DS", "33313 5 2 00B99B7006F496D135B01AB17EDB469B4BE9E1973884DEA757BC4E3015A8C3AB"}, + {"sql1.example.com", "RRSIG", "DS 5 3 3600 20100322084538 20100220084538 33495 example.com. dIqZKvpkJN1l92SOiWgJh3KbjErIN+EfojMsm4pEdV5xQdZwj6DNNEu6Kw4rRwdvrZIu0TyqPr3jSJb7o6R7vZgZzmLfVV/ojQah7rwuYHCFcfyZ4JyK2311fMhRR1QAvMsdcjdyA1XC140Cm6AnL3cH5rh/KUks/0ec3Ca7GNQ="}, + {"sql1.example.com", "NSEC", "subzone.example.com. NS DS RRSIG NSEC"}, + {"sql1.example.com", "RRSIG", "NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. k9FRdFyk/cPdkmmaoZbGZPpzIzfbFWQ3QCHd2qhJa0xAXaEOT/GBL6aFqx9SlunDu2wgES+To5fWPZGi4NzWpp6c5t27rnATN/oCEQ/UYIJKmWbqrXdst0Ps5boznk7suK2Y+km31KxaIf3fDd/T3kZCVsR0aWKRRRatPb7GfLw="}, + + {NULL, NULL, NULL} +}; +const struct RRData example_com_glue_records[] = { + {"ns1.subzone.example.com", "A", "192.0.2.1"}, + {"ns2.subzone.example.com", "A", "192.0.2.2"}, + {NULL, NULL, NULL} +}; + +// +// zone data for sql1.example.com +// +const struct RRData sql1_example_com_records[] = { + {"sql1.example.com", "NS", "dns01.example.com"}, + {"sql1.example.com", "NS", "dns02.example.com"}, + {"sql1.example.com", "NS", "dns03.example.com"}, + {"sql1.example.com", "RRSIG", "NS 5 3 3600 20100322084536 20100220084536 12447 sql1.example.com. 0CL8noy0NSgoWwuKd+Dc6vyIIw2BrAEBx0IJzcSB6GlB25x/zjEd6AJG0be13HN6jOaTX8iWTuCVrEYuXg76V+M4EvTZHjEScj0az74TrDv4Vdo459paGKCX9B8NLJW1mW4fzZrrXQ8jmBEZeS91Q5rJrO+UKJEuUz3LYdTPvao="}, + {"sql1.example.com", "SOA", "master.example.com. admin.example.com. 678 3600 1800 2419200 7200"}, + {"sql1.example.com", "RRSIG", "SOA 5 3 3600 20100322084536 20100220084536 12447 sql1.example.com. oakulfyljL/RAKgCKXEZ3KsG8BJj5WG4JK4moWFB6c9OKem6jIk8hKP2XlUVXFuOYJlRdIM4KicmR2GAK+5jJp6z5ShssstYTXo3QosVm6oCKumuFeLFHzcjfqP1D+F9NsvHldJIBnS/4ebPkmR5OENyCZXQF5HmN2awIj4CLjE="}, + {"sql1.example.com", "NSEC", "www.sql1.example.com. NS SOA RRSIG NSEC DNSKEY"}, + {"sql1.example.com", "RRSIG", "NSEC 5 3 7200 20100322084536 20100220084536 12447 sql1.example.com. v71CgdTYccCiTqfRcn6HsvISQa8ruvUfCKtpwym0RW/G27xlZn8otj2IMtWwkLxti8Rqqu+PTViLaOIbeVfHBcqzAd7U59cAOYoq3ODZx6auiE3C23HAKqUavKcP7Esaajm1cbcWy6Kyie4CAZc8M7EeKxgkXMKJGqBQzF+/FOo="}, + + // www.sql1.example.com + {"www.sql1.example.com", "A", "192.0.2.2"}, + {"www.sql1.example.com", "RRSIG", "A 5 4 3600 20100322084536 20100220084536 12447 sql1.example.com. DNdVKxB3oBsB14NPoV9WG14Y/g4zMcIXLYnFjj9vRZRZJpAvbTEipiXlayuhOxnqU827OipETQyeULZmLsqIQ1wK4Fgf+9b5aJ8D85/o4wBka00X4hZ3MwDPRb4mjuogwBTBg5NRpNSzUfbkPGiav08BFwgg+Efm9veSB05arS0="}, + {"www.sql1.example.com", "NSEC", "sql1.example.com. A RRSIG NSEC"}, + {"www.sql1.example.com", "RRSIG", "NSEC 5 4 7200 20100322084536 20100220084536 12447 sql1.example.com. cJMJhDx/ND7/9j3zhyXe+6eaSsU7ByYpXhJzbe+OhjFgH0VasQXq7o1QB3I293UZ+yhkjgXap+9QtPlraaNaYyTyOMQ42OoxSefJpYz9CME/FI2tsUfyrCnLFxYRNet7sMS0q+hLqxRayuEHDFDp72hHPGLJQ8a7jq4SrIonT50="}, + + {NULL, NULL, NULL} +}; + +// +// zone data for loop.example +// +const struct RRData loop_example_records[] = { + {"loop.example", "SOA", "master.loop.example admin.loop.example. " + "1234 3600 1800 2419200 7200"}, + {"loop.example", "NS", "ns.loop.example"}, + {"one.loop.example", "CNAME", "two.loop.example"}, + {"two.loop.example", "CNAME", "one.loop.example"}, + {NULL, NULL, NULL} +}; + +// +// zone data for nons.example +// +const struct RRData nons_example_records[] = { + {"nons.example", "SOA", "master.nons.example admin.nons.example. " + "1234 3600 1800 2419200 7200"}, + {"www.nons.example", "A", "192.0.2.1"}, + {"ns.nons.example", "A", "192.0.2.2"}, + {NULL, NULL, NULL} +}; + +// +// zone data for nons-dname.example +// +const struct RRData nonsdname_example_records[] = { + {"nons-dname.example", "SOA", "master.nons-dname.example " + "admin.nons-dname.example. 1234 3600 1800 2419200 7200"}, + {"nons-dname.example", "DNAME", "example.org"}, + {"www.nons-dname.example", "A", "192.0.2.1"}, + {"ns.nons-dname.example", "A", "192.0.2.2"}, + {NULL, NULL, NULL} +}; + +// +// zone data for nons-dname.example +// +const struct RRData nosoa_example_records[] = { + {"nosoa.example", "NS", "ns.nosoa.example"}, + {"www.nosoa.example", "A", "192.0.2.1"}, + {"ns.nosoa.example", "A", "192.0.2.2"}, + {NULL, NULL, NULL} +}; + +// +// empty data set, for convenience. +// +const struct RRData empty_records[] = { + {NULL, NULL, NULL} +}; + +// +// test zones +// +const struct ZoneData zone_data[] = { + { "example.com", "IN", example_com_records, example_com_glue_records }, + { "sql1.example.com", "IN", sql1_example_com_records, empty_records }, + { "loop.example", "IN", loop_example_records, empty_records }, + { "nons.example", "IN", nons_example_records, empty_records }, + { "nons-dname.example", "IN", nonsdname_example_records, empty_records }, + { "nosoa.example", "IN", nosoa_example_records, empty_records } +}; +const size_t NUM_ZONES = sizeof(zone_data) / sizeof(zone_data[0]); + +struct Zone { + Zone(const char* const name, const char* const class_txt) : + zone_name(Name(name)), rrclass(class_txt) + {} + Name zone_name; + RRClass rrclass; + vector names; + vector rrsets; +}; +vector zones; } DataSrc::Result @@ -110,359 +307,54 @@ TestDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) return init(); } +void +buildZone(Zone& zone, const RRData* records, const bool is_glue) { + RRsetPtr prev_rrset; + for (int i = 0; records[i].name != NULL; ++i) { + Name name(records[i].name); + RRType rrtype(records[i].rrtype); + RRsetPtr rrset; + bool new_name = false; + + if (!prev_rrset || prev_rrset->getName() != name) { + if (!is_glue) { + zone.names.push_back(name); + } + new_name = true; + } + + if (new_name || prev_rrset->getType() != rrtype) { + rrset = RRsetPtr(new RRset(name, zone.rrclass, rrtype, + RRTTL(TEST_TTL))); + if (rrtype != RRType::RRSIG()) { + zone.rrsets.push_back(rrset); + } + } else { + rrset = prev_rrset; + } + rrset->addRdata(createRdata(rrtype, zone.rrclass, records[i].rdata)); + if (rrtype == RRType::RRSIG()) { + prev_rrset->addRRsig(rrset); + } + prev_rrset = rrset; + } +} + DataSrc::Result TestDataSrc::init() { if (initialized) { return (SUCCESS); } - RRset* rp; - RRsetPtr rrsig; - - // example.com - example_ns = RRsetPtr(new RRset(example, RRClass::IN(), - RRType::NS(), RRTTL(3600))); - example_ns->addRdata(generic::NS(dns01)); - example_ns->addRdata(generic::NS(dns02)); - example_ns->addRdata(generic::NS(dns03)); - - rp = new RRset(example, RRClass::IN(), RRType::RRSIG(), RRTTL(3600)); - rrsig = RRsetPtr(rp); - rrsig->addRdata(generic::RRSIG("NS 5 2 3600 20100322084538 20100220084538 33495 example.com. ClcrfjkQZUY5L6ZlCkU3cJHzcrEGrofKSVeeoeZ+w6yeEowFNVXs2YBo3tom53DiCrdD9rs3feVSLGW5rjsz/O6lDuomgQG+EVSnWa7GTIPBXj1BmDXXp3XxeldYmhf4UzaN5BA+RUA5E8NChNKuNNof76j2S9tilfN/kvpy4fw=")); - example_ns->addRRsig(rrsig); - - example_soa = RRsetPtr(new RRset(example, RRClass::IN(), - RRType::SOA(), RRTTL(3600))); - example_soa->addRdata(generic::SOA("master.example.com. admin.example.com. 1234 3600 1800 2419200 7200")); - - rrsig = RRsetPtr(new RRset(example, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("SOA 5 2 3600 20100322084538 20100220084538 33495 example.com. KUun66Qaw36osk2BJS6U1fAy3PPDkNo2QK4meGNbDBY8q8b+f2o+IXJ14YCvssGl1ORW0CcLnDRxssnk8V/Svmj5iFhO+8HC2hnVBdi2zewvdVtwRb+lWwKN7pkXXwuy6g1t9WCd/j5FCc/wgxqtZUTPb6XgZcnHrORDMOTqLs4=")); - example_soa->addRRsig(rrsig); - - example_nsec = RRsetPtr(new RRset(example, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - example_nsec->addRdata(generic::NSEC("cname-ext.example.com. NS SOA MX RRSIG NSEC DNSKEY")); - rrsig = RRsetPtr(new RRset(example, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 2 7200 20100322084538 20100220084538 33495 example.com. KxuVaPPKNPJzr/q+cJPiNlkHVTQK0LVsgTbSqruXQc25lAd0wn5oKUtxL1bEAchHkfA8eLzcYCj2ZqqAv9OJubw53mfskTad7UHs4Uj2RTrIsNGMCiZGgOpvNb9JcWpQtoyXVT1uNse+Qsbeir0eyeYIufUynFU041jtNrlJMio=")); - example_nsec->addRRsig(rrsig); - - // sql1.example.com - sql1_ns = RRsetPtr(new RRset(sql1, RRClass::IN(), - RRType::NS(), RRTTL(3600))); - sql1_ns->addRdata(generic::NS(dns01)); - sql1_ns->addRdata(generic::NS(dns02)); - sql1_ns->addRdata(generic::NS(dns03)); - - rrsig = RRsetPtr(new RRset(sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NS 5 3 3600 20100322084536 20100220084536 12447 sql1.example.com. 0CL8noy0NSgoWwuKd+Dc6vyIIw2BrAEBx0IJzcSB6GlB25x/zjEd6AJG0be13HN6jOaTX8iWTuCVrEYuXg76V+M4EvTZHjEScj0az74TrDv4Vdo459paGKCX9B8NLJW1mW4fzZrrXQ8jmBEZeS91Q5rJrO+UKJEuUz3LYdTPvao=")); - sql1_ns->addRRsig(rrsig); - - sql1_soa = RRsetPtr(new RRset(sql1, RRClass::IN(), - RRType::SOA(), RRTTL(3600))); - sql1_soa->addRdata(generic::SOA("master.example.com. admin.example.com. 678 3600 1800 2419200 7200")); - - rrsig = RRsetPtr(new RRset(sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("SOA 5 3 3600 20100322084536 20100220084536 12447 sql1.example.com. oakulfyljL/RAKgCKXEZ3KsG8BJj5WG4JK4moWFB6c9OKem6jIk8hKP2XlUVXFuOYJlRdIM4KicmR2GAK+5jJp6z5ShssstYTXo3QosVm6oCKumuFeLFHzcjfqP1D+F9NsvHldJIBnS/4ebPkmR5OENyCZXQF5HmN2awIj4CLjE=")); - sql1_soa->addRRsig(rrsig); - - sql1_nsec = RRsetPtr(new RRset(sql1, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - sql1_nsec->addRdata(generic::NSEC("www.sql1.example.com. NS SOA RRSIG NSEC DNSKEY")); - rrsig = RRsetPtr(new RRset(sql1, RRClass::IN(), RRType::RRSIG(), RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084536 20100220084536 12447 sql1.example.com. v71CgdTYccCiTqfRcn6HsvISQa8ruvUfCKtpwym0RW/G27xlZn8otj2IMtWwkLxti8Rqqu+PTViLaOIbeVfHBcqzAd7U59cAOYoq3ODZx6auiE3C23HAKqUavKcP7Esaajm1cbcWy6Kyie4CAZc8M7EeKxgkXMKJGqBQzF+/FOo=")); - sql1_nsec->addRRsig(rrsig); - sql1_ds = RRsetPtr(new RRset(sql1, RRClass::IN(), - RRType::DS(), RRTTL(3600))); - sql1_ds->addRdata(generic::DS("33313 5 1 0FDD7A2C11AA7F55D50FBF9B7EDDA2322C541A8D")); - sql1_ds->addRdata(generic::DS("33313 5 2 00B99B7006F496D135B01AB17EDB469B4BE9E1973884DEA757BC4E3015A8C3AB")); - - rrsig = RRsetPtr(new RRset(sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("DS 5 3 3600 20100322084538 20100220084538 33495 example.com. dIqZKvpkJN1l92SOiWgJh3KbjErIN+EfojMsm4pEdV5xQdZwj6DNNEu6Kw4rRwdvrZIu0TyqPr3jSJb7o6R7vZgZzmLfVV/ojQah7rwuYHCFcfyZ4JyK2311fMhRR1QAvMsdcjdyA1XC140Cm6AnL3cH5rh/KUks/0ec3Ca7GNQ=")); - sql1_ds->addRRsig(rrsig); - - - sql1_ds_nsec = RRsetPtr(new RRset(sql1, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - sql1_ds_nsec->addRdata(generic::NSEC("subzone.example.com. NS DS RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. k9FRdFyk/cPdkmmaoZbGZPpzIzfbFWQ3QCHd2qhJa0xAXaEOT/GBL6aFqx9SlunDu2wgES+To5fWPZGi4NzWpp6c5t27rnATN/oCEQ/UYIJKmWbqrXdst0Ps5boznk7suK2Y+km31KxaIf3fDd/T3kZCVsR0aWKRRRatPb7GfLw=")); - sql1_ds_nsec->addRRsig(rrsig); - - // www.sql1.example.com - www_sql1_a = RRsetPtr(new RRset(www_sql1, - RRClass::IN(), RRType::A(), - RRTTL(3600))); - www_sql1_a->addRdata(in::A("192.0.2.2")); - - rrsig = RRsetPtr(new RRset(www_sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 4 3600 20100322084536 20100220084536 12447 sql1.example.com. DNdVKxB3oBsB14NPoV9WG14Y/g4zMcIXLYnFjj9vRZRZJpAvbTEipiXlayuhOxnqU827OipETQyeULZmLsqIQ1wK4Fgf+9b5aJ8D85/o4wBka00X4hZ3MwDPRb4mjuogwBTBg5NRpNSzUfbkPGiav08BFwgg+Efm9veSB05arS0=")); - www_sql1_a->addRRsig(rrsig); - - www_sql1_nsec = RRsetPtr(new RRset(www_sql1, - RRClass::IN(), RRType::NSEC(), - RRTTL(3600))); - www_sql1_nsec->addRdata(generic::NSEC("sql1.example.com. A RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(www_sql1, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 4 7200 20100322084536 20100220084536 12447 sql1.example.com. cJMJhDx/ND7/9j3zhyXe+6eaSsU7ByYpXhJzbe+OhjFgH0VasQXq7o1QB3I293UZ+yhkjgXap+9QtPlraaNaYyTyOMQ42OoxSefJpYz9CME/FI2tsUfyrCnLFxYRNet7sMS0q+hLqxRayuEHDFDp72hHPGLJQ8a7jq4SrIonT50=")); - www_sql1_nsec->addRRsig(rrsig); - - // dns01.example.com - dns01_a = RRsetPtr(new RRset(dns01, - RRClass::IN(), RRType::A(), - RRTTL(3600))); - dns01_a->addRdata(in::A("192.0.2.1")); - - rrsig = RRsetPtr(new RRset(dns01, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 3 3600 20100322084538 20100220084538 33495 example.com. NIawlZLk8WZAjNux7oQM2mslfW52OZFFkWt++7FHu2SU98XqEeKfCMnpgtWe5T8Nr9cS8df901iEOJoWQzGTEaHYUBtEhsSjBVn7mKp3fz6473a2xxy75SUKZ0rxjNXSZ8Q5rnFmkX0HTH2Sg51mtjH6aC2pfheQnA2t193BnSg=")); - dns01_a->addRRsig(rrsig); - - dns01_nsec = RRsetPtr(new RRset(dns01, RRClass::IN(), RRType::NSEC(), RRTTL(3600))); - dns01_nsec->addRdata(generic::NSEC("dns02.example.com. A RRSIG NSEC")); - - rrsig = RRsetPtr(new RRset(dns01, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. EkyeshmMNP9xiAz6mDFDIwksTdmkF9zsFzLuVKAgK6eUk7St6tp5PSvjA8nWol0vdvvz4LK85a4ffTFEiNRyvWeYP2vOhEkyDcrwuCd8Vc3jh/8Sm1Js+nX7hJStrZGFvp2TWPpt9nKH5p3MxXvTb/YVurnue0xSeFAE17O3+I0=")); - dns01_nsec->addRRsig(rrsig); - - // dns02.example.com - dns02_a = RRsetPtr(new RRset(dns02, RRClass::IN(), RRType::A(), RRTTL(3600))); - dns02_a->addRdata(in::A("192.0.2.2")); - - rrsig = RRsetPtr(new RRset(dns02, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 3 3600 20100322084538 20100220084538 33495 example.com. XJtVMbUIRE0mk6Hn/Nx6k36jaxaBDPK2/IYB6vCQjJETz6gW4T6q/H/eY9/Lsw5iYPFhoBRDxT4XFj575t98kELXnJe1WhuMbRPlOhyOjxkLECaUne/sbFPOtbGFx9ohuojI0RgxxZiCFaO8wJuv6nfPuzmlLajWS6z9NZeOMIk=")); - dns02_a->addRRsig(rrsig); - - dns02_nsec = RRsetPtr(new RRset(dns02, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - dns02_nsec->addRdata(generic::NSEC("dns03.example.com. A RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(dns02, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. imBNTMB3sPU4kblcaAH6V7lCVt5xgtAybi3DA/SbLEulLaV2NE6vcoEn/AieaM4mOJicQnUDj/H+1hSEhzxU2tRM8zfVlvztxQWn6eh7ZR4mKfNDSvRUGU9ykhpwMyC7wjOt1j5bcSA/OTnLRAilslnJyOM4bSaxVEFo8YPjncY=")); - dns02_nsec->addRRsig(rrsig); - - // dns03.example.com - dns03_a = RRsetPtr(new RRset(dns03, - RRClass::IN(), RRType::A(), - RRTTL(3600))); - dns03_a->addRdata(in::A("192.0.2.3")); - - rrsig = RRsetPtr(new RRset(dns03, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 3 3600 20100322084538 20100220084538 33495 example.com. Ubrcm1H+F6m8khle7P9zU8eO+Jtuj+1Vx1MM5KAkmZPJwQe9uTcoCpQa6DXOGG9kajDTnNN1Be1gkZuJDTZJG4SmJLXLbNY3RDnxpGmWta3qs/VgDq78/YM8ropt1/s7YKyrCfGE2ff+FUB0mLObiG01ZV2gu5HJzgE7SEWLEiI=")); - dns03_a->addRRsig(rrsig); - - dns03_nsec = RRsetPtr(new RRset(dns03, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - dns03_nsec->addRdata(generic::NSEC("foo.example.com. A RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(dns03, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. nn829Xw5CJFnPHwI9WHeT5epQv+odtCkHnjlPFGoPTLOyiks+041UmMqtq3uiSp4d2meMSe9UuDvoROT0L6NTtQQvVqiDhTn0irTFw1uw7fO8ZTG7eyu6Ypfz0+HvfbNvd4kMoD2OTgADRXPVsCTwK+PBOIIG9YTEQfl8pCqW5g=")); - dns03_nsec->addRRsig(rrsig); - - // www.example.com - www_a = RRsetPtr(new RRset(www, RRClass::IN(), RRType::A(), - RRTTL(3600))); - www_a->addRdata(in::A("192.0.2.1")); - - rrsig = RRsetPtr(new RRset(www, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 3 3600 20100322084538 20100220084538 33495 example.com. qyFyyV/mE8x4pdhudr5iycwhDsva31MzwO1kBR+bDKvzJg8mN8KxlPZrOlNNUhd3YRXQVwieMyxOTWRPXoxrNEDkNwimXkfe3rrHY7ibV9eNS4OIBUjb44VjCNr9CmQSzfuQ2yxO2r+YIuPYHRCjieD4xh6t9ay4IaCN/tDAJ+Q=")); - www_a->addRRsig(rrsig); - - www_nsec = RRsetPtr(new RRset(www, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - www_nsec->addRdata(generic::NSEC("example.com. A RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(www, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. ZLZlSVBa2oe4U+7SZASnypP2VkI5gg1/1cVGqYUvfYNIUkcVMWDgn7DZCfpmo+2vdlV/4VhAc+sjDd+X+e57XGnW8+lqZHvG6NMMhmSGmeATD3D+8lEJJGo0dxoN4rHJQyp/eT2S4nChz+D/ze+YRagYxGF7pXm9zcrw3kKZGTs=")); - www_nsec->addRRsig(rrsig); - - // *.wild.example.com - wild_a = RRsetPtr(new RRset(wild, RRClass::IN(), RRType::A(), - RRTTL(3600))); - wild_a->addRdata(in::A("192.0.2.2")); - - rrsig = RRsetPtr(new RRset(wild, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("A 5 3 3600 20100322084538 20100220084538 33495 example.com. FdO+UWONgtLKFxUzzygGunw67F9y8SzsP7yOLEYVJclRR8X3Ii62L0gtQHq2y0TcKsXttRsD6XY+tM5P/pgXlTNi7Bk4Fgb0PIDPjOsfT4DrS80kWn0YbinM/4/FA1j5ru5sTTboOY5UGhvDnoA9ogNuQQYb2/3wkoH0PrA2Q/0=")); - wild_a->addRRsig(rrsig); - - wild_nsec = RRsetPtr(new RRset(wild, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - wild_nsec->addRdata(generic::NSEC("*.wild2.example.com. A RRSIG NSEC")); - - rrsig = RRsetPtr(new RRset(wild, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. OoGYslRj4xjZnBuzgOqsrvkDAHWycmQzbUxCRmgWnCbXiobJK7/ynONH3jm8G3vGlU0lwpHkhNs6cUK+6Nu8W49X3MT0Xksl/brroLcXYLi3vfxnYUNMMpXdeFl6WNNfoJRo90F/f/TWXAClRrDS29qiG3G1PEJZikIxZsZ0tyM=")); - wild_nsec->addRRsig(rrsig); - - // *.wild2.example.com - wild2_cname = RRsetPtr(new RRset(wild2, RRClass::IN(), RRType::CNAME(), - RRTTL(3600))); - wild2_cname->addRdata(generic::CNAME("www.example.com")); - - rrsig = RRsetPtr(new RRset(wild2, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("CNAME 5 3 3600 20100410212307 20100311212307 33495 example.com. pGHtGdRBi4GKFSKszi6SsKvuBLDX8dFhZubU0tMojQ9SJuiFNF+WtxvdAYuUaoWP/9VLUaYmiw5u7JnzmR84DiXZPEs6DtD+UJdOZhaS7V7RTpE+tMOfVQBLpUnRWYtlTTmiBpFquzf3DdIxgUFhEPEuJJyp3LFRxJObCaq9 nvI=")); - wild2_cname->addRRsig(rrsig); - - wild2_nsec = RRsetPtr(new RRset(wild2, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - wild2_nsec->addRdata(generic::NSEC("*.wild3.example.com. CNAME RRSIG NSEC")); - - rrsig = RRsetPtr(new RRset(wild2, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100410212307 20100311212307 33495 example.com. EuSzh6or8mbvwru2H7fyYeMpW6J8YZ528rabU38V/lMN0TdamghIuCneAvSNaZgwk2MSN1bWpZqB2kAipaM/ZI9/piLlTvVjjOQ8pjk0auwCEqT7Z7Qng3E92O9yVzO+WHT9QZn/fR6t60392In4IvcBGjZyjzQk8njIwbui xGA=")); - wild2_nsec->addRRsig(rrsig); - - // *.wild3.example.com -- a wildcard record with a lame CNAME - wild3_cname = RRsetPtr(new RRset(wild3, RRClass::IN(), RRType::CNAME(), - RRTTL(3600))); - wild3_cname->addRdata(generic::CNAME("spork.example.com")); - - rrsig = RRsetPtr(new RRset(wild3, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("CNAME 5 3 3600 20100410212307 20100311212307 33495 example.com. pGHtGdRBi4GKFSKszi6SsKvuBLDX8dFhZubU0tMojQ9SJuiFNF+WtxvdAYuUaoWP/9VLUaYmiw5u7JnzmR84DiXZPEs6DtD+UJdOZhaS7V7RTpE+tMOfVQBLpUnRWYtlTTmiBpFquzf3DdIxgUFhEPEuJJyp3LFRxJObCaq9 nvI=")); - wild3_cname->addRRsig(rrsig); - - wild3_nsec = RRsetPtr(new RRset(wild3, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - wild3_nsec->addRdata(generic::NSEC("www.example.com. CNAME RRSIG NSEC")); - - rrsig = RRsetPtr(new RRset(wild3, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100410212307 20100311212307 33495 example.com. EuSzh6or8mbvwru2H7fyYeMpW6J8YZ528rabU38V/lMN0TdamghIuCneAvSNaZgwk2MSN1bWpZqB2kAipaM/ZI9/piLlTvVjjOQ8pjk0auwCEqT7Z7Qng3E92O9yVzO+WHT9QZn/fR6t60392In4IvcBGjZyjzQk8njIwbui xGA=")); - wild3_nsec->addRRsig(rrsig); - - // foo.example.com - foo_cname = RRsetPtr(new RRset(foo, RRClass::IN(), RRType::CNAME(), - RRTTL(3600))); - foo_cname->addRdata(generic::CNAME("cnametest.flame.org")); - - rrsig = RRsetPtr(new RRset(foo, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. DSqkLnsh0gCeCPVW/Q8viy9GNP+KHmFGfWqyVG1S6koBtGN/VQQ16M4PHZ9Zssmf/JcDVJNIhAChHPE2WJiaPCNGTprsaUshf1Q2vMPVnkrJKgDY8SVRYMptmT8eaT0gGri4KhqRoFpMT5OYfesybwDgfhFSQQAh6ps3bIUsy4o=")); - foo_cname->addRRsig(rrsig); - - foo_nsec = RRsetPtr(new RRset(foo, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - foo_nsec->addRdata(generic::NSEC("mail.example.com. CNAME RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(foo, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. RTQwlSqui6StUYye1KCSOEr1d3irndWFqHBpwP7g7n+w8EDXJ8I7lYgwzHvlQt6BLAxe5fUDi7ct8M5hXvsm7FoWPZ5wXH+2/eJUCYxIw4vezKMkMwBP6M/YkJ2CMqY8DppYf60QaLDONQAr7AcK/naSyioeI5h6eaoVitUDMso=")); - foo_nsec->addRRsig(rrsig); - - // cname-int.example.com - cnameint_cname = RRsetPtr(new RRset(cnameint, RRClass::IN(), - RRType::CNAME(), RRTTL(3600))); - cnameint_cname->addRdata(generic::CNAME("www.example.com.")); - - rrsig = RRsetPtr(new RRset(cnameint, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. U1wjt0XY9xjTwvUmWSUcfLGMhCjfX2ylWfHrycy50x2oxcK9z94E1ejen9wDTIEBSGYgi6wpZ8RK0+02N1DWTGpDqNXd7aFRfDrWQJ/q/XJHDx0vlcmhkWhrT82LBfKxkrptOzchuSo/c0mpK+mpiIMc1VOwY+yuQ2ALfcD6EHw=")); - cnameint_cname->addRRsig(rrsig); - - cnameint_nsec = RRsetPtr(new RRset(cnameint, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - cnameint_nsec->addRdata(generic::NSEC("dname.example.com. CNAME RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(cnameint, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. rbV+gaxfrsoha59NOLF4EFyWQ+GuFCVK/8D77x1atan3HNlXBlZ1smgudKTaJ3CtlobIDt0MEdPxY1yn2Tskw/5mlP1PWf8oaP3BwGSQdn4gLI8+sMpNOPFEdXpxqxngm2F6/7fqniL1QuSAQBEdO+5UiCAgnncPmAsSJg3u1zg=")); - cnameint_nsec->addRRsig(rrsig); - - // cname-ext.example.com - cnameext_cname = RRsetPtr(new RRset(cnameext, RRClass::IN(), - RRType::CNAME(), RRTTL(3600))); - cnameext_cname->addRdata(generic::CNAME("www.sql1.example.com")); - - rrsig = RRsetPtr(new RRset(cnameext, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("CNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. bGPIuZilyygvTThK4BrdECuaBcnZUgW/0d09iN2CrNjckchQl3dtbnMNirFsVs9hShDSldRNlQpiAVMpnPgXHhReNum7jmX6yqIH6s8GKIo91zr3VL/ramlezie5w4MilDHrxXLK2pb8IHmP+ZHivQ2EtdYQZgETWBWxr5FDfwk=")); - cnameext_cname->addRRsig(rrsig); - - cnameext_nsec = RRsetPtr(new RRset(cnameext, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - cnameext_nsec->addRdata(generic::NSEC("cname-int.example.com. CNAME RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(cnameext, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. inWsFwSDWG7TakjwbUTzTRpXz0WifelA5Kn3ABk6BVirIPmd+yQoNj2QZBDFAQwhnLPlNws2Oo4vgMsBMyx1Fv5eHgMUuCN3DUDaLlzlPtUb42CjOUa+jZBeTV/Hd7WZrirluASE1QFDprLdSSqoPPfAKvN3pORtW7y580dMOIM=")); - cnameext_nsec->addRRsig(rrsig); - - // dname.example.com - dname_dname = RRsetPtr(new RRset(dname, RRClass::IN(), RRType::DNAME(), - RRTTL(3600))); - dname_dname->addRdata(generic::DNAME("sql1.example.com.")); - - rrsig = RRsetPtr(new RRset(dname, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("DNAME 5 3 3600 20100322084538 20100220084538 33495 example.com. ae8U47oaiwWdurkSyzcsCAF6DxBqjukizwF7K7U6lQVMtfoUE14oiAqfj1fjH8YLDOO/Hd1twrd/u0vgjnI1Gg32YTi7cYOzwE912SV1u2B/y0awaQKWPBwOW0aI7vxelt1vMUF81xosiQD04gOIdDBTqbHKcDxum87iWbhk4Ug=")); - dname_dname->addRRsig(rrsig); - - dname_nsec = RRsetPtr(new RRset(dname, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - dname_nsec->addRdata(generic::NSEC("dns01.example.com. DNAME RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(dname, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. c21Fff2D8vBrLzohBnUeflkaRdUAnUxAFGp+UQ0miACDCMOFBlCS9v9g/2+orOnKfd3l4vyz55C310t8JXgXb119ofaZWj2zkdUe+X8Bax+sMS0Y5K/sUhSNvbJbozr9UYPdvjSVBiWgh3s9fsb+etKq9uFukAzGU/FuGYpO0r0=")); - dname_nsec->addRRsig(rrsig); - - // subzone.example.com - subzone_ns = RRsetPtr(new RRset(subzone, RRClass::IN(), RRType::NS(), - RRTTL(3600))); - subzone_ns->addRdata(generic::NS(Name("ns1.subzone.example.com"))); - subzone_ns->addRdata(generic::NS(Name("ns2.subzone.example.com"))); - - subzone_ds = RRsetPtr(new RRset(subzone, RRClass::IN(), RRType::DS(), - RRTTL(3600))); - - subzone_glue1 = RRsetPtr(new RRset(Name("ns1.subzone.example.com"), - RRClass::IN(), RRType::A(), - RRTTL(3600))); - subzone_glue1->addRdata(in::A("192.0.2.1")); - subzone_glue2 = RRsetPtr(new RRset(Name("ns2.subzone.example.com"), - RRClass::IN(), RRType::A(), - RRTTL(3600))); - subzone_glue2->addRdata(in::A("192.0.2.2")); - - subzone_ds = RRsetPtr(new RRset(subzone, RRClass::IN(), RRType::DS(), - RRTTL(3600))); - - subzone_ds->addRdata(generic::DS("33313 5 1 0FDD7A2C11AA7F55D50FBF9B7EDDA2322C541A8D")); - subzone_ds->addRdata(generic::DS("33313 5 2 00B99B7006F496D135B01AB17EDB469B4BE9E1973884DEA757BC4E3015A8C3AB")); - - rrsig = RRsetPtr(new RRset(subzone, RRClass::IN(), RRType::RRSIG(), - RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("DS 5 3 3600 20100322084538 20100220084538 33495 example.com. dIqZKvpkJN1l92SOiWgJh3KbjErIN+EfojMsm4pEdV5xQdZwj6DNNEu6Kw4rRwdvrZIu0TyqPr3jSJb7o6R7vZgZzmLfVV/ojQah7rwuYHCFcfyZ4JyK2311fMhRR1QAvMsdcjdyA1XC140Cm6AnL3cH5rh/KUks/0ec3Ca7GNQ=")); - subzone_ds->addRRsig(rrsig); - - subzone_nsec = RRsetPtr(new RRset(subzone, RRClass::IN(), - RRType::NSEC(), RRTTL(3600))); - subzone_nsec->addRdata(generic::NSEC("*.wild.example.com. NS DS RRSIG NSEC")); - rrsig = RRsetPtr(new RRset(subzone, RRClass::IN(), RRType::RRSIG(), RRTTL(3600))); - rrsig->addRdata(generic::RRSIG("NSEC 5 3 7200 20100322084538 20100220084538 33495 example.com. Oe2kgIhsLtPJ4+lDZDxznV8/vEVoXKOBFN9lwWyebaKa19BaSXlQ+YVejmulmKDDjEucMvEfuItfn6w7bnU+DzOLk5D1lJCjwDlKz8u3xOAx16TiuQn4bgQAOiFtBQygmGGqO3BVpX+jxsmw7eH3emofy8uUqr/C4aopnwuf28g=")); - subzone_nsec->addRRsig(rrsig); - - loop1_cname = RRsetPtr(new RRset(loop1, RRClass::IN(), RRType::CNAME(), - RRTTL(3600))); - loop1_cname->addRdata(generic::CNAME(loop2)); - loop2_cname = RRsetPtr(new RRset(loop2, RRClass::IN(), RRType::CNAME(), - RRTTL(3600))); - loop2_cname->addRdata(generic::CNAME(loop1)); + if (zones.empty()) { + for (int i = 0; i < NUM_ZONES; ++i) { + Zone zone(zone_data[i].zone_name, zone_data[i].rrclass); + buildZone(zone, zone_data[i].records, false); + buildZone(zone, zone_data[i].glue_records, true); + sort(zone.names.begin(), zone.names.end()); + zones.push_back(zone); + } + } initialized = true; return (SUCCESS); @@ -472,269 +364,152 @@ void TestDataSrc::findClosestEnclosure(NameMatch& match, const RRClass& qclass) const { const Name& qname = match.qname(); - NameComparisonResult::NameRelation cmp; if (qclass != getClass() && qclass != RRClass::ANY()) { return; } - cmp = qname.compare(sql1).getRelation(); - if (cmp == NameComparisonResult::EQUAL || - cmp == NameComparisonResult::SUBDOMAIN) { - match.update(*this, sql1); - return; + vector::const_iterator it; + vector::const_iterator best_it = zones.end(); + unsigned int best_common_labels = 0; + for (it = zones.begin(); it != zones.end(); ++it) { + const NameComparisonResult cmp = qname.compare(it->zone_name); + const NameComparisonResult::NameRelation reln = cmp.getRelation(); + + if ((reln == NameComparisonResult::EQUAL || + reln == NameComparisonResult::SUBDOMAIN) && + cmp.getCommonLabels() > best_common_labels) { + best_it = it; + best_common_labels = cmp.getCommonLabels(); + } } - cmp = qname.compare(example).getRelation(); - if (cmp == NameComparisonResult::EQUAL || - cmp == NameComparisonResult::SUBDOMAIN) { - match.update(*this, example); - return; + if (best_it != zones.end()) { + match.update(*this, best_it->zone_name); } - } +struct ZoneNameMatch : public unary_function { + ZoneNameMatch(const Name& name) : name_(name) {} + bool operator()(const Zone& zone) const { + return (zone.zone_name == name_); + } + const Name& name_; +}; + +// XXX: the main data source module can override the returned RRset. +// That's bad and should be fixed (Trac #254), but for now we work around it. +RRsetPtr +copyRRset(RRsetPtr const source) { + RRsetPtr rrset = RRsetPtr(new RRset(source->getName(), source->getClass(), + source->getType(), source->getTTL())); + RdataIteratorPtr it = source->getRdataIterator(); + for (it->first(); !it->isLast(); it->next()) { + rrset->addRdata(it->getCurrent()); + } + if (source->getRRsig()) { + rrset->addRRsig(copyRRset(source->getRRsig())); + } + + return (rrset); +} + +class TestDataSrc::RRsetMatch { +public: + struct MatchResult { + MatchResult(const bool name_found, const bool has_delegation) : + name_found_(name_found), has_delegation_(has_delegation) + {} + bool name_found_; + bool has_delegation_; + }; + RRsetMatch(const Name& name, const RRType& rrtype, const Mode mode, + RRsetList& target, uint32_t& flags) : + name_(name), rrtype_(rrtype), mode_(mode), target_(target), + flags_(flags), name_found_(false), has_delegation_(false) + {} + void operator()(const RRsetPtr& rrset) { + if (rrset->getName() != name_) { + return; + } + name_found_ = true; + + if (rrset->getType() == RRType::NS() || + rrset->getType() == RRType::DNAME()) { + has_delegation_ = true; + } + + if (mode_ == DELEGATION) { + if (rrset->getType() == RRType::NS() || + rrset->getType() == RRType::DNAME() || + rrset->getType() == RRType::DS()) { + target_.addRRset(copyRRset(rrset)); + } + } else if (mode_ == ADDRESS) { + if (rrset->getType() == RRType::A() || + rrset->getType() == RRType::AAAA()) { + target_.addRRset(copyRRset(rrset)); + } + } else { + if (rrtype_ == RRType::NSEC() && + rrset->getType() == RRType::CNAME()) { + // XXX: ignore CNAME if the qtype is NSEC. + // tricky, but necessary. + return; + } + if (rrtype_ == RRType::ANY() || rrtype_ == rrset->getType() || + rrset->getType() == RRType::CNAME() || + rrset->getType() == RRType::DNAME()) { + target_.addRRset(copyRRset(rrset)); + if (rrset->getType() == RRType::CNAME()) { + flags_ |= CNAME_FOUND; + } + if (rrset->getType() == RRType::DNAME()) { + flags_ |= REFERRAL; + } + } + } + + } + MatchResult getResult() { return (MatchResult(name_found_, + has_delegation_)); } + const Name& name_; + const RRType& rrtype_; + const Mode mode_; + RRsetList& target_; + uint32_t& flags_; + bool name_found_; + bool has_delegation_; +}; + void TestDataSrc::findRecords(const Name& name, const RRType& rdtype, - RRsetList& target, const Name* zonename, const Mode mode, - uint32_t& flags) const + RRsetList& target, const Name* zonename, + const Mode mode, uint32_t& flags) const { - const bool any = (rdtype == RRType::ANY()); flags = 0; assert(zonename != NULL); - if (*zonename == sql1) { - if (name == sql1 && mode == DELEGATION) { - target.addRRset(sql1_ns); - flags |= REFERRAL; - } else if (name == sql1) { - flags |= REFERRAL; - if (any) { - target.addRRset(sql1_ns); - target.addRRset(sql1_nsec); - } else if (rdtype == RRType::NS()) { - target.addRRset(sql1_ns); - } else if (rdtype == RRType::SOA()) { - target.addRRset(sql1_soa); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(sql1_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == www_sql1) { - if (any) { - target.addRRset(www_sql1_a); - target.addRRset(www_sql1_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(www_sql1_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(www_sql1_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else { - flags |= NAME_NOT_FOUND; - } - } else { - if (name == example && mode == DELEGATION) { - target.addRRset(example_ns); - flags |= REFERRAL; - } else if (name == example) { - flags |= REFERRAL; - if (any) { - target.addRRset(example_ns); - target.addRRset(example_soa); - target.addRRset(example_nsec); - } else if (rdtype == RRType::NS()) { - target.addRRset(example_ns); - } else if (rdtype == RRType::SOA()) { - target.addRRset(example_soa); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(example_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == sql1 && mode == DELEGATION) { - target.addRRset(sql1_ns); - target.addRRset(sql1_ds); - target.addRRset(sql1_ds_nsec); - flags |= REFERRAL; - } else if (name == sql1) { - flags |= REFERRAL; - if (any) { - target.addRRset(sql1_ns); - target.addRRset(sql1_ds); - target.addRRset(sql1_ds_nsec); - } else if (rdtype == RRType::DS()) { - target.addRRset(sql1_ds); - } else if (rdtype == RRType::NS()) { - target.addRRset(sql1_ns); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(sql1_ds_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == subzone && mode == DELEGATION) { - target.addRRset(subzone_ns); - target.addRRset(subzone_ds); - flags |= REFERRAL; - } else if (name == subzone) { - flags |= REFERRAL; - if (any) { - target.addRRset(subzone_ns); - target.addRRset(subzone_nsec); - } else if (rdtype == RRType::NS()) { - target.addRRset(subzone_ns); - } else if (rdtype == RRType::DS()) { - target.addRRset(subzone_ds); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(subzone_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == dns01 && mode == ADDRESS) { - target.addRRset(dns01_a); - } else if (name == dns01) { - if (any) { - target.addRRset(dns01_a); - target.addRRset(dns01_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(dns01_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(dns01_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == dns02 && mode == ADDRESS) { - target.addRRset(dns02_a); - } else if (name == dns02) { - if (any) { - target.addRRset(dns02_a); - target.addRRset(dns02_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(dns02_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(dns02_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == dns03 && mode == ADDRESS) { - target.addRRset(dns03_a); - } else if (name == dns03) { - if (any) { - target.addRRset(dns03_a); - target.addRRset(dns03_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(dns03_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(dns03_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == wild) { - if (any) { - target.addRRset(wild_a); - target.addRRset(wild_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(wild_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(wild_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == wild2) { - if (any) { - target.addRRset(wild2_cname); - target.addRRset(wild2_nsec); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(wild2_nsec); - } else { - target.addRRset(wild2_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } - } else if (name == wild3) { - if (any) { - target.addRRset(wild3_cname); - target.addRRset(wild3_nsec); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(wild3_nsec); - } else { - target.addRRset(wild3_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } - } else if (name == www) { - if (any) { - target.addRRset(www_a); - target.addRRset(www_nsec); - } else if (rdtype == RRType::A()) { - target.addRRset(www_a); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(www_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == foo) { - if (rdtype == RRType::NSEC()) { - target.addRRset(foo_nsec); - } else { - target.addRRset(foo_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } - } else if (name == cnameint) { - if (rdtype == RRType::NSEC()) { - target.addRRset(cnameint_nsec); - } else { - target.addRRset(cnameint_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } - } else if (name == cnameext) { - if (rdtype == RRType::NSEC()) { - target.addRRset(cnameext_nsec); - } else { - target.addRRset(cnameext_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } - } else if (name == dname) { - flags |= REFERRAL; - if (any) { - target.addRRset(dname_dname); - target.addRRset(dname_nsec); - } else if (rdtype == RRType::DNAME()) { - target.addRRset(dname_dname); - } else if (rdtype == RRType::NSEC()) { - target.addRRset(dns01_nsec); - } else { - flags |= TYPE_NOT_FOUND; - } - } else if (name == Name("ns1.subzone.example.com") && mode == ADDRESS) { - target.addRRset(subzone_glue1); - } else if (name == Name("ns2.subzone.example.com") && mode == ADDRESS) { - target.addRRset(subzone_glue2); - } else if (name == loop1) { - target.addRRset(loop1_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } - } else if (name == loop2) { - target.addRRset(loop1_cname); - if (rdtype != RRType::CNAME()) { - flags |= CNAME_FOUND; - } + + vector::const_iterator zone = find_if(zones.begin(), zones.end(), + ZoneNameMatch(*zonename)); + if (zone == zones.end()) { + return; + } + + const RRsetMatch::MatchResult match_result = + for_each(zone->rrsets.begin(), zone->rrsets.end(), + RRsetMatch(name, rdtype, mode, target, flags)).getResult(); + if (match_result.has_delegation_) { + flags |= REFERRAL; + } + if (target.size() == 0) { + if (match_result.name_found_) { + flags |= TYPE_NOT_FOUND; } else { flags |= NAME_NOT_FOUND; } } - return; } DataSrc::Result @@ -770,7 +545,7 @@ TestDataSrc::findExactRRset(const Name& qname, flags &= ~REFERRAL; // CNAMEs don't count in this case - if (flags & CNAME_FOUND) { + if ((flags & CNAME_FOUND) != 0) { flags &= ~CNAME_FOUND; flags |= TYPE_NOT_FOUND; } @@ -815,42 +590,30 @@ TestDataSrc::findPreviousName(const Name& qname, { assert(zonename != NULL); - if (*zonename == example) { - if (qname >= example && qname < cnameext) { - target = example; - } else if (qname < cnameint) { - target = cnameext; - } else if (qname < dname) { - target = cnameint; - } else if (qname < dns01) { - target = dname; - } else if (qname < dns02) { - target = dns01; - } else if (qname < dns03) { - target = dns02; - } else if (qname < foo) { - target = dns03; - } else if (qname < sql1) { - target = foo; - } else if (qname < subzone) { - target = sql1; - } else if (qname < wild) { - target = subzone; - } else if (qname < wild2) { - target = wild; - } else if (qname < wild3) { - target = wild2; - } else if (qname < www) { - target = wild3; - } else { - target = www; - } + vector::const_iterator zone = find_if(zones.begin(), zones.end(), + ZoneNameMatch(*zonename)); + if (zone == zones.end()) { + return (ERROR); + } + + if (zone->names.empty()) { + return (ERROR); + } + + // if found, next_name >= qname. + vector::const_iterator next_name = + lower_bound(zone->names.begin(), zone->names.end(), qname); + if (next_name == zone->names.end()) { + // if no such name was found, the previous name is the last name. + target = zone->names.back(); + } else if (*next_name == qname) { + target = *next_name; + } else if (next_name == zone->names.begin()) { + // if qname < first_name, the "previous name" is the last name. + target = zone->names.back(); } else { - if (qname >= sql1 || qname < www_sql1) { - target = sql1; - } else { - target = www_sql1; - } + // otherwise, qname and next_name share the same previous name. + target = *(next_name - 1); } return (SUCCESS); } diff --git a/src/lib/datasrc/tests/test_datasrc.h b/src/lib/datasrc/tests/test_datasrc.h index b625d9ee53..b3ed55a986 100644 --- a/src/lib/datasrc/tests/test_datasrc.h +++ b/src/lib/datasrc/tests/test_datasrc.h @@ -96,6 +96,7 @@ private: ADDRESS, DELEGATION }; + class RRsetMatch; void findRecords(const isc::dns::Name& name, const isc::dns::RRType& rdtype, isc::dns::RRsetList& target, From 1408f51d521006d5a38a0ba6df7b3c21cf11f4b8 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 26 Jun 2010 06:55:44 +0000 Subject: [PATCH 49/66] added an entry for Trac #249 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2287 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index ebd8e3629e..e30c58c711 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ + 59. [bug] jinmei + lib/datasrc,bin/auth: The authoritative server could return a + SERVFAIL with a partial answer if it finds a data source broken + while looking for an answer. This can happen, for example, if a + zone that doesn't have an NS RR is configured and loaded as a + sqlite3 data source. (Trac #249, r2286) + 58. [bug] jinmei Worked around an interaction issue between ASIO and standard C++ library headers. Without this ASIO didn't work: sometimes the From 76533e82a1c6710582074c11e2b0f999d3a843d6 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 26 Jun 2010 07:00:13 +0000 Subject: [PATCH 50/66] minor editorial fix to a comment. skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2289 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/tests/test_datasrc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/datasrc/tests/test_datasrc.cc b/src/lib/datasrc/tests/test_datasrc.cc index d5de85b2a8..64816fab5d 100644 --- a/src/lib/datasrc/tests/test_datasrc.cc +++ b/src/lib/datasrc/tests/test_datasrc.cc @@ -260,7 +260,7 @@ const struct RRData nonsdname_example_records[] = { }; // -// zone data for nons-dname.example +// zone data for nosoa.example // const struct RRData nosoa_example_records[] = { {"nosoa.example", "NS", "ns.nosoa.example"}, From 5993b0d10ed7b3d83beeca4267b8ca59a0d439ce Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 26 Jun 2010 07:05:23 +0000 Subject: [PATCH 51/66] style fix: curly brace position. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2290 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/tests/test_datasrc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/datasrc/tests/test_datasrc.cc b/src/lib/datasrc/tests/test_datasrc.cc index 64816fab5d..a5a9841dab 100644 --- a/src/lib/datasrc/tests/test_datasrc.cc +++ b/src/lib/datasrc/tests/test_datasrc.cc @@ -362,7 +362,8 @@ TestDataSrc::init() { void TestDataSrc::findClosestEnclosure(NameMatch& match, - const RRClass& qclass) const { + const RRClass& qclass) const +{ const Name& qname = match.qname(); if (qclass != getClass() && qclass != RRClass::ANY()) { From b51fea10648cef95fb1bd45e7f9a2a502365901e Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Sat, 26 Jun 2010 07:06:22 +0000 Subject: [PATCH 52/66] cleanup: removed unnecessary UNUSED_PARAM. trivial, skipping review. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2291 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/datasrc/tests/test_datasrc.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/datasrc/tests/test_datasrc.cc b/src/lib/datasrc/tests/test_datasrc.cc index a5a9841dab..d92a2da060 100644 --- a/src/lib/datasrc/tests/test_datasrc.cc +++ b/src/lib/datasrc/tests/test_datasrc.cc @@ -515,7 +515,7 @@ TestDataSrc::findRecords(const Name& name, const RRType& rdtype, DataSrc::Result TestDataSrc::findRRset(const Name& qname, - const RRClass& qclass UNUSED_PARAM, + const RRClass& qclass, const RRType& qtype, RRsetList& target, uint32_t& flags, @@ -531,7 +531,7 @@ TestDataSrc::findRRset(const Name& qname, DataSrc::Result TestDataSrc::findExactRRset(const Name& qname, - const RRClass& qclass UNUSED_PARAM, + const RRClass& qclass, const RRType& qtype, RRsetList& target, uint32_t& flags, @@ -556,7 +556,7 @@ TestDataSrc::findExactRRset(const Name& qname, DataSrc::Result TestDataSrc::findAddrs(const Name& qname, - const RRClass& qclass UNUSED_PARAM, + const RRClass& qclass, RRsetList& target, uint32_t& flags, const Name* zonename) const @@ -571,7 +571,7 @@ TestDataSrc::findAddrs(const Name& qname, DataSrc::Result TestDataSrc::findReferral(const Name& qname, - const RRClass& qclass UNUSED_PARAM, + const RRClass& qclass, RRsetList& target, uint32_t& flags, const Name* zonename) const From 1e1f20e2be9267f810a88e2fdc83ebde713c7496 Mon Sep 17 00:00:00 2001 From: "Jeremy C. Reed" Date: Mon, 28 Jun 2010 14:08:31 +0000 Subject: [PATCH 53/66] Fix a few typos or improve grammar for some comments or inline docs. git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2306 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/log.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index a50c6c493f..30147295e5 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -52,10 +52,10 @@ class NSFileLogHandler(logging.handlers.RotatingFileHandler): If the log file is deleted at runtime, a new file will be created. """ dfn = self.baseFilename - if (self.stream) and (not os.path.exists(dfn)): #Is log file exist? + if (self.stream) and (not os.path.exists(dfn)): #Does log file exist? self.stream.close() dir = os.path.split(dfn) - if not (os.path.exists(dir[0])): #Is log subdirectory exist? + if not (os.path.exists(dir[0])): #Does log subdirectory exist? os.makedirs(dir[0]) self.stream = self._open() return super(NSFileLogHandler, self).shouldRollover(record) @@ -63,7 +63,7 @@ class NSFileLogHandler(logging.handlers.RotatingFileHandler): def update_config(self, file_name, backup_count, max_bytes): """Update RotatingFileHandler configuration. - If the file path is not exist, we will use the old log file. + If the file path does not exist, we will use the old log file. input: log file name max backup count @@ -153,7 +153,7 @@ class NSLogger(logging.getLoggerClass()): """Add a rotate file handler. input: - log_file : the location of log file. Handler wouldn't be created + log_file : the location of log file. Handler will not be created if log_file='' max_bytes : limit log growth backup_count : max backup count @@ -205,7 +205,7 @@ class NSLogger(logging.getLoggerClass()): self._add_rotate_handler(log_file, backup_count, max_bytes) def _get_config(self, config_data): - """Get config data from module configration""" + """Get config data from module configuration""" log_file_str = config_data.get('log_file') if(log_file_str): From 963591b9bba03589adc53c79d67efa5e95166732 Mon Sep 17 00:00:00 2001 From: "Jeremy C. Reed" Date: Mon, 28 Jun 2010 14:23:02 +0000 Subject: [PATCH 54/66] Remove space from "shutdown" in log message (back to way it was before). Spell out file descriptor (this "FD" was prior to this patch). git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2307 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/xfrout/xfrout.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 3e4b3ec949..fc263e26f3 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -58,7 +58,7 @@ class XfroutSession(BaseRequestHandler): def handle(self): fd = recv_fd(self.request.fileno()) if fd < 0: - self._log.log_message("error", "Failed to receive the FD for XFR connection") + self._log.log_message("error", "Failed to receive the file descriptor for XFR connection") data_len = self.request.recv(2) msg_len = struct.unpack('!H', data_len)[0] msgdata = self.request.recv(msg_len) @@ -397,7 +397,7 @@ class XfroutServer: def command_handler(self, cmd, args): if cmd == "shutdown": - self._log.log_message("info", "Received shut down command.") + self._log.log_message("info", "Received shutdown command.") self.shutdown() answer = create_answer(0) else: From 1b9d9fed56f25ec0a4f7a58853e16d78ddec2d35 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Mon, 28 Jun 2010 17:22:58 +0000 Subject: [PATCH 56/66] entry for Trac #251 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2311 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index e30c58c711..81170a07de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ + 60. [build] jinmei + Supported SunStudio C++ compiler. Note: gtest still doesn't work. + (Trac #251, svn r2310) + 59. [bug] jinmei lib/datasrc,bin/auth: The authoritative server could return a SERVFAIL with a partial answer if it finds a data source broken From edb8115f8265612007cff6137a8ed81c27beb6c5 Mon Sep 17 00:00:00 2001 From: "Jeremy C. Reed" Date: Tue, 29 Jun 2010 00:05:50 +0000 Subject: [PATCH 57/66] Only use -Wno-unused-parameter with g++. Use libtool to create libcc. Have users of libcc use the libcc.la (libtool archive). I noticed this because libcfgclient's tests only linked with cc/data.o but build using Sunstudio showed it used libcc's session also. So instead of just linking with cc/session.o (which does work), I chose to link with libcc -- and noticed it was not using libtool. (Later will change other linking with foo.o object files to use libtool .la files instead. Also for Sunstudio support a minor patch for src/lib/cc/session_unittests.cc may later be committed.) No trac ticket for this. It was discussed with jinmei via jabber. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2316 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/auth/Makefile.am | 2 +- src/bin/auth/tests/Makefile.am | 2 +- src/lib/cc/Makefile.am | 6 +++--- src/lib/config/tests/Makefile.am | 4 +++- src/lib/datasrc/tests/Makefile.am | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/bin/auth/Makefile.am b/src/bin/auth/Makefile.am index 4ab64ee640..af6813dafd 100644 --- a/src/bin/auth/Makefile.am +++ b/src/bin/auth/Makefile.am @@ -50,7 +50,7 @@ b10_auth_SOURCES += main.cc b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a b10_auth_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a b10_auth_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a -b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.a +b10_auth_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a b10_auth_LDADD += $(top_builddir)/src/bin/auth/libasio_link.a b10_auth_LDADD += $(SQLITE_LIBS) diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am index 3405f43543..5ce117679d 100644 --- a/src/bin/auth/tests/Makefile.am +++ b/src/bin/auth/tests/Makefile.am @@ -22,7 +22,7 @@ run_unittests_LDADD += $(SQLITE_LIBS) run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/config/.libs/libcfgclient.a -run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a +run_unittests_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a endif diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index c7a7249641..320ba9c125 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -10,8 +10,8 @@ if USE_GXX AM_CXXFLAGS += -Wno-unused-parameter endif -lib_LIBRARIES = libcc.a -libcc_a_SOURCES = data.cc data.h session.cc session.h +lib_LTLIBRARIES = libcc.la +libcc_la_SOURCES = data.cc data.h session.cc session.h CLEANFILES = *.gcno *.gcda session_config.h @@ -29,7 +29,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) # TODO: remove PTHREAD_LDFLAGS (and from configure too) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) $(PTHREAD_LDFLAGS) -run_unittests_LDADD = libcc.a $(GTEST_LDADD) +run_unittests_LDADD = libcc.la $(GTEST_LDADD) run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a diff --git a/src/lib/config/tests/Makefile.am b/src/lib/config/tests/Makefile.am index 436d962937..b36b15eacf 100644 --- a/src/lib/config/tests/Makefile.am +++ b/src/lib/config/tests/Makefile.am @@ -2,7 +2,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib AM_CXXFLAGS = $(B10_CXXFLAGS) # see src/lib/cc/Makefile.am for -Wno-unused-parameter +if USE_GXX AM_CXXFLAGS += -Wno-unused-parameter +endif CLEANFILES = *.gcno *.gcda @@ -20,7 +22,7 @@ run_unittests_LDADD = $(GTEST_LDADD) run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la run_unittests_LDADD += libfake_session.la run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la -run_unittests_LDADD += $(top_builddir)/src/lib/cc/data.o +run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la endif diff --git a/src/lib/datasrc/tests/Makefile.am b/src/lib/datasrc/tests/Makefile.am index a2912b8862..5fed72f84d 100644 --- a/src/lib/datasrc/tests/Makefile.am +++ b/src/lib/datasrc/tests/Makefile.am @@ -23,7 +23,7 @@ run_unittests_LDADD = $(GTEST_LDADD) run_unittests_LDADD += $(SQLITE_LIBS) run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns++.a -run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a +run_unittests_LDADD += $(top_builddir)/src/lib/cc/.libs/libcc.a run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a endif From ad60bb544e65b87632c1710f321b033ad6b631fb Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Tue, 29 Jun 2010 13:17:24 +0000 Subject: [PATCH 58/66] Revert the special link-only-to-data.o so it builds on debian(-derived) systems again. This should break the sunstudio build again, looking into how that can be fixed (but i don't have access to that specific machine yet). git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2324 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/config/tests/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/config/tests/Makefile.am b/src/lib/config/tests/Makefile.am index b36b15eacf..ac996e6b4a 100644 --- a/src/lib/config/tests/Makefile.am +++ b/src/lib/config/tests/Makefile.am @@ -22,7 +22,10 @@ run_unittests_LDADD = $(GTEST_LDADD) run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la run_unittests_LDADD += libfake_session.la run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la -run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la +# link *only* to data.o from lib/cc (more importantly, don't link in +# the session class provided there, since we use our own fake_session +# here) +run_unittests_LDADD += $(top_builddir)/src/lib/cc/data.o endif From 2da6b0550c29a826a22cc8eed0b7778ccd5a8a99 Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Tue, 29 Jun 2010 14:13:40 +0000 Subject: [PATCH 59/66] merge of ticket #225 (b10-auth fails if ran from source tree), also changes xfrin and xfrout to use the database_file setting from the auth module, so for xfrin you don't need to specify it on the command, and for out it doesn't need its own configuration value git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2325 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 9 +++++++++ src/bin/auth/auth_srv.cc | 15 ++++++++++++++- src/bin/xfrin/xfrin.py.in | 16 +++++++++++++++- src/bin/xfrout/tests/xfrout_test.py | 16 +++++++++++++--- src/bin/xfrout/xfrout.py.in | 22 ++++++++++++++-------- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81170a07de..6d9772191e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ + + 62. [func] jelte + bin/xfrin: Use the database_file as configured in Auth to transfers + bin/xfrout: Use the database_file as configured in Auth to transfers + + 61. [bug] jelte + bin/auth: Enable b10-auth to be launched in source tree + (i.e. use a zone database file relative to that) + 60. [build] jinmei Supported SunStudio C++ compiler. Note: gtest still doesn't work. (Trac #251, svn r2310) diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc index 71810ae906..026196afdb 100644 --- a/src/bin/auth/auth_srv.cc +++ b/src/bin/auth/auth_srv.cc @@ -274,9 +274,22 @@ AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) { bool is_default; string item("database_file"); ElementPtr value = cs_->getValue(is_default, item); - db_file_ = value->stringValue(); final = Element::createFromString("{}"); + + // If the value is the default, and we are running from + // a specific directory ('from build'), we need to use + // a different value than the default (which may not exist) + // (btw, this should not be done here in the end, i think + // the from-source script should have a check for this, + // but for that we need offline access to config, so for + // now this is a decent solution) + if (is_default && getenv("B10_FROM_BUILD")) { + value = Element::create(string(getenv("B10_FROM_BUILD")) + + "/bind10_zones.sqlite3"); + } final->set(item, value); + + db_file_ = value->stringValue(); } else { return (answer); } diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in index c0fd69916e..f4a918a491 100644 --- a/src/bin/xfrin/xfrin.py.in +++ b/src/bin/xfrin/xfrin.py.in @@ -40,11 +40,14 @@ except ImportError as e: # installed on the system if "B10_FROM_BUILD" in os.environ: SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/xfrin" + AUTH_SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/auth" else: PREFIX = "@prefix@" DATAROOTDIR = "@datarootdir@" SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX) + AUTH_SPECFILE_PATH = SPECFILE_PATH SPECFILE_LOCATION = SPECFILE_PATH + "/xfrin.spec" +AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + "/auth.spec" __version__ = 'BIND10' @@ -441,7 +444,18 @@ a separate method for the convenience of unit tests. db_file = args.get('db_file') if not db_file: #TODO, the db file path should be got in auth server's configuration - db_file = '@@LOCALSTATEDIR@@/@PACKAGE@/zone.sqlite3' + # if we need access to this configuration more often, we + # should add it on start, and not remove it here + # (or, if we have writable ds, we might not need this in + # the first place) + self._cc.add_remote_config(AUTH_SPECFILE_LOCATION) + db_file, is_default = self._cc.get_remote_config_value("Auth", "database_file") + if is_default and "B10_FROM_BUILD" in os.environ: + # this too should be unnecessary, but currently the + # 'from build' override isn't stored in the config + # (and we don't have writable datasources yet) + db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3" + self._cc.remove_remote_config(AUTH_SPECFILE_LOCATION) return (zone_name, master_addrinfo, db_file) diff --git a/src/bin/xfrout/tests/xfrout_test.py b/src/bin/xfrout/tests/xfrout_test.py index f4adbde968..bbee8c929f 100644 --- a/src/bin/xfrout/tests/xfrout_test.py +++ b/src/bin/xfrout/tests/xfrout_test.py @@ -242,22 +242,32 @@ class TestXfroutSession(unittest.TestCase): self.xfrsess.server._shutdown_event.set() self.assertRaises(XfroutException, self.xfrsess._reply_xfrout_query, self.getmsg(), self.sock, "example.com.") +class MyCCSession(): + def __init__(self): + pass + + def get_remote_config_value(self, module_name, identifier): + if module_name == "Auth" and identifier == "database_file": + return "initdb.file", False + else: + return "unknown", False + + class MyUnixSockServer(UnixSockServer): def __init__(self): self._lock = threading.Lock() self._transfers_counter = 0 self._shutdown_event = threading.Event() - self._db_file = "initdb.file" self._max_transfers_out = 10 + self._cc = MyCCSession() class TestUnixSockServer(unittest.TestCase): def setUp(self): self.unix = MyUnixSockServer() def test_updata_config_data(self): - self.unix.update_config_data({'transfers_out':10, 'db_file':"db.file"}) + self.unix.update_config_data({'transfers_out':10 }) self.assertEqual(self.unix._max_transfers_out, 10) - self.assertEqual(self.unix._db_file, "db.file") def test_get_db_file(self): self.assertEqual(self.unix.get_db_file(), "initdb.file") diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index 1643946504..83ee35abe1 100644 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -41,14 +41,17 @@ except ImportError as e: if "B10_FROM_BUILD" in os.environ: SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/xfrout" + AUTH_SPECFILE_PATH = os.environ["B10_FROM_BUILD"] + "/src/bin/auth" UNIX_SOCKET_FILE= os.environ["B10_FROM_BUILD"] + "/auth_xfrout_conn" else: PREFIX = "@prefix@" DATAROOTDIR = "@datarootdir@" SPECFILE_PATH = "@datadir@/@PACKAGE@".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX) + AUTH_SPECFILE_PATH = SPECFILE_PATH UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn" SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec" +AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + os.sep + "auth.spec" MAX_TRANSFERS_OUT = 10 verbose_mode = False @@ -285,7 +288,7 @@ class XfroutSession(BaseRequestHandler): class UnixSockServer(ThreadingUnixStreamServer): '''The unix domain socket server which accept xfr query sent from auth server.''' - def __init__(self, sock_file, handle_class, shutdown_event, config_data): + def __init__(self, sock_file, handle_class, shutdown_event, config_data, cc): self._remove_unused_sock_file(sock_file) self._sock_file = sock_file ThreadingUnixStreamServer.__init__(self, sock_file, handle_class) @@ -293,6 +296,7 @@ class UnixSockServer(ThreadingUnixStreamServer): self._transfers_counter = 0 self._shutdown_event = shutdown_event self.update_config_data(config_data) + self._cc = cc def _remove_unused_sock_file(self, sock_file): '''Try to remove the socket file. If the file is being used @@ -334,18 +338,20 @@ class UnixSockServer(ThreadingUnixStreamServer): def update_config_data(self, new_config): '''Apply the new config setting of xfrout module. ''' - self._lock.acquire() self._max_transfers_out = new_config.get('transfers_out') - self._db_file = new_config.get('db_file') self._lock.release() def get_db_file(self): - self._lock.acquire() - file = self._db_file - self._lock.release() + file, is_default = self._cc.get_remote_config_value("Auth", "database_file") + # this too should be unnecessary, but currently the + # 'from build' override isn't stored in the config + # (and we don't have indirect python access to datasources yet) + if is_default and "B10_FROM_BUILD" in os.environ: + file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3" return file + def increase_transfers_counter(self): '''Return False, if counter + 1 > max_transfers_out, or else return True @@ -388,16 +394,16 @@ class XfroutServer: self._listen_sock_file = UNIX_SOCKET_FILE self._shutdown_event = threading.Event() self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler) + self._cc.add_remote_config(AUTH_SPECFILE_LOCATION); self._config_data = self._cc.get_full_config() self._cc.start() self._start_xfr_query_listener() - def _start_xfr_query_listener(self): '''Start a new thread to accept xfr query. ''' self._unix_socket_server = UnixSockServer(self._listen_sock_file, XfroutSession, - self._shutdown_event, self._config_data); + self._shutdown_event, self._config_data, self._cc); listener = threading.Thread(target = listen_on_xfr_query, args = (self._unix_socket_server,)) listener.start() From dfc50e2853dfcd44e1f182d6cc26f0cee6b7962e Mon Sep 17 00:00:00 2001 From: Shane Kerr Date: Tue, 29 Jun 2010 19:54:04 +0000 Subject: [PATCH 60/66] Optionally drop priviliges in the boss process. This involves adding a "-u" flag, then invoking setuid() if passed. A set of tests for this were also added. See Trac ticket #180 for more details: http://bind10.isc.org/ticket/180 git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2330 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/bind10/bind10.py.in | 138 ++++++++++++++++++++++------ src/bin/bind10/tests/args_test.py | 134 +++++++++++++++++++++++++++ src/bin/bind10/tests/bind10_test.in | 3 +- 3 files changed, 245 insertions(+), 30 deletions(-) create mode 100644 src/bin/bind10/tests/args_test.py diff --git a/src/bin/bind10/bind10.py.in b/src/bin/bind10/bind10.py.in index 040f14bce1..823c2304bd 100644 --- a/src/bin/bind10/bind10.py.in +++ b/src/bin/bind10/bind10.py.in @@ -57,6 +57,9 @@ import time import select import random from optparse import OptionParser, OptionValueError +import io +import pwd +import posix import isc.cc @@ -108,21 +111,38 @@ to avoid being restarted at exactly 10 seconds.""" when = time.time() return max(when, self.restart_time) +class ProcessInfoError(Exception): pass + class ProcessInfo: """Information about a process""" dev_null = open(os.devnull, "w") def __init__(self, name, args, env={}, dev_null_stdout=False, - dev_null_stderr=False): + dev_null_stderr=False, uid=None, username=None): self.name = name self.args = args self.env = env self.dev_null_stdout = dev_null_stdout self.dev_null_stderr = dev_null_stderr self.restart_schedule = RestartSchedule() + self.uid = uid + self.username = username self._spawn() + def _setuid(self): + """Function used before running a program that needs to run as a + different user.""" + if self.uid is not None: + try: + posix.setuid(self.uid) + except OSError as e: + if e.errno == errno.EPERM: + # if we failed to change user due to permission report that + raise ProcessInfoError("Unable to change to user %s (uid %d)" % (self.username, self.uid)) + else: + # otherwise simply re-raise whatever error we found + raise def _spawn(self): if self.dev_null_stdout: @@ -138,14 +158,15 @@ class ProcessInfo: # on construction (self.env). spawn_env = os.environ spawn_env.update(self.env) - if not 'B10_FROM_SOURCE' in os.environ: + if 'B10_FROM_SOURCE' not in os.environ: spawn_env['PATH'] = "@@LIBEXECDIR@@:" + spawn_env['PATH'] self.process = subprocess.Popen(self.args, stdin=subprocess.PIPE, stdout=spawn_stdout, stderr=spawn_stderr, close_fds=True, - env=spawn_env,) + env=spawn_env, + preexec_fn=self._setuid) self.pid = self.process.pid self.restart_schedule.set_run_start_time() @@ -155,7 +176,8 @@ class ProcessInfo: class BoB: """Boss of BIND class.""" - def __init__(self, msgq_socket_file=None, auth_port=5300, verbose=False): + def __init__(self, msgq_socket_file=None, auth_port=5300, verbose=False, + setuid=None, username=None): """Initialize the Boss of BIND. This is a singleton (only one can run). @@ -171,6 +193,8 @@ class BoB: self.processes = {} self.dead_processes = {} self.runnable = False + self.uid = setuid + self.username = username def config_handler(self, new_config): if self.verbose: @@ -225,12 +249,14 @@ class BoB: sys.stdout.write("[bind10] Starting b10-msgq\n") try: c_channel = ProcessInfo("b10-msgq", ["b10-msgq"], c_channel_env, - True, not self.verbose) + True, not self.verbose, uid=self.uid, + username=self.username) except Exception as e: return "Unable to start b10-msgq; " + str(e) self.processes[c_channel.pid] = c_channel if self.verbose: - sys.stdout.write("[bind10] Started b10-msgq (PID %d)\n" % c_channel.pid) + sys.stdout.write("[bind10] Started b10-msgq (PID %d)\n" % + c_channel.pid) # now connect to the c-channel cc_connect_start = time.time() @@ -250,7 +276,8 @@ class BoB: sys.stdout.write("[bind10] Starting b10-cfgmgr\n") try: bind_cfgd = ProcessInfo("b10-cfgmgr", ["b10-cfgmgr"], - c_channel_env) + c_channel_env, uid=self.uid, + username=self.username) except Exception as e: c_channel.process.kill() return "Unable to start b10-cfgmgr; " + str(e) @@ -272,23 +299,6 @@ class BoB: if self.verbose: sys.stdout.write("[bind10] ccsession started\n") - # start the xfrout before auth-server, to make sure every xfr-query can - # be processed properly. - xfrout_args = ['b10-xfrout'] - if self.verbose: - sys.stdout.write("[bind10] Starting b10-xfrout\n") - xfrout_args += ['-v'] - try: - xfrout = ProcessInfo("b10-xfrout", xfrout_args, - c_channel_env ) - except Exception as e: - c_channel.process.kill() - bind_cfgd.process.kill() - return "Unable to start b10-xfrout; " + str(e) - self.processes[xfrout.pid] = xfrout - if self.verbose: - sys.stdout.write("[bind10] Started b10-xfrout (PID %d)\n" % xfrout.pid) - # start b10-auth # XXX: this must be read from the configuration manager in the future authargs = ['b10-auth', '-p', str(self.auth_port)] @@ -308,6 +318,28 @@ class BoB: if self.verbose: sys.stdout.write("[bind10] Started b10-auth (PID %d)\n" % auth.pid) + # everything after the authoritative server can run as non-root + if self.uid is not None: + posix.setuid(self.uid) + + # start the xfrout before auth-server, to make sure every xfr-query can + # be processed properly. + xfrout_args = ['b10-xfrout'] + if self.verbose: + sys.stdout.write("[bind10] Starting b10-xfrout\n") + xfrout_args += ['-v'] + try: + xfrout = ProcessInfo("b10-xfrout", xfrout_args, + c_channel_env ) + except Exception as e: + c_channel.process.kill() + bind_cfgd.process.kill() + return "Unable to start b10-xfrout; " + str(e) + self.processes[xfrout.pid] = xfrout + if self.verbose: + sys.stdout.write("[bind10] Started b10-xfrout (PID %d)\n" % + xfrout.pid) + # start b10-xfrin xfrin_args = ['b10-xfrin'] if self.verbose: @@ -324,7 +356,8 @@ class BoB: return "Unable to start b10-xfrin; " + str(e) self.processes[xfrind.pid] = xfrind if self.verbose: - sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" % xfrind.pid) + sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" % + xfrind.pid) # start the b10-cmdctl # XXX: we hardcode port 8080 @@ -344,7 +377,8 @@ class BoB: return "Unable to start b10-cmdctl; " + str(e) self.processes[cmd_ctrld.pid] = cmd_ctrld if self.verbose: - sys.stdout.write("[bind10] Started b10-cmdctl (PID %d)\n" % cmd_ctrld.pid) + sys.stdout.write("[bind10] Started b10-cmdctl (PID %d)\n" % + cmd_ctrld.pid) self.runnable = True @@ -435,11 +469,16 @@ class BoB: sys.stdout.write("[bind10] Unknown child pid %d exited.\n" % pid) def restart_processes(self): - """Restart any dead processes.""" + """Restart any dead processes. + Returns the time when the next process is ready to be restarted. + If the server is shutting down, returns 0. + If there are no processes, returns None. + The values returned can be safely passed into select() as the + timeout value.""" next_restart = None # if we're shutting down, then don't restart if not self.runnable: - return next_restart + return 0 # otherwise look through each dead process and try to restart still_dead = {} now = time.time() @@ -510,6 +549,10 @@ def check_port(option, opt_str, value, parser): def main(): global options global boss_of_bind + # Enforce line buffering on stdout, even when not a TTY + sys.stdout = io.TextIOWrapper(sys.stdout.detach(), line_buffering=True) + + # Parse any command-line options. parser = OptionParser(version=__version__) parser.add_option("-v", "--verbose", dest="verbose", action="store_true", @@ -520,7 +563,42 @@ def main(): parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file", type="string", default=None, help="UNIX domain socket file the b10-msgq daemon will use") + parser.add_option("-u", "--user", dest="user", + type="string", default=None, + help="Change user after startup (must run as root)") (options, args) = parser.parse_args() + if args: + parser.print_help() + sys.exit(1) + + # Check user ID. + setuid = None + username = None + if options.user: + # Try getting information about the user, assuming UID passed. + try: + pw_ent = pwd.getpwuid(int(options.user)) + setuid = pw_ent.pw_uid + username = pw_ent.pw_name + except ValueError: + pass + except KeyError: + pass + + # Next try getting information about the user, assuming user name + # passed. + # If the information is both a valid user name and user number, we + # prefer the name because we try it second. A minor point, hopefully. + try: + pw_ent = pwd.getpwnam(options.user) + setuid = pw_ent.pw_uid + username = pw_ent.pw_name + except KeyError: + pass + + if setuid is None: + sys.stderr.write("bind10: invalid user: '%s'\n" % options.user) + sys.exit(1) # Announce startup. if options.verbose: @@ -543,11 +621,12 @@ def main(): # Go bob! boss_of_bind = BoB(options.msgq_socket_file, int(options.auth_port), - options.verbose) + options.verbose, setuid, username) startup_result = boss_of_bind.startup() if startup_result: sys.stderr.write("[bind10] Error on startup: %s\n" % startup_result) sys.exit(1) + sys.stdout.write("[bind10] BIND 10 started\n") # In our main loop, we check for dead processes or messages # on the c-channel. @@ -584,6 +663,7 @@ def main(): # shutdown signal.signal(signal.SIGCHLD, signal.SIG_DFL) boss_of_bind.shutdown() + sys.exit(0) if __name__ == "__main__": main() diff --git a/src/bin/bind10/tests/args_test.py b/src/bin/bind10/tests/args_test.py new file mode 100644 index 0000000000..9e38ccd867 --- /dev/null +++ b/src/bin/bind10/tests/args_test.py @@ -0,0 +1,134 @@ +""" +This program tests the boss process to make sure that it runs while +dropping permissions. It must be run as a user that can set permission. +""" +import unittest +import os +import sys +import subprocess +import select +import time +import pwd + +# Set to a valid user name on the system to run setuid() test +#SUID_USER=None +SUID_USER="shane" + +BIND10_EXE="../run_bind10.sh" +TIMEOUT=3 + +class TestBossArgs(unittest.TestCase): + def _waitForString(self, bob, s): + found_string = False + start_time = time.time() + while time.time() < start_time + TIMEOUT: + (r,w,x) = select.select((bob.stdout,), (), (), TIMEOUT) + if bob.stdout in r: + s = bob.stdout.readline() + if s == '': + break + if s.startswith(s): + found_string = True + break + return found_string + + def testNoArgs(self): + """Run bind10 without any arguments""" + bob = subprocess.Popen(args=(BIND10_EXE,), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + started_ok = self._waitForString(bob, '[bind10] BIND 10 started') + time.sleep(0.1) + bob.terminate() + bob.wait() + self.assertTrue(started_ok) + + def testBadOption(self): + """Run bind10 with a bogus option""" + bob = subprocess.Popen(args=(BIND10_EXE, "--badoption"), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + failed = self._waitForString(bob, 'bind10: error: no such option: --badoption') + time.sleep(0.1) + bob.terminate() + self.assertTrue(bob.wait() == 2) + self.assertTrue(failed) + + def testArgument(self): + """Run bind10 with an argument (this is not allowed)""" + bob = subprocess.Popen(args=(BIND10_EXE, "argument"), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + failed = self._waitForString(bob, 'Usage: bind10 [options]') + time.sleep(0.1) + bob.terminate() + self.assertTrue(bob.wait() == 1) + self.assertTrue(failed) + + def testBadUser(self): + """Run bind10 with a bogus user""" + bob = subprocess.Popen(args=(BIND10_EXE, "-u", "bogus_user"), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + failed = self._waitForString(bob, "bind10: invalid user: 'bogus_user'") + time.sleep(0.1) + bob.terminate() + self.assertTrue(bob.wait() == 1) + self.assertTrue(failed) + + def testBadUid(self): + """Run bind10 with a bogus user ID""" + bob = subprocess.Popen(args=(BIND10_EXE, "-u", "999999999"), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + failed = self._waitForString(bob, "bind10: invalid user: '999999999'") + time.sleep(0.1) + bob.terminate() + self.assertTrue(bob.wait() == 1) + self.assertTrue(failed) + + def testFailSetUser(self): + """Try the -u option when we don't run as root""" + global SUID_USER + if SUID_USER is None: + self.skipTest("test needs a valid user (set when run)") + if os.getuid() == 0: + self.skipTest("test must not be run as root (uid is 0)") + # XXX: we depend on the "nobody" user + bob = subprocess.Popen(args=(BIND10_EXE, "-u", "nobody"), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + failed = self._waitForString(bob, "[bind10] Error on startup: Unable to start b10-msgq; Unable to change to user nobody") + time.sleep(0.1) + bob.terminate() + self.assertTrue(bob.wait() == 1) + self.assertTrue(failed) + + def testSetUser(self): + """Try the -u option""" + global SUID_USER + if SUID_USER is None: + self.skipTest("test needs a valid user (set when run)") + if os.getuid() != 0: + self.skipTest("test must run as root (uid is not 0)") + if os.geteuid() != 0: + self.skipTest("test must run as root (euid is not 0)") + + bob = subprocess.Popen(args=(BIND10_EXE, "-u", SUID_USER), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + started_ok = self._waitForString(bob, '[bind10] BIND 10 started') + self.assertTrue(started_ok) + ps = subprocess.Popen(args=("ps", "axo", "user,pid"), + stdout=subprocess.PIPE) + s = ps.stdout.readline() + ps_user = None + while True: + s = ps.stdout.readline() + if s == '': break + (user, pid) = s.split() + if int(pid) == bob.pid: + ps_user = user.decode() + break + self.assertTrue(ps_user is not None) + self.assertTrue(ps_user == SUID_USER) + time.sleep(0.1) + bob.terminate() + x = bob.wait() + self.assertTrue(bob.wait() == 0) + +if __name__ == '__main__': + unittest.main() diff --git a/src/bin/bind10/tests/bind10_test.in b/src/bin/bind10/tests/bind10_test.in index d448bf5294..cbd74524a1 100755 --- a/src/bin/bind10/tests/bind10_test.in +++ b/src/bin/bind10/tests/bind10_test.in @@ -27,5 +27,6 @@ PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_srcdir@/src/bin/bind10 export PYTHONPATH cd ${BIND10_PATH}/tests -exec ${PYTHON_EXEC} -O bind10_test.py $* +${PYTHON_EXEC} -O bind10_test.py $* +exec ${PYTHON_EXEC} -O args_test.py $* From dabb1631f6b8123303882d2753bacb9bb4ffda39 Mon Sep 17 00:00:00 2001 From: Shane Kerr Date: Tue, 29 Jun 2010 19:56:38 +0000 Subject: [PATCH 61/66] ChangeLog for privilege dropping (Trac ticket #180). git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2331 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6d9772191e..5328eaa2f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + 63. [func] shane + Added initial support for setuid(), using the "-u" flag. This will + be replaced in the future, but for now provides a reasonable + starting point. + (Trac #180, svn r2330) 62. [func] jelte bin/xfrin: Use the database_file as configured in Auth to transfers From bfc4bec5391e606eaf1c2504afc147de9fc5e13e Mon Sep 17 00:00:00 2001 From: Jerry Date: Wed, 30 Jun 2010 02:08:53 +0000 Subject: [PATCH 62/66] Add syslog handler unittest git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac176@2337 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/log.py | 4 ++-- src/lib/python/isc/log/tests/log_test.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/lib/python/isc/log/log.py b/src/lib/python/isc/log/log.py index 30147295e5..635e4bd29b 100644 --- a/src/lib/python/isc/log/log.py +++ b/src/lib/python/isc/log/log.py @@ -177,13 +177,13 @@ class NSLogger(logging.getLoggerClass()): self._stream_handler.setFormatter(TIME_FORMATTER) self.addHandler(self._stream_handler) - def _add_syslog_handler(self, facility=syslog.LOG_USER): + def _add_syslog_handler(self, nsfacility=syslog.LOG_USER): """Add a syslog handler. If facility is not specified, LOG_USER is used. The default severity level is INFO. """ - self._syslog_handler = NSSysLogHandler('BIND10', facility) + self._syslog_handler = NSSysLogHandler('BIND10', facility = nsfacility) self._syslog_handler.setFormatter(FORMATTER) #set syslog handler severity level INFO self._syslog_handler.setLevel(logging.INFO) diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py index 2af4f18098..ae1fccb605 100644 --- a/src/lib/python/isc/log/tests/log_test.py +++ b/src/lib/python/isc/log/tests/log_test.py @@ -50,6 +50,18 @@ class TestRotateFileHandler(unittest.TestCase): self.FILE_LOG2.close() self.FILE_LOG3.close() +class TestSysLogHandler(unittest.TestCase): + def setUp(self): + self.handler = NSSysLogHandler("BIND10") + + def test_encodeLevel(self): + sysLevel = self.handler._encodeLevel(logging.ERROR) + self.assertEqual(sysLevel, syslog.LOG_ERR) + + def test_emit(self): + record = logging.LogRecord(None, None, "", 0, "syslog handler", (), None, None) + self.handler.emit(record) + class TestLogging(unittest.TestCase): From 31ec8c6c6598f614c77817a12d4642a5ec829c31 Mon Sep 17 00:00:00 2001 From: tingting shen Date: Wed, 30 Jun 2010 07:27:30 +0000 Subject: [PATCH 63/66] Added verbose options to exactly what is happening with loadzone. Added loadzone test suite of different file formats to load. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2340 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 5 + configure.ac | 6 + src/bin/loadzone/Makefile.am | 46 ++-- src/bin/loadzone/b10-loadzone.py.in | 22 +- src/bin/loadzone/tests/correct/Makefile.am | 24 ++ .../loadzone/tests/correct/correct_test.sh.in | 72 +++++ src/bin/loadzone/tests/correct/example.db | 14 + .../loadzone/tests/correct/get_zonedatas.py | 8 + src/bin/loadzone/tests/correct/inclsub.db | 4 + src/bin/loadzone/tests/correct/include.db | 23 ++ src/bin/loadzone/tests/correct/known.test.out | 79 ++++++ src/bin/loadzone/tests/correct/mix1.db | 21 ++ src/bin/loadzone/tests/correct/mix1sub1.db | 3 + src/bin/loadzone/tests/correct/mix1sub2.db | 3 + src/bin/loadzone/tests/correct/mix2.db | 21 ++ src/bin/loadzone/tests/correct/mix2sub1.txt | 3 + src/bin/loadzone/tests/correct/mix2sub2.txt | 3 + src/bin/loadzone/tests/correct/ttl1.db | 17 ++ src/bin/loadzone/tests/correct/ttl2.db | 17 ++ src/bin/loadzone/tests/correct/ttlext.db | 18 ++ src/bin/loadzone/tests/error/Makefile.am | 25 ++ src/bin/loadzone/tests/error/error.known | 11 + src/bin/loadzone/tests/error/error_test.sh.in | 75 +++++ src/bin/loadzone/tests/error/formerr1.db | 13 + src/bin/loadzone/tests/error/formerr2.db | 12 + src/bin/loadzone/tests/error/formerr3.db | 12 + src/bin/loadzone/tests/error/formerr4.db | 12 + src/bin/loadzone/tests/error/formerr5.db | 13 + src/bin/loadzone/tests/error/include.txt | 1 + src/bin/loadzone/tests/error/keyerror1.db | 12 + src/bin/loadzone/tests/error/keyerror2.db | 12 + src/bin/loadzone/tests/error/keyerror3.db | 13 + src/bin/loadzone/tests/error/originerr1.db | 11 + src/bin/loadzone/tests/error/originerr2.db | 12 + .../normal}/Kexample.com.+005+04456.key | 0 .../normal}/Kexample.com.+005+04456.private | 0 .../normal}/Kexample.com.+005+33495.key | 0 .../normal}/Kexample.com.+005+33495.private | 0 .../normal}/Ksql1.example.com.+005+12447.key | 0 .../Ksql1.example.com.+005+12447.private | 0 .../normal}/Ksql1.example.com.+005+33313.key | 0 .../Ksql1.example.com.+005+33313.private | 0 .../normal}/Ksql2.example.com.+005+38482.key | 0 .../Ksql2.example.com.+005+38482.private | 0 .../normal}/Ksql2.example.com.+005+63192.key | 0 .../Ksql2.example.com.+005+63192.private | 0 .../{testdata => tests/normal}/README | 0 .../normal/dsset-subzone.example.com} | 0 .../{testdata => tests/normal}/example.com | 0 .../normal}/example.com.signed | 0 .../normal}/sql1.example.com | 0 .../normal}/sql1.example.com.signed | 0 .../normal}/sql2.example.com | 0 .../normal}/sql2.example.com.signed | 0 src/lib/python/isc/datasrc/master.py | 256 +++++++++++++----- 55 files changed, 811 insertions(+), 88 deletions(-) create mode 100644 src/bin/loadzone/tests/correct/Makefile.am create mode 100644 src/bin/loadzone/tests/correct/correct_test.sh.in create mode 100644 src/bin/loadzone/tests/correct/example.db create mode 100644 src/bin/loadzone/tests/correct/get_zonedatas.py create mode 100644 src/bin/loadzone/tests/correct/inclsub.db create mode 100644 src/bin/loadzone/tests/correct/include.db create mode 100644 src/bin/loadzone/tests/correct/known.test.out create mode 100644 src/bin/loadzone/tests/correct/mix1.db create mode 100644 src/bin/loadzone/tests/correct/mix1sub1.db create mode 100644 src/bin/loadzone/tests/correct/mix1sub2.db create mode 100644 src/bin/loadzone/tests/correct/mix2.db create mode 100644 src/bin/loadzone/tests/correct/mix2sub1.txt create mode 100644 src/bin/loadzone/tests/correct/mix2sub2.txt create mode 100644 src/bin/loadzone/tests/correct/ttl1.db create mode 100644 src/bin/loadzone/tests/correct/ttl2.db create mode 100644 src/bin/loadzone/tests/correct/ttlext.db create mode 100644 src/bin/loadzone/tests/error/Makefile.am create mode 100644 src/bin/loadzone/tests/error/error.known create mode 100644 src/bin/loadzone/tests/error/error_test.sh.in create mode 100644 src/bin/loadzone/tests/error/formerr1.db create mode 100644 src/bin/loadzone/tests/error/formerr2.db create mode 100644 src/bin/loadzone/tests/error/formerr3.db create mode 100644 src/bin/loadzone/tests/error/formerr4.db create mode 100644 src/bin/loadzone/tests/error/formerr5.db create mode 100644 src/bin/loadzone/tests/error/include.txt create mode 100644 src/bin/loadzone/tests/error/keyerror1.db create mode 100644 src/bin/loadzone/tests/error/keyerror2.db create mode 100644 src/bin/loadzone/tests/error/keyerror3.db create mode 100644 src/bin/loadzone/tests/error/originerr1.db create mode 100644 src/bin/loadzone/tests/error/originerr2.db rename src/bin/loadzone/{testdata => tests/normal}/Kexample.com.+005+04456.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Kexample.com.+005+04456.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/Kexample.com.+005+33495.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Kexample.com.+005+33495.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql1.example.com.+005+12447.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql1.example.com.+005+12447.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql1.example.com.+005+33313.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql1.example.com.+005+33313.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql2.example.com.+005+38482.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql2.example.com.+005+38482.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql2.example.com.+005+63192.key (100%) rename src/bin/loadzone/{testdata => tests/normal}/Ksql2.example.com.+005+63192.private (100%) rename src/bin/loadzone/{testdata => tests/normal}/README (100%) rename src/bin/loadzone/{testdata/dsset-subzone.example.com. => tests/normal/dsset-subzone.example.com} (100%) rename src/bin/loadzone/{testdata => tests/normal}/example.com (100%) rename src/bin/loadzone/{testdata => tests/normal}/example.com.signed (100%) rename src/bin/loadzone/{testdata => tests/normal}/sql1.example.com (100%) rename src/bin/loadzone/{testdata => tests/normal}/sql1.example.com.signed (100%) rename src/bin/loadzone/{testdata => tests/normal}/sql2.example.com (100%) rename src/bin/loadzone/{testdata => tests/normal}/sql2.example.com.signed (100%) diff --git a/ChangeLog b/ChangeLog index 7b2743ec96..6c2edf18f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ + 65. [func] shentingting + Added verbose options to exactly what is happening with loadzone. + Added loadzone test suite of different file formats to load. + (tingting-loadzone, svn r2339) + 64. [func] jerry Added python logging framework. It is for testing and experimenting with logging ideas. Currently, it supports three channels(file, diff --git a/configure.ac b/configure.ac index a70c455e10..1919099581 100644 --- a/configure.ac +++ b/configure.ac @@ -415,6 +415,8 @@ AC_CONFIG_FILES([Makefile src/bin/cfgmgr/tests/Makefile src/bin/host/Makefile src/bin/loadzone/Makefile + src/bin/loadzone/tests/correct/Makefile + src/bin/loadzone/tests/error/Makefile src/bin/msgq/Makefile src/bin/msgq/tests/Makefile src/bin/auth/Makefile @@ -464,6 +466,8 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py src/bin/bindctl/bindctl-source.py src/bin/bindctl/tests/bindctl_test src/bin/loadzone/run_loadzone.sh + src/bin/loadzone/tests/correct/correct_test.sh + src/bin/loadzone/tests/error/error_test.sh src/bin/loadzone/b10-loadzone.py src/bin/usermgr/run_b10-cmdctl-usermgr.sh src/bin/usermgr/b10-cmdctl-usermgr.py @@ -491,6 +495,8 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py chmod +x src/bin/bindctl/tests/bindctl_test chmod +x src/bin/bindctl/run_bindctl.sh chmod +x src/bin/loadzone/run_loadzone.sh + chmod +x src/bin/loadzone/tests/correct/correct_test.sh + chmod +x src/bin/loadzone/tests/error/error_test.sh chmod +x src/bin/usermgr/run_b10-cmdctl-usermgr.sh chmod +x src/bin/msgq/run_msgq.sh chmod +x src/bin/msgq/tests/msgq_test diff --git a/src/bin/loadzone/Makefile.am b/src/bin/loadzone/Makefile.am index 1a29ef25c7..7895f65f4a 100644 --- a/src/bin/loadzone/Makefile.am +++ b/src/bin/loadzone/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS = tests/correct +SUBDIRS += tests/error bin_SCRIPTS = b10-loadzone CLEANFILES = b10-loadzone @@ -22,23 +24,27 @@ install-data-local: $(mkinstalldirs) $(DESTDIR)/@localstatedir@/@PACKAGE@ # TODO: permissions handled later -EXTRA_DIST += testdata/README -EXTRA_DIST += testdata/dsset-subzone.example.com. -EXTRA_DIST += testdata/example.com -EXTRA_DIST += testdata/example.com.signed -EXTRA_DIST += testdata/Kexample.com.+005+04456.key -EXTRA_DIST += testdata/Kexample.com.+005+04456.private -EXTRA_DIST += testdata/Kexample.com.+005+33495.key -EXTRA_DIST += testdata/Kexample.com.+005+33495.private -EXTRA_DIST += testdata/Ksql1.example.com.+005+12447.key -EXTRA_DIST += testdata/Ksql1.example.com.+005+12447.private -EXTRA_DIST += testdata/Ksql1.example.com.+005+33313.key -EXTRA_DIST += testdata/Ksql1.example.com.+005+33313.private -EXTRA_DIST += testdata/Ksql2.example.com.+005+38482.key -EXTRA_DIST += testdata/Ksql2.example.com.+005+38482.private -EXTRA_DIST += testdata/Ksql2.example.com.+005+63192.key -EXTRA_DIST += testdata/Ksql2.example.com.+005+63192.private -EXTRA_DIST += testdata/sql1.example.com -EXTRA_DIST += testdata/sql1.example.com.signed -EXTRA_DIST += testdata/sql2.example.com -EXTRA_DIST += testdata/sql2.example.com.signed +EXTRA_DIST += tests/normal/README +EXTRA_DIST += tests/normal/dsset-subzone.example.com. +EXTRA_DIST += tests/normal/example.com +EXTRA_DIST += tests/normal/example.com.signed +EXTRA_DIST += tests/normal/Kexample.com.+005+04456.key +EXTRA_DIST += tests/normal/Kexample.com.+005+04456.private +EXTRA_DIST += tests/normal/Kexample.com.+005+33495.key +EXTRA_DIST += tests/normal/Kexample.com.+005+33495.private +EXTRA_DIST += tests/normal/Ksql1.example.com.+005+12447.key +EXTRA_DIST += tests/normal/Ksql1.example.com.+005+12447.private +EXTRA_DIST += tests/normal/Ksql1.example.com.+005+33313.key +EXTRA_DIST += tests/normal/Ksql1.example.com.+005+33313.private +EXTRA_DIST += tests/normal/Ksql2.example.com.+005+38482.key +EXTRA_DIST += tests/normal/Ksql2.example.com.+005+38482.private +EXTRA_DIST += tests/normal/Ksql2.example.com.+005+63192.key +EXTRA_DIST += tests/normal/Ksql2.example.com.+005+63192.private +EXTRA_DIST += tests/normal/sql1.example.com +EXTRA_DIST += tests/normal/sql1.example.com.signed +EXTRA_DIST += tests/normal/sql2.example.com +EXTRA_DIST += tests/normal/sql2.example.com.signed + +pytest: + $(SHELL) tests/correct/correct_test.sh + $(SHELL) tests/error/error_test.sh diff --git a/src/bin/loadzone/b10-loadzone.py.in b/src/bin/loadzone/b10-loadzone.py.in index 98525985d6..6c0704c514 100644 --- a/src/bin/loadzone/b10-loadzone.py.in +++ b/src/bin/loadzone/b10-loadzone.py.in @@ -19,7 +19,8 @@ import sys; sys.path.append ('@@PYTHONPATH@@') import re, getopt import isc.datasrc from isc.datasrc.master import MasterFile - +import time +import os ######################################################################### # usage: print usage note and exit ######################################################################### @@ -57,23 +58,32 @@ def main(): if len(args) != 1: usage() zonefile = args[0] - + verbose = os.isatty(sys.stdout.fileno()) try: - master = MasterFile(zonefile, initial_origin) + master = MasterFile(zonefile, initial_origin, verbose) except Exception as e: - print("Error reading zone file: " + str(e)) + sys.stderr.write("Error reading zone file: %s\n" % str(e)) exit(1) try: zone = master.zonename() + if verbose: + sys.stdout.write("Using SQLite3 database file %s\n" % dbfile) + sys.stdout.write("Zone name is %s\n" % zone) + sys.stdout.write("Loading file \"%s\"\n" % zonefile) except Exception as e: - print("Error reading zone file: " + str(e)) + sys.stdout.write("\n") + sys.stderr.write("Error reading zone file: %s\n" % str(e)) exit(1) try: isc.datasrc.sqlite3_ds.load(dbfile, zone, master.zonedata) + if verbose: + master.closeverbose() + sys.stdout.write("\nDone.\n") except Exception as e: - print("Error loading database: " + str(e)) + sys.stdout.write("\n") + sys.stderr.write("Error loading database: %s\n"% str(e)) exit(1) if __name__ == "__main__": diff --git a/src/bin/loadzone/tests/correct/Makefile.am b/src/bin/loadzone/tests/correct/Makefile.am new file mode 100644 index 0000000000..fb146275a0 --- /dev/null +++ b/src/bin/loadzone/tests/correct/Makefile.am @@ -0,0 +1,24 @@ +PYTESTS = correct_test.sh +EXTRA_DIST = get_zonedatas.py +EXTRA_DIST += include.db +EXTRA_DIST += inclsub.db +EXTRA_DIST += known.test.out +EXTRA_DIST += mix1.db +EXTRA_DIST += mix1sub1.db +EXTRA_DIST += mix1sub2.db +EXTRA_DIST += mix2.db +EXTRA_DIST += mix2sub1.txt +EXTRA_DIST += mix2sub2.txt +EXTRA_DIST += ttl1.db +EXTRA_DIST += ttl2.db +EXTRA_DIST += ttlext.db + +# 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: + 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_srcdir)/$$pytest ; \ + done diff --git a/src/bin/loadzone/tests/correct/correct_test.sh.in b/src/bin/loadzone/tests/correct/correct_test.sh.in new file mode 100644 index 0000000000..ebd6993cca --- /dev/null +++ b/src/bin/loadzone/tests/correct/correct_test.sh.in @@ -0,0 +1,72 @@ +#! /bin/sh + +# Copyright (C) 2010 Internet Systems Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} +export PYTHON_EXEC + +PYTHONPATH=@abs_top_builddir@/src/lib/python +export PYTHONPATH + +LOADZONE_PATH=@abs_top_srcdir@/src/bin/loadzone +status=0 +echo "Loadzone include. from include.db file" +cd ${LOADZONE_PATH}/tests/correct +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 include.db >> /dev/null + +echo "loadzone ttl1. from ttl1.db file" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttl1.db >> /dev/null + +echo "loadzone ttl2. from ttl2.db file" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttl2.db >> /dev/null + +echo "loadzone mix1. from mix1.db" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 mix1.db >> /dev/null + +echo "loadzone mix2. from mix2.db" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 mix2.db >> /dev/null + +echo "loadzone ttlext. from ttlext.db" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttlext.db >> /dev/null + +echo "loadzone example.com. from example.db" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 example.db >> /dev/null + +echo "I:test master file \$INCLUDE semantics" +echo "I:test master file BIND 8 compatibility TTL and \$TTL semantics" +echo "I:test master file RFC1035 TTL and \$TTL semantics" +echo "I:test master file BIND8 compatibility and mixed \$INCLUDE with \$TTL semantics" +echo "I:test master file RFC1035 TTL and mixed \$INCLUDE with \$TTL semantics" +echo "I:test master file BIND9 extenstion of TTL" +echo "I:test master file RFC1035 missing CLASS, TTL, NAME semantics" + +${PYTHON_EXEC} get_zonedatas.py > test.out +echo "Compare test results." +diff test.out known.test.out || status=1 + +echo "Clean tmp files." +rm -f zone.sqlite3 +rm -f test.out +echo "I:exit status: $status" +echo "------------------------------------------------------------------------------" +echo "Ran 7 test files" +echo "" +if [ "$status" -eq 1 ] ;then + echo "ERROR" +else + echo "OK" +fi +exit $status diff --git a/src/bin/loadzone/tests/correct/example.db b/src/bin/loadzone/tests/correct/example.db new file mode 100644 index 0000000000..fe012cf8ec --- /dev/null +++ b/src/bin/loadzone/tests/correct/example.db @@ -0,0 +1,14 @@ +;This file includes all kinds of rr form. missing name, ttl and class or not. +$ORIGIN example.com. +$TTL 60 +@ IN SOA ns1.example.com. hostmaster.example.com. (1 43200 900 1814400 7200) + IN 20 NS ns1 + NS ns2 +ns1 IN 30 A 192.168.1.102 + 70 NS ns3 + IN NS ns4 + 10 IN MX 10 mail.example.com. +ns2 80 A 1.1.1.1 +ns3 IN A 2.2.2.2 +ns4 A 3.3.3.3 +ns5 90 IN A 4.4.4.4 diff --git a/src/bin/loadzone/tests/correct/get_zonedatas.py b/src/bin/loadzone/tests/correct/get_zonedatas.py new file mode 100644 index 0000000000..de629f2a10 --- /dev/null +++ b/src/bin/loadzone/tests/correct/get_zonedatas.py @@ -0,0 +1,8 @@ +from isc.datasrc import sqlite3_ds +import sys +ZONE_FILE = "zone.sqlite3" +zonename_set = ["include.", "ttl1.", "ttl2.", "mix1.", "mix2.", "ttlext.", "example.com."] +for zone_name in zonename_set: + for rr_data in sqlite3_ds.get_zone_datas(zone_name, ZONE_FILE): + data_len = len(rr_data[2]) + sys.stdout.write(rr_data[2] + '\t\t' + str(rr_data[4]) + '\tIN\t' + rr_data[5] + '\t' + rr_data[7] + '\n') diff --git a/src/bin/loadzone/tests/correct/inclsub.db b/src/bin/loadzone/tests/correct/inclsub.db new file mode 100644 index 0000000000..242e5ecb8b --- /dev/null +++ b/src/bin/loadzone/tests/correct/inclsub.db @@ -0,0 +1,4 @@ +a 300 A 10.0.1.1 +$ORIGIN foo +b 300 A 10.0.2.2 + diff --git a/src/bin/loadzone/tests/correct/include.db b/src/bin/loadzone/tests/correct/include.db new file mode 100644 index 0000000000..f60a24007b --- /dev/null +++ b/src/bin/loadzone/tests/correct/include.db @@ -0,0 +1,23 @@ +$ORIGIN include. ; initialize origin +$TTL 300 +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns + +ns A 127.0.0.1 + +a A 10.0.0.1 +$INCLUDE inclsub.db sub ; a.include. is the relative domain name origin for the included file +; use the current domain name + A 99.99.99.99 +b A 10.0.0.2 +$ORIGIN b +$INCLUDE inclsub.db +; use the current domain name + A 10.0.0.99 +c A 10.0.0.3 diff --git a/src/bin/loadzone/tests/correct/known.test.out b/src/bin/loadzone/tests/correct/known.test.out new file mode 100644 index 0000000000..8e2fe3cf3c --- /dev/null +++ b/src/bin/loadzone/tests/correct/known.test.out @@ -0,0 +1,79 @@ +include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600 +include. 300 IN NS ns.include. +ns.include. 300 IN A 127.0.0.1 +a.include. 300 IN A 10.0.0.1 +a.sub.include. 300 IN A 10.0.1.1 +b.foo.sub.include. 300 IN A 10.0.2.2 +a.include. 300 IN A 99.99.99.99 +b.include. 300 IN A 10.0.0.2 +a.b.include. 300 IN A 10.0.1.1 +b.foo.b.include. 300 IN A 10.0.2.2 +b.include. 300 IN A 10.0.0.99 +c.b.include. 300 IN A 10.0.0.3 +ttl1. 3 IN SOA ns.ttl1. hostmaster.ttl1. 1 3600 1800 1814400 3 +ttl1. 3 IN NS ns.ttl1. +ns.ttl1. 3 IN A 10.53.0.1 +a.ttl1. 3 IN TXT "soa minttl 3" +b.ttl1. 2 IN TXT "explicit ttl 2" +c.ttl1. 3 IN TXT "soa minttl 3" +d.ttl1. 1 IN TXT "default ttl 1" +e.ttl1. 4 IN TXT "explicit ttl 4" +f.ttl1. 1 IN TXT "default ttl 1" +ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3 +ttl2. 1 IN NS ns.ttl2. +ns.ttl2. 1 IN A 10.53.0.1 +a.ttl2. 1 IN TXT "inherited ttl 1" +b.ttl2. 2 IN TXT "explicit ttl 2" +c.ttl2. 2 IN TXT "inherited ttl 2" +d.ttl2. 3 IN TXT "default ttl 3" +e.ttl2. 2 IN TXT "explicit ttl 2" +f.ttl2. 3 IN TXT "default ttl 3" +mix1. 3 IN SOA ns.mix1. hostmaster.mix1. 1 3600 1800 1814400 3 +mix1. 3 IN NS ns.mix1. +ns.mix1. 3 IN A 10.53.0.1 +a.mix1. 3 IN TXT "soa minttl 3" +b.mix1. 2 IN TXT "explicit ttl 2" +a.mix1. 3 IN TXT "soa minttl 3" +b.foo.mix1. 3 IN TXT "soa minttl 3" +c.mix1. 3 IN TXT "soa minttl 3" +d.mix1. 1 IN TXT "default ttl 1" +e.mix1. 4 IN TXT "explicit ttl 4" +f.mix1. 1 IN TXT "default ttl 1" +i.mix1. 1 IN TXT "default ttl 1" +g.mix1. 5 IN TXT "default ttl 5" +h.mix1. 5 IN TXT "the include ttl 5" +mix2. 1 IN SOA ns.mix2. hostmaster.mix2. 1 3600 1800 1814400 3 +mix2. 1 IN NS ns.mix2. +ns.mix2. 1 IN A 10.53.0.1 +a.mix2. 1 IN TXT "inherited ttl 1" +h.mix2. 1 IN TXT "inherited ttl 1" +g.mix2. 6 IN TXT "inherited ttl 6" +b.mix2. 6 IN TXT "explicit ttl 6" +c.mix2. 2 IN TXT "inherited ttl 2" +m.mix2. 6 IN TXT "explicit ttl 6" +d.mix2. 3 IN TXT "default ttl 3" +e.mix2. 2 IN TXT "explicit ttl 2" +n.mix2. 3 IN TXT "default ttl 3" +f.mix2. 3 IN TXT "default ttl 3" +g.mix2. 5 IN TXT "default ttl 5" +f.mix2. 5 IN TXT "default ttl 5" +ttlext. 3 IN SOA ns.ttlext. hostmaster.ttlext. 1 3600 1800 1814400 3 +ttlext. 3 IN NS ns.ttlext. +ns.ttlext. 3 IN A 10.53.0.1 +a.ttlext. 3 IN TXT "soa minttl 3" +b.ttlext. 2 IN TXT "explicit ttl 2" +c.ttlext. 3 IN TXT "soa minttl 3" +d.ttlext. 600 IN TXT "default ttl 600" +e.ttlext. 4 IN TXT "explicit ttl 4" +f.ttlext. 600 IN TXT "default ttl 600" +example.com. 60 IN SOA ns1.example.com. hostmaster.example.com. 1 43200 900 1814400 7200 +example.com. 20 IN NS ns1.example.com. +example.com. 60 IN NS ns2.example.com. +ns1.example.com. 30 IN A 192.168.1.102 +ns1.example.com. 70 IN NS ns3.example.com. +ns1.example.com. 60 IN NS ns4.example.com. +ns1.example.com. 10 IN MX 10 mail.example.com. +ns2.example.com. 80 IN A 1.1.1.1 +ns3.example.com. 60 IN A 2.2.2.2 +ns4.example.com. 60 IN A 3.3.3.3 +ns5.example.com. 90 IN A 4.4.4.4 diff --git a/src/bin/loadzone/tests/correct/mix1.db b/src/bin/loadzone/tests/correct/mix1.db new file mode 100644 index 0000000000..da562ffc46 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix1.db @@ -0,0 +1,21 @@ +; $Id: ttl1.db,v 1.6 2007/06/19 23:47:04 tbox Exp $ +$ORIGIN mix1. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "soa minttl 3" +b 2 TXT "explicit ttl 2" +$INCLUDE mix1sub1.db +c TXT "soa minttl 3" +$TTL 1 +d TXT "default ttl 1" +e 4 TXT "explicit ttl 4" +f TXT "default ttl 1" +$INCLUDE mix1sub2.db +h 5 TXT "the include ttl 5" diff --git a/src/bin/loadzone/tests/correct/mix1sub1.db b/src/bin/loadzone/tests/correct/mix1sub1.db new file mode 100644 index 0000000000..9174a39986 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix1sub1.db @@ -0,0 +1,3 @@ +a TXT "soa minttl 3" +$ORIGIN foo +b TXT "soa minttl 3" diff --git a/src/bin/loadzone/tests/correct/mix1sub2.db b/src/bin/loadzone/tests/correct/mix1sub2.db new file mode 100644 index 0000000000..e704d7f805 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix1sub2.db @@ -0,0 +1,3 @@ +i TXT "default ttl 1" +$TTL 5 +g TXT "default ttl 5" diff --git a/src/bin/loadzone/tests/correct/mix2.db b/src/bin/loadzone/tests/correct/mix2.db new file mode 100644 index 0000000000..2c8153dc65 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix2.db @@ -0,0 +1,21 @@ +$ORIGIN mix2. +@ 1 IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "inherited ttl 1" +$INCLUDE mix2sub1.txt +b TXT "explicit ttl 6" +c 2 TXT "inherited ttl 2" +m TXT "explicit ttl 6" +$TTL 3 +d TXT "default ttl 3" +e 2 TXT "explicit ttl 2" +n TXT "default ttl 3" +$INCLUDE mix2sub2.txt +f TXT "default ttl 5" diff --git a/src/bin/loadzone/tests/correct/mix2sub1.txt b/src/bin/loadzone/tests/correct/mix2sub1.txt new file mode 100644 index 0000000000..1db4411bb5 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix2sub1.txt @@ -0,0 +1,3 @@ +h TXT "inherited ttl 1" +$TTL 6 +g TXT "inherited ttl 6" diff --git a/src/bin/loadzone/tests/correct/mix2sub2.txt b/src/bin/loadzone/tests/correct/mix2sub2.txt new file mode 100644 index 0000000000..96d53c1283 --- /dev/null +++ b/src/bin/loadzone/tests/correct/mix2sub2.txt @@ -0,0 +1,3 @@ +f TXT "default ttl 3" +$TTL 5 +g TXT "default ttl 5" diff --git a/src/bin/loadzone/tests/correct/ttl1.db b/src/bin/loadzone/tests/correct/ttl1.db new file mode 100644 index 0000000000..aa6e2bb5d8 --- /dev/null +++ b/src/bin/loadzone/tests/correct/ttl1.db @@ -0,0 +1,17 @@ +$ORIGIN ttl1. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "soa minttl 3" +b 2 TXT "explicit ttl 2" +c TXT "soa minttl 3" +$TTL 1 +d TXT "default ttl 1" +e 4 TXT "explicit ttl 4" +f TXT "default ttl 1" diff --git a/src/bin/loadzone/tests/correct/ttl2.db b/src/bin/loadzone/tests/correct/ttl2.db new file mode 100644 index 0000000000..f7f6eee3b1 --- /dev/null +++ b/src/bin/loadzone/tests/correct/ttl2.db @@ -0,0 +1,17 @@ +$ORIGIN ttl2. +@ 1 IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "inherited ttl 1" +b 2 TXT "explicit ttl 2" +c TXT "inherited ttl 2" +$TTL 3 ; a new ttl +d TXT "default ttl 3" +e 2 TXT "explicit ttl 2" +f TXT "default ttl 3" diff --git a/src/bin/loadzone/tests/correct/ttlext.db b/src/bin/loadzone/tests/correct/ttlext.db new file mode 100644 index 0000000000..8ad6103a0c --- /dev/null +++ b/src/bin/loadzone/tests/correct/ttlext.db @@ -0,0 +1,18 @@ +; $Id: ttl1.db,v 1.6 2007/06/19 23:47:04 tbox Exp $ +$ORIGIN ttlext. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "soa minttl 3" +b 2S TXT "explicit ttl 2" +c TXT "soa minttl 3" +$TTL 10M ; bind9 extention ttl +d TXT "default ttl 600" +e 4 TXT "explicit ttl 4" +f TXT "default ttl 600" diff --git a/src/bin/loadzone/tests/error/Makefile.am b/src/bin/loadzone/tests/error/Makefile.am new file mode 100644 index 0000000000..2ce860cd16 --- /dev/null +++ b/src/bin/loadzone/tests/error/Makefile.am @@ -0,0 +1,25 @@ +PYTESTS = error_test.sh + +EXTRA_DIST = error.known +EXTRA_DIST += formerr1.db +EXTRA_DIST += formerr2.db +EXTRA_DIST += formerr3.db +EXTRA_DIST += formerr4.db +EXTRA_DIST += formerr5.db +EXTRA_DIST += include.txt +EXTRA_DIST += keyerror1.db +EXTRA_DIST += keyerror2.db +EXTRA_DIST += keyerror3.db +EXTRA_DIST += nofilenane.db +EXTRA_DIST += originerr1.db +EXTRA_DIST += originerr2.db + +# 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: + 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_srcdir)/$$pytest ; \ + done diff --git a/src/bin/loadzone/tests/error/error.known b/src/bin/loadzone/tests/error/error.known new file mode 100644 index 0000000000..5961064278 --- /dev/null +++ b/src/bin/loadzone/tests/error/error.known @@ -0,0 +1,11 @@ +Error reading zone file: Cannot parse RR, No $ORIGIN: @ IN SOA ns hostmaster 1 3600 1800 1814400 3600 +Error reading zone file: $ORIGIN is not absolute in record:$ORIGIN com +Error reading zone file: Cannot parse RR: $TL 300 +Error reading zone file: Cannot parse RR: $OIGIN com. +Error loading database: Error while loading com.: Cannot parse RR: $INLUDE file.txt +Error loading database: Error while loading com.: Invalid $include format +Error loading database: Error while loading com.: Cannot parse RR, No $ORIGIN: include.txt sub +Error reading zone file: Invalid TTL: "" +Error reading zone file: Invalid TTL: "M" +Error loading database: Error while loading com.: Cannot parse RR: b "no type error!" +Error reading zone file: Could not open bogusfile diff --git a/src/bin/loadzone/tests/error/error_test.sh.in b/src/bin/loadzone/tests/error/error_test.sh.in new file mode 100644 index 0000000000..ff1872ca59 --- /dev/null +++ b/src/bin/loadzone/tests/error/error_test.sh.in @@ -0,0 +1,75 @@ +#! /bin/sh + +# Copyright (C) 2010 Internet Systems Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM +# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} +export PYTHON_EXEC + +PYTHONPATH=@abs_top_builddir@/src/lib/python +export PYTHONPATH + +LOADZONE_PATH=@abs_top_srcdir@/src/bin/loadzone +export LOADZONE_PATH +status=0 +cd ${LOADZONE_PATH}/tests/error + +echo "Test no \$ORIGIN error in zone file" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 originerr1.db 1> /dev/null 2> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 originerr2.db 1> /dev/null 2>> error.out + +echo "Test: key word TTL spell error" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror1.db 1> /dev/null 2>> error.out + +echo "Test: key word ORIGIN spell error" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror2.db 1> /dev/null 2>> error.out + +echo "Test: key INCLUDE spell error" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror3.db 1> /dev/null 2>> error.out + +echo "Test: include formal error, miss filename" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr1.db 1> /dev/null 2>>error.out + +echo "Test: include form error, domain is not absolute" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr2.db 1> /dev/null 2>> error.out + +echo "Test: TTL form error, no ttl value" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr3.db 1> /dev/null 2>> error.out + +echo "Test: TTL form error, ttl value error" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr4.db 1> /dev/null 2>> error.out + +echo "Test: rr form error, no type" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr5.db 1> /dev/null 2>> error.out + +echo "Test: zone file is bogus" +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 bogusfile 1> /dev/null 2>> error.out + +diff error.out error.known || status=1 + +echo "Clean tmp file." +rm -f error.out +rm -f zone.sqlite3 + +echo "I:exit status:$status" +echo "-----------------------------------------------------------------------------" +echo "Ran 11 test files" +echo "" +if [ "$status" -eq 1 ];then + echo "ERROR" +else + echo "OK" +fi +exit $status diff --git a/src/bin/loadzone/tests/error/formerr1.db b/src/bin/loadzone/tests/error/formerr1.db new file mode 100644 index 0000000000..9bab49fec8 --- /dev/null +++ b/src/bin/loadzone/tests/error/formerr1.db @@ -0,0 +1,13 @@ +$TTL 300 +$ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +$INCLUDE +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/formerr2.db b/src/bin/loadzone/tests/error/formerr2.db new file mode 100644 index 0000000000..3d7dd485a1 --- /dev/null +++ b/src/bin/loadzone/tests/error/formerr2.db @@ -0,0 +1,12 @@ +$TTL 300 +com. IN SOA ns.com. hostmaster.com. ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns.example.com. +ns.com. A 127.0.0.1 +$INCLUDE include.txt sub +a.com. A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/formerr3.db b/src/bin/loadzone/tests/error/formerr3.db new file mode 100644 index 0000000000..c1c39755c3 --- /dev/null +++ b/src/bin/loadzone/tests/error/formerr3.db @@ -0,0 +1,12 @@ +$TTL +$ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/formerr4.db b/src/bin/loadzone/tests/error/formerr4.db new file mode 100644 index 0000000000..d37515ff8c --- /dev/null +++ b/src/bin/loadzone/tests/error/formerr4.db @@ -0,0 +1,12 @@ +$TTL M +$ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/formerr5.db b/src/bin/loadzone/tests/error/formerr5.db new file mode 100644 index 0000000000..fa5983fa22 --- /dev/null +++ b/src/bin/loadzone/tests/error/formerr5.db @@ -0,0 +1,13 @@ +$TTL 2M +$ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 ; ip value +b "no type error!" +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/include.txt b/src/bin/loadzone/tests/error/include.txt new file mode 100644 index 0000000000..9b4c57cbbc --- /dev/null +++ b/src/bin/loadzone/tests/error/include.txt @@ -0,0 +1 @@ +a 300 A 127.0.0.1 diff --git a/src/bin/loadzone/tests/error/keyerror1.db b/src/bin/loadzone/tests/error/keyerror1.db new file mode 100644 index 0000000000..738436280c --- /dev/null +++ b/src/bin/loadzone/tests/error/keyerror1.db @@ -0,0 +1,12 @@ +$TL 300 +@ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/keyerror2.db b/src/bin/loadzone/tests/error/keyerror2.db new file mode 100644 index 0000000000..5c97e4ef30 --- /dev/null +++ b/src/bin/loadzone/tests/error/keyerror2.db @@ -0,0 +1,12 @@ +$TTL 300 +$OIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/keyerror3.db b/src/bin/loadzone/tests/error/keyerror3.db new file mode 100644 index 0000000000..eebb0aa385 --- /dev/null +++ b/src/bin/loadzone/tests/error/keyerror3.db @@ -0,0 +1,13 @@ +$TTL 300 +$ORIGIN com. +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +$INLUDE file.txt +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/originerr1.db b/src/bin/loadzone/tests/error/originerr1.db new file mode 100644 index 0000000000..fc20edc27c --- /dev/null +++ b/src/bin/loadzone/tests/error/originerr1.db @@ -0,0 +1,11 @@ +$TTL 300 +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/tests/error/originerr2.db b/src/bin/loadzone/tests/error/originerr2.db new file mode 100644 index 0000000000..2cb90eb222 --- /dev/null +++ b/src/bin/loadzone/tests/error/originerr2.db @@ -0,0 +1,12 @@ +$TTL 300 +$ORIGIN com +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns +ns A 127.0.0.1 +a A 10.0.0.1 diff --git a/src/bin/loadzone/testdata/Kexample.com.+005+04456.key b/src/bin/loadzone/tests/normal/Kexample.com.+005+04456.key similarity index 100% rename from src/bin/loadzone/testdata/Kexample.com.+005+04456.key rename to src/bin/loadzone/tests/normal/Kexample.com.+005+04456.key diff --git a/src/bin/loadzone/testdata/Kexample.com.+005+04456.private b/src/bin/loadzone/tests/normal/Kexample.com.+005+04456.private similarity index 100% rename from src/bin/loadzone/testdata/Kexample.com.+005+04456.private rename to src/bin/loadzone/tests/normal/Kexample.com.+005+04456.private diff --git a/src/bin/loadzone/testdata/Kexample.com.+005+33495.key b/src/bin/loadzone/tests/normal/Kexample.com.+005+33495.key similarity index 100% rename from src/bin/loadzone/testdata/Kexample.com.+005+33495.key rename to src/bin/loadzone/tests/normal/Kexample.com.+005+33495.key diff --git a/src/bin/loadzone/testdata/Kexample.com.+005+33495.private b/src/bin/loadzone/tests/normal/Kexample.com.+005+33495.private similarity index 100% rename from src/bin/loadzone/testdata/Kexample.com.+005+33495.private rename to src/bin/loadzone/tests/normal/Kexample.com.+005+33495.private diff --git a/src/bin/loadzone/testdata/Ksql1.example.com.+005+12447.key b/src/bin/loadzone/tests/normal/Ksql1.example.com.+005+12447.key similarity index 100% rename from src/bin/loadzone/testdata/Ksql1.example.com.+005+12447.key rename to src/bin/loadzone/tests/normal/Ksql1.example.com.+005+12447.key diff --git a/src/bin/loadzone/testdata/Ksql1.example.com.+005+12447.private b/src/bin/loadzone/tests/normal/Ksql1.example.com.+005+12447.private similarity index 100% rename from src/bin/loadzone/testdata/Ksql1.example.com.+005+12447.private rename to src/bin/loadzone/tests/normal/Ksql1.example.com.+005+12447.private diff --git a/src/bin/loadzone/testdata/Ksql1.example.com.+005+33313.key b/src/bin/loadzone/tests/normal/Ksql1.example.com.+005+33313.key similarity index 100% rename from src/bin/loadzone/testdata/Ksql1.example.com.+005+33313.key rename to src/bin/loadzone/tests/normal/Ksql1.example.com.+005+33313.key diff --git a/src/bin/loadzone/testdata/Ksql1.example.com.+005+33313.private b/src/bin/loadzone/tests/normal/Ksql1.example.com.+005+33313.private similarity index 100% rename from src/bin/loadzone/testdata/Ksql1.example.com.+005+33313.private rename to src/bin/loadzone/tests/normal/Ksql1.example.com.+005+33313.private diff --git a/src/bin/loadzone/testdata/Ksql2.example.com.+005+38482.key b/src/bin/loadzone/tests/normal/Ksql2.example.com.+005+38482.key similarity index 100% rename from src/bin/loadzone/testdata/Ksql2.example.com.+005+38482.key rename to src/bin/loadzone/tests/normal/Ksql2.example.com.+005+38482.key diff --git a/src/bin/loadzone/testdata/Ksql2.example.com.+005+38482.private b/src/bin/loadzone/tests/normal/Ksql2.example.com.+005+38482.private similarity index 100% rename from src/bin/loadzone/testdata/Ksql2.example.com.+005+38482.private rename to src/bin/loadzone/tests/normal/Ksql2.example.com.+005+38482.private diff --git a/src/bin/loadzone/testdata/Ksql2.example.com.+005+63192.key b/src/bin/loadzone/tests/normal/Ksql2.example.com.+005+63192.key similarity index 100% rename from src/bin/loadzone/testdata/Ksql2.example.com.+005+63192.key rename to src/bin/loadzone/tests/normal/Ksql2.example.com.+005+63192.key diff --git a/src/bin/loadzone/testdata/Ksql2.example.com.+005+63192.private b/src/bin/loadzone/tests/normal/Ksql2.example.com.+005+63192.private similarity index 100% rename from src/bin/loadzone/testdata/Ksql2.example.com.+005+63192.private rename to src/bin/loadzone/tests/normal/Ksql2.example.com.+005+63192.private diff --git a/src/bin/loadzone/testdata/README b/src/bin/loadzone/tests/normal/README similarity index 100% rename from src/bin/loadzone/testdata/README rename to src/bin/loadzone/tests/normal/README diff --git a/src/bin/loadzone/testdata/dsset-subzone.example.com. b/src/bin/loadzone/tests/normal/dsset-subzone.example.com similarity index 100% rename from src/bin/loadzone/testdata/dsset-subzone.example.com. rename to src/bin/loadzone/tests/normal/dsset-subzone.example.com diff --git a/src/bin/loadzone/testdata/example.com b/src/bin/loadzone/tests/normal/example.com similarity index 100% rename from src/bin/loadzone/testdata/example.com rename to src/bin/loadzone/tests/normal/example.com diff --git a/src/bin/loadzone/testdata/example.com.signed b/src/bin/loadzone/tests/normal/example.com.signed similarity index 100% rename from src/bin/loadzone/testdata/example.com.signed rename to src/bin/loadzone/tests/normal/example.com.signed diff --git a/src/bin/loadzone/testdata/sql1.example.com b/src/bin/loadzone/tests/normal/sql1.example.com similarity index 100% rename from src/bin/loadzone/testdata/sql1.example.com rename to src/bin/loadzone/tests/normal/sql1.example.com diff --git a/src/bin/loadzone/testdata/sql1.example.com.signed b/src/bin/loadzone/tests/normal/sql1.example.com.signed similarity index 100% rename from src/bin/loadzone/testdata/sql1.example.com.signed rename to src/bin/loadzone/tests/normal/sql1.example.com.signed diff --git a/src/bin/loadzone/testdata/sql2.example.com b/src/bin/loadzone/tests/normal/sql2.example.com similarity index 100% rename from src/bin/loadzone/testdata/sql2.example.com rename to src/bin/loadzone/tests/normal/sql2.example.com diff --git a/src/bin/loadzone/testdata/sql2.example.com.signed b/src/bin/loadzone/tests/normal/sql2.example.com.signed similarity index 100% rename from src/bin/loadzone/testdata/sql2.example.com.signed rename to src/bin/loadzone/tests/normal/sql2.example.com.signed diff --git a/src/lib/python/isc/datasrc/master.py b/src/lib/python/isc/datasrc/master.py index 55556ccb24..566f1b4673 100644 --- a/src/lib/python/isc/datasrc/master.py +++ b/src/lib/python/isc/datasrc/master.py @@ -16,7 +16,8 @@ # $Id$ import sys, re, string - +import time +import os ######################################################################### # define exceptions ######################################################################### @@ -102,7 +103,7 @@ def isname(s): # isttl: check whether a string is a valid TTL specifier. # returns: boolean ######################################################################### -ttl_regex = re.compile('[0-9]+[wdhms]?', re.I) +ttl_regex = re.compile('([0-9]+[wdhms]?)+', re.I) def isttl(s): global ttl_regex if ttl_regex.match(s): @@ -121,19 +122,26 @@ def isttl(s): # MasterFileError ######################################################################### def parse_ttl(s): - m = re.match('([0-9]+)(.*)', s) - if not m: + sum = 0 + if not isttl(s): raise MasterFileError('Invalid TTL: ' + s) - ttl, suffix = int(m.group(1)), m.group(2) - if suffix.lower() == 'w': - ttl *= 604800 - elif suffix.lower() == 'd': - ttl *= 86400 - elif suffix.lower() == 'h': - ttl *= 3600 - elif suffix.lower() == 'm': - ttl *= 60 - return str(ttl) + for ttl_expr in re.findall('\d+[wdhms]?', s, re.I): + if ttl_expr.isdigit(): + ttl = int(ttl_expr) + sum += ttl + continue + ttl = int(ttl_expr[:-1]) + suffix = ttl_expr[-1].lower() + if suffix == 'w': + ttl *= 604800 + elif suffix == 'd': + ttl *= 86400 + elif suffix == 'h': + ttl *= 3600 + elif suffix == 'm': + ttl *= 60 + sum += ttl + return str(sum) ######################################################################### # records: generator function to return complete RRs from the zone file, @@ -147,7 +155,9 @@ def records(input): record = [] complete = True paren = 0 + size = 0 for line in input: + size += len(line) list = cleanup(line).split() for word in list: if paren == 0: @@ -169,10 +179,12 @@ def records(input): if paren == 1 or not record: continue - + ret = ' '.join(record) record = [] - yield ret + oldsize = size + size = 0 + yield ret, oldsize ######################################################################### # define the MasterFile class for reading zone master files @@ -181,24 +193,62 @@ class MasterFile: __rrclass = 'IN' __maxttl = 0x7fffffff __ttl = '' + __lastttl = '' __zonefile = '' __name = '' + __file_level = 0 + __file_type = "" + __init_time = time.time() + __records_num = 0 - def __init__(self, filename, initial_origin = ''): - if initial_origin == '.': - initial_origin = '' + def __init__(self, filename, initial_origin = '', verbose = False): self.__initial_origin = initial_origin self.__origin = initial_origin + self.__datafile = filename + + try: + self.__zonefile = open(filename, 'r') + except: + raise MasterFileError("Could not open " + filename) + self.__filesize = os.fstat(self.__zonefile.fileno()).st_size + + self.__cur = 0 + self.__numback = 0 + self.__verbose = verbose try: self.__zonefile = open(filename, 'r') except: raise MasterFileError("Could not open " + filename) + def __status(self): + interval = time.time() - MasterFile.__init_time + if self.__filesize == 0: + percent = 100 + else: + percent = (self.__cur * 100)/self.__filesize + + sys.stdout.write("\r" + (80 * " ")) + sys.stdout.write("\r%d RR(s) loaded in %d second(s) (%.2f%% of %s%s)"\ + % (MasterFile.__records_num, interval, percent, MasterFile.__file_type, self.__datafile)) + def __del__(self): if self.__zonefile: self.__zonefile.close() - - ######################################################################### + ######################################################################## + # check if the zonename is relative + # no then return + # yes , sets the relative domain name to the stated name + ####################################################################### + def __statedname(self, name, record): + if name[-1] != '.': + if not self.__origin: + raise MasterFileError("Cannot parse RR, No $ORIGIN: " + record) + elif self.__origin == '.': + name += '.' + else: + name += '.' + self.__origin + return name + ##################################################################### # handle $ORIGIN, $TTL and $GENERATE directives # (currently only $ORIGIN and $TTL are implemented) # input: @@ -216,20 +266,22 @@ class MasterFile: raise MasterFileError('Invalid $ORIGIN') if more: raise MasterFileError('Invalid $ORIGIN') - if second == '.': - self.__origin = '' - elif second[-1] == '.': + if second[-1] == '.': self.__origin = second - else: + elif not self.__origin: + raise MasterFileError("$ORIGIN is not absolute in record:%s" % s) + elif self.__origin != '.': self.__origin = second + '.' + self.__origin + else: + self.__origin = second + '.' return True elif re.match('\$ttl', first, re.I): if not second or not isttl(second): raise MasterFileError('Invalid TTL: "' + second + '"') if more: raise MasterFileError('Invalid $TTL statement') - self.__ttl = parse_ttl(second) - if int(self.__ttl) > self.__maxttl: + MasterFile.__ttl = parse_ttl(second) + if int(MasterFile.__ttl) > self.__maxttl: raise MasterFileError('TTL too high: ' + second) return True elif re.match('\$generate', first, re.I): @@ -246,14 +298,28 @@ class MasterFile: # throws: # MasterFileError ######################################################################### - __filename = re.compile('[\"\']*([^\'\"]+)[\"\']*') + __include_syntax1 = re.compile('\s+(\S+)(?:\s+(\S+))?$', re.I) + __include_syntax2 = re.compile('\s+"([^"]+)"(?:\s+(\S+))?$', re.I) + __include_syntax3 = re.compile("\s+'([^']+)'(?:\s+(\S+))?$", re.I) def __include(self, s): - first, rest = pop(s) - if re.match('\$include', first, re.I): - m = self.__filename.match(rest) - if m: - file = m.group(1) - return file + if not s.lower().startswith('$include'): + return "", "" + s = s[len('$include'):] + m = self.__include_syntax1.match(s) + if not m: + m = self.__include_syntax2.match(s) + if not m: + m = self.__include_syntax3.match(s) + if not m: + raise MasterFileError('Invalid $include format') + file = m.group(1) + if m.group(2): + if not isname(m.group(2)): + raise MasterFileError('Invalid $include format (invalid origin)') + origin = self.__statedname(m.group(2), s) + else: + origin = self.__origin + return file, origin ######################################################################### # try parsing an RR on the assumption that the type is specified in @@ -272,6 +338,14 @@ class MasterFile: if istype(list[3]): if isclass(list[2]) and isttl(list[1]) and isname(list[0]): name, ttl, rrclass, rrtype = list[0:4] + ttl = parse_ttl(ttl) + MasterFile.__lastttl = ttl or MasterFile.__lastttl + rdata = ' '.join(list[4:]) + ret = name, ttl, rrclass, rrtype, rdata + elif isclass(list[1]) and isttl(list[2]) and isname(list[0]): + name, rrclass, ttl, rrtype = list[0:4] + ttl = parse_ttl(ttl) + MasterFile.__lastttl = ttl or MasterFile.__lastttl rdata = ' '.join(list[4:]) ret = name, ttl, rrclass, rrtype, rdata return ret @@ -284,6 +358,9 @@ class MasterFile: # returns: # empty list if parse failed, else name, ttl, class, type, rdata ######################################################################### + def __getttl(self): + return MasterFile.__ttl or MasterFile.__lastttl + def __three(self, record, curname): ret = '' list = record.split() @@ -292,19 +369,25 @@ class MasterFile: if istype(list[2]) and not istype(list[1]): if isclass(list[1]) and not isttl(list[0]) and isname(list[0]): rrclass = list[1] - ttl = self.__ttl + ttl = self.__getttl() name = list[0] - elif not isclass(list[1]) and isttl(list[1]) and isname(list[0]): + elif not isclass(list[1]) and isttl(list[1]) and not isclass(list[0]) and isname(list[0]): rrclass = self.__rrclass ttl = parse_ttl(list[1]) + MasterFile.__lastttl = ttl or MasterFile.__lastttl name = list[0] elif curname and isclass(list[1]) and isttl(list[0]): - rrclass = self.__rrclass + rrclass = list[1] ttl = parse_ttl(list[0]) + MasterFile.__lastttl = ttl or MasterFile.__lastttl + name = curname + elif curname and isttl(list[1]) and isclass(list[0]): + rrclass = list[0] + ttl = parse_ttl(list[1]) + MasterFile.__lastttl = ttl or MasterFile.__lastttl name = curname else: return ret - rrtype = list[2] rdata = ' '.join(list[3:]) ret = name, ttl, rrclass, rrtype, rdata @@ -325,46 +408,81 @@ class MasterFile: list = record.split() if len(list) <= 2: return ret - if istype(list[1]): rrclass = self.__rrclass rrtype = list[1] if list[0].lower() == 'rrsig': name = curname - ttl = self.__ttl + ttl = self.__getttl() rrtype = list[0] rdata = ' '.join(list[1:]) elif isttl(list[0]): ttl = parse_ttl(list[0]) name = curname rdata = ' '.join(list[2:]) + elif isclass(list[0]): + ttl = self.__getttl() + name = curname + rdata = ' '.join(list[2:]) elif isname(list[0]): name = list[0] - ttl = self.__ttl + ttl = self.__getttl() rdata = ' '.join(list[2:]) else: raise MasterFileError("Cannot parse RR: " + record) ret = name, ttl, rrclass, rrtype, rdata - return ret + ######################################################################## + #close verbose + ###################################################################### + def closeverbose(self): + self.__status() + ######################################################################### # zonedata: generator function to parse a zone master file and return # each RR as a (name, ttl, type, class, rdata) tuple ######################################################################### def zonedata(self): name = '' + last_status = 0.0 + flag = 1 - for record in records(self.__zonefile): + for record, size in records(self.__zonefile): + if self.__verbose: + now = time.time() + if flag == 1: + self.__status() + flag = 0 + if now - last_status >= 1.0: + self.__status() + last_status = now + + self.__cur += size if self.__directive(record): continue - incl = self.__include(record) + incl, suborigin = self.__include(record) if incl: - sub = MasterFile(incl, self.__origin) - for name, ttl, rrclass, rrtype, rdata in sub.zonedata(): - yield (name, ttl, rrclass, rrtype, rdata) + if self.__filesize == 0: + percent = 100 + else: + percent = (self.__cur * 100)/self.__filesize + if self.__verbose: + sys.stdout.write("\r" + (80 * " ")) + sys.stdout.write("\rIncluding \"%s\" from \"%s\"\n" % (incl, self.__datafile)) + MasterFile.__file_level += 1 + MasterFile.__file_type = "included " + sub = MasterFile(incl, suborigin, self.__verbose) + + for rrname, ttl, rrclass, rrtype, rdata in sub.zonedata(): + yield (rrname, ttl, rrclass, rrtype, rdata) + if self.__verbose: + sub.closeverbose() + MasterFile.__file_level -= 1 + if MasterFile.__file_level == 0: + MasterFile.__file_type = "" del sub continue @@ -373,7 +491,7 @@ class MasterFile: if rl[0] == '@': rl[0] = self.__origin if not self.__origin: - rl[0] = '.' + raise MasterFileError("Cannot parse RR, No $ORIGIN: " + record) record = ' '.join(rl) result = self.__four(record, name) @@ -387,36 +505,43 @@ class MasterFile: if not result: first, rdata = pop(record) if istype(first): - result = name, self.__ttl, self.__rrclass, first, rdata + result = name, self.__getttl(), self.__rrclass, first, rdata if not result: raise MasterFileError("Cannot parse RR: " + record) name, ttl, rrclass, rrtype, rdata = result - if name[-1] != '.': - name += '.' + self.__origin + name = self.__statedname(name, record) if rrclass.lower() != 'in': raise MasterFileError("CH and HS zones not supported") - if not ttl: - raise MasterFileError("No TTL specified; zone rejected") - # add origin to rdata containing names, if necessary if rrtype.lower() in ('cname', 'dname', 'ns', 'ptr'): if not isname(rdata): raise MasterFileError("Invalid " + rrtype + ": " + rdata) - if rdata[-1] != '.': - rdata += '.' + self.__origin + rdata = self.__statedname(rdata, record) + if rrtype.lower() == 'soa': soa = rdata.split() if len(soa) < 2 or not isname(soa[0]) or not isname(soa[1]): raise MasterFileError("Invalid " + rrtype + ": " + rdata) - if soa[0][-1] != '.': - soa[0] += '.' + self.__origin - if soa[1][-1] != '.': - soa[1] += '.' + self.__origin + soa[0] = self.__statedname(soa[0], record) + soa[1] = self.__statedname(soa[1], record) + if not MasterFile.__ttl and not ttl: + MasterFile.__ttl = MasterFile.__ttl or parse_ttl(soa[-1]) + ttl = MasterFile.__ttl + + for index in range(3, len(soa)): + if isttl(soa[index]): + soa[index] = parse_ttl(soa[index]) + else : + raise MasterFileError("No TTL specified; in soa record!") rdata = ' '.join(soa) + + if not ttl: + raise MasterFileError("No TTL specified; zone rejected") + if rrtype.lower() == 'mx': mx = rdata.split() if len(mx) != 2 or not isname(mx[1]): @@ -424,7 +549,7 @@ class MasterFile: if mx[1][-1] != '.': mx[1] += '.' + self.__origin rdata = ' '.join(mx) - + MasterFile.__records_num += 1 yield (name, ttl, rrclass, rrtype, rdata) ######################################################################### @@ -436,16 +561,22 @@ class MasterFile: return self.__name old_origin = self.__origin self.__origin = self.__initial_origin + cur_value = self.__cur old_location = self.__zonefile.tell() + old_verbose = self.__verbose + self.__verbose = False self.__zonefile.seek(0) + for name, ttl, rrclass, rrtype, rdata in self.zonedata(): if rrtype.lower() == 'soa': break self.__zonefile.seek(old_location) self.__origin = old_origin + self.__cur = cur_value if rrtype.lower() != 'soa': raise MasterFileError("No SOA found") self.__name = name + self.__verbose = old_verbose return name ######################################################################### @@ -454,7 +585,8 @@ class MasterFile: def reset(self): self.__zonefile.seek(0) self.__origin = self.__initial_origin - self.__ttl = '' + MasterFile.__ttl = '' + MasterFile.__lastttl = '' ######################################################################### # main: used for testing; parse a zone file and print out each record From 7276b76e2ff9645457a21db6fff56a3a8ecad9b9 Mon Sep 17 00:00:00 2001 From: tingting shen Date: Wed, 30 Jun 2010 08:43:40 +0000 Subject: [PATCH 64/66] change ChagneLog file git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2341 e5f2f494-b856-4b98-b285-d166d9295462 --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6c2edf18f6..89e14b49a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 65. [func] shentingting Added verbose options to exactly what is happening with loadzone. Added loadzone test suite of different file formats to load. - (tingting-loadzone, svn r2339) + (Trac #197, #199, #244, #161, #198, #174, #175, svn r2340) 64. [func] jerry Added python logging framework. It is for testing and experimenting From e23b961435ee945540fe0f0d1973ecbdee04ba24 Mon Sep 17 00:00:00 2001 From: Likun Zhang Date: Wed, 30 Jun 2010 10:29:35 +0000 Subject: [PATCH 65/66] Make sure generated file 'bind10_config.py' can be found by log_test when running 'make distcheck' git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2343 e5f2f494-b856-4b98-b285-d166d9295462 --- src/lib/python/isc/log/tests/Makefile.am | 2 +- src/lib/python/isc/log/tests/log_test.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/python/isc/log/tests/Makefile.am b/src/lib/python/isc/log/tests/Makefile.am index 82fa1ed65b..f7e869a22c 100644 --- a/src/lib/python/isc/log/tests/Makefile.am +++ b/src/lib/python/isc/log/tests/Makefile.am @@ -7,6 +7,6 @@ PYCOVERAGE = $(PYTHON) 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/isc/log \ + 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 ; \ done diff --git a/src/lib/python/isc/log/tests/log_test.in b/src/lib/python/isc/log/tests/log_test.in index 099bf197a1..60e5e3f699 100644 --- a/src/lib/python/isc/log/tests/log_test.in +++ b/src/lib/python/isc/log/tests/log_test.in @@ -19,7 +19,7 @@ PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} export PYTHON_EXEC TEST_PATH=@abs_top_srcdir@/src/lib/python/isc/log/tests -PYTHONPATH=@abs_top_srcdir@/src/lib/python +PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python export PYTHONPATH cd ${TEST_PATH} From 2c594d9b4d69a3e6616b678ddcd9b322e9a007fb Mon Sep 17 00:00:00 2001 From: Jelte Jansen Date: Wed, 30 Jun 2010 10:37:40 +0000 Subject: [PATCH 66/66] set of fixes in makefiles and test scripts, mostly about reading from src vs build for generated/nongenerated files, and putting temporary test output files under the build tree instead of the source tree, as well as a few environment variables. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2344 e5f2f494-b856-4b98-b285-d166d9295462 --- src/bin/loadzone/Makefile.am | 2 +- src/bin/loadzone/tests/correct/Makefile.am | 5 ++- .../loadzone/tests/correct/correct_test.sh.in | 31 +++++++++------- .../loadzone/tests/correct/get_zonedatas.py | 2 +- src/bin/loadzone/tests/error/Makefile.am | 4 +- src/bin/loadzone/tests/error/error_test.sh.in | 37 +++++++++++-------- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/bin/loadzone/Makefile.am b/src/bin/loadzone/Makefile.am index 7895f65f4a..777ebb25d9 100644 --- a/src/bin/loadzone/Makefile.am +++ b/src/bin/loadzone/Makefile.am @@ -25,7 +25,7 @@ install-data-local: # TODO: permissions handled later EXTRA_DIST += tests/normal/README -EXTRA_DIST += tests/normal/dsset-subzone.example.com. +EXTRA_DIST += tests/normal/dsset-subzone.example.com EXTRA_DIST += tests/normal/example.com EXTRA_DIST += tests/normal/example.com.signed EXTRA_DIST += tests/normal/Kexample.com.+005+04456.key diff --git a/src/bin/loadzone/tests/correct/Makefile.am b/src/bin/loadzone/tests/correct/Makefile.am index fb146275a0..213d089191 100644 --- a/src/bin/loadzone/tests/correct/Makefile.am +++ b/src/bin/loadzone/tests/correct/Makefile.am @@ -12,6 +12,7 @@ EXTRA_DIST += mix2sub2.txt EXTRA_DIST += ttl1.db EXTRA_DIST += ttl2.db EXTRA_DIST += ttlext.db +EXTRA_DIST += example.db # later will have configure option to choose this, like: coverage run --branch PYCOVERAGE = $(PYTHON) @@ -19,6 +20,6 @@ PYCOVERAGE = $(PYTHON) 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_srcdir)/$$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 ; \ done diff --git a/src/bin/loadzone/tests/correct/correct_test.sh.in b/src/bin/loadzone/tests/correct/correct_test.sh.in index ebd6993cca..509d8e5f13 100644 --- a/src/bin/loadzone/tests/correct/correct_test.sh.in +++ b/src/bin/loadzone/tests/correct/correct_test.sh.in @@ -18,32 +18,35 @@ PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} export PYTHON_EXEC -PYTHONPATH=@abs_top_builddir@/src/lib/python +PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python export PYTHONPATH -LOADZONE_PATH=@abs_top_srcdir@/src/bin/loadzone +LOADZONE_PATH=@abs_top_builddir@/src/bin/loadzone +TEST_FILE_PATH=@abs_top_srcdir@/src/bin/loadzone/tests/correct +TEST_OUTPUT_PATH=@abs_top_builddir@/src/bin/loadzone//tests/correct + status=0 echo "Loadzone include. from include.db file" -cd ${LOADZONE_PATH}/tests/correct -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 include.db >> /dev/null +cd ${TEST_FILE_PATH} +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 include.db >> /dev/null echo "loadzone ttl1. from ttl1.db file" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttl1.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 ttl1.db >> /dev/null echo "loadzone ttl2. from ttl2.db file" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttl2.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 ttl2.db >> /dev/null echo "loadzone mix1. from mix1.db" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 mix1.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 mix1.db >> /dev/null echo "loadzone mix2. from mix2.db" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 mix2.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 mix2.db >> /dev/null echo "loadzone ttlext. from ttlext.db" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ttlext.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 ttlext.db >> /dev/null echo "loadzone example.com. from example.db" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 example.db >> /dev/null +${LOADZONE_PATH}/b10-loadzone -d ${TEST_OUTPUT_PATH}/zone.sqlite3 example.db >> /dev/null echo "I:test master file \$INCLUDE semantics" echo "I:test master file BIND 8 compatibility TTL and \$TTL semantics" @@ -53,13 +56,13 @@ echo "I:test master file RFC1035 TTL and mixed \$INCLUDE with \$TTL semantics" echo "I:test master file BIND9 extenstion of TTL" echo "I:test master file RFC1035 missing CLASS, TTL, NAME semantics" -${PYTHON_EXEC} get_zonedatas.py > test.out +${PYTHON_EXEC} ${TEST_FILE_PATH}/get_zonedatas.py ${TEST_OUTPUT_PATH}/zone.sqlite3 > ${TEST_OUTPUT_PATH}/test.out echo "Compare test results." -diff test.out known.test.out || status=1 +diff ${TEST_OUTPUT_PATH}/test.out ${TEST_FILE_PATH}/known.test.out || status=1 echo "Clean tmp files." -rm -f zone.sqlite3 -rm -f test.out +rm -f ${TEST_OUTPUT_PATH}/zone.sqlite3 +rm -f ${TEST_OUTPUT_PATH}/test.out echo "I:exit status: $status" echo "------------------------------------------------------------------------------" echo "Ran 7 test files" diff --git a/src/bin/loadzone/tests/correct/get_zonedatas.py b/src/bin/loadzone/tests/correct/get_zonedatas.py index de629f2a10..faa563449c 100644 --- a/src/bin/loadzone/tests/correct/get_zonedatas.py +++ b/src/bin/loadzone/tests/correct/get_zonedatas.py @@ -1,6 +1,6 @@ from isc.datasrc import sqlite3_ds import sys -ZONE_FILE = "zone.sqlite3" +ZONE_FILE = sys.argv[1] zonename_set = ["include.", "ttl1.", "ttl2.", "mix1.", "mix2.", "ttlext.", "example.com."] for zone_name in zonename_set: for rr_data in sqlite3_ds.get_zone_datas(zone_name, ZONE_FILE): diff --git a/src/bin/loadzone/tests/error/Makefile.am b/src/bin/loadzone/tests/error/Makefile.am index 2ce860cd16..427260d1c0 100644 --- a/src/bin/loadzone/tests/error/Makefile.am +++ b/src/bin/loadzone/tests/error/Makefile.am @@ -10,7 +10,7 @@ EXTRA_DIST += include.txt EXTRA_DIST += keyerror1.db EXTRA_DIST += keyerror2.db EXTRA_DIST += keyerror3.db -EXTRA_DIST += nofilenane.db +#EXTRA_DIST += nofilenane.db EXTRA_DIST += originerr1.db EXTRA_DIST += originerr2.db @@ -21,5 +21,5 @@ 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_srcdir)/$$pytest ; \ + $(SHELL) $(abs_builddir)/$$pytest ; \ done diff --git a/src/bin/loadzone/tests/error/error_test.sh.in b/src/bin/loadzone/tests/error/error_test.sh.in index ff1872ca59..d1d6bd1837 100644 --- a/src/bin/loadzone/tests/error/error_test.sh.in +++ b/src/bin/loadzone/tests/error/error_test.sh.in @@ -18,46 +18,53 @@ PYTHON_EXEC=${PYTHON_EXEC:-@PYTHON@} export PYTHON_EXEC -PYTHONPATH=@abs_top_builddir@/src/lib/python +PYTHONPATH=@abs_top_srcdir@/src/lib/python:@abs_top_builddir@/src/lib/python export PYTHONPATH -LOADZONE_PATH=@abs_top_srcdir@/src/bin/loadzone -export LOADZONE_PATH -status=0 +LOADZONE_PATH=@abs_top_builddir@/src/bin/loadzone +TEST_OUTPUT_PATH=@abs_top_builddir@/src/bin/loadzone/tests/error +TEST_FILE_PATH=@abs_top_srcdir@/src/bin/loadzone/tests/error + cd ${LOADZONE_PATH}/tests/error +export LOADZONE_PATH +status=0 + +echo "PYTHON PATH: $PYTHONPATH" + echo "Test no \$ORIGIN error in zone file" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 originerr1.db 1> /dev/null 2> error.out -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 originerr2.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/originerr1.db 1> /dev/null 2> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/originerr2.db 1> /dev/null 2>> error.out echo "Test: key word TTL spell error" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror1.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/keyerror1.db 1> /dev/null 2>> error.out echo "Test: key word ORIGIN spell error" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror2.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/keyerror2.db 1> /dev/null 2>> error.out echo "Test: key INCLUDE spell error" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 keyerror3.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/keyerror3.db 1> /dev/null 2>> error.out echo "Test: include formal error, miss filename" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr1.db 1> /dev/null 2>>error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/formerr1.db 1> /dev/null 2>>error.out echo "Test: include form error, domain is not absolute" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr2.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/formerr2.db 1> /dev/null 2>> error.out echo "Test: TTL form error, no ttl value" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr3.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/formerr3.db 1> /dev/null 2>> error.out echo "Test: TTL form error, ttl value error" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr4.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/formerr4.db 1> /dev/null 2>> error.out echo "Test: rr form error, no type" -${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 formerr5.db 1> /dev/null 2>> error.out +${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 ${TEST_FILE_PATH}/formerr5.db 1> /dev/null 2>> error.out echo "Test: zone file is bogus" +# since bogusfile doesn't exist anyway, we *don't* specify the directory ${LOADZONE_PATH}/b10-loadzone -d zone.sqlite3 bogusfile 1> /dev/null 2>> error.out -diff error.out error.known || status=1 +diff error.out ${TEST_FILE_PATH}/error.known || status=1 echo "Clean tmp file." rm -f error.out