Browse Source

Merge branch 'master' into trac1384

Jelte Jansen 13 years ago
parent
commit
11a4fe2def

+ 3 - 0
configure.ac

@@ -107,6 +107,9 @@ case "$host" in
 	SET_ENV_LIBRARY_PATH=yes
 	SET_ENV_LIBRARY_PATH=yes
 	ENV_LIBRARY_PATH=DYLD_LIBRARY_PATH
 	ENV_LIBRARY_PATH=DYLD_LIBRARY_PATH
 	;;
 	;;
+*-freebsd*)
+	SET_ENV_LIBRARY_PATH=yes
+	;;
 esac
 esac
 AM_CONDITIONAL(SET_ENV_LIBRARY_PATH, test $SET_ENV_LIBRARY_PATH = yes)
 AM_CONDITIONAL(SET_ENV_LIBRARY_PATH, test $SET_ENV_LIBRARY_PATH = yes)
 AC_SUBST(SET_ENV_LIBRARY_PATH)
 AC_SUBST(SET_ENV_LIBRARY_PATH)

+ 54 - 23
src/lib/datasrc/tests/Makefile.am

@@ -18,23 +18,43 @@ CLEANFILES = *.gcno *.gcda
 
 
 TESTS =
 TESTS =
 if HAVE_GTEST
 if HAVE_GTEST
-TESTS += run_unittests
-run_unittests_SOURCES = run_unittests.cc
-run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
-run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
+TESTS += run_unittests run_unittests_sqlite3 run_unittests_memory
+
+#
+# For each specific datasource, there is a separate binary that includes
+# the code itself (we can't unittest through the public API). These need
+# to be separate because the included code, by design, contains conflicting
+# symbols.
+# We also have a 'general' run_unittests with non-datasource-specific tests
+#
+
+# First define the parts shared by all
+common_sources = run_unittests.cc
+common_sources += $(top_srcdir)/src/lib/dns/tests/unittest_util.h
+common_sources += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
+
+common_ldadd  = $(GTEST_LDADD)
+common_ldadd += $(SQLITE_LIBS)
+common_ldadd += $(top_builddir)/src/lib/datasrc/libdatasrc.la
+common_ldadd += $(top_builddir)/src/lib/dns/libdns++.la
+common_ldadd += $(top_builddir)/src/lib/util/libutil.la
+common_ldadd += $(top_builddir)/src/lib/log/liblog.la
+common_ldadd += $(top_builddir)/src/lib/exceptions/libexceptions.la
+common_ldadd += $(top_builddir)/src/lib/cc/libcc.la
+common_ldadd += $(top_builddir)/src/lib/testutils/libtestutils.la
+common_ldadd += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+
+
+# The general tests
+run_unittests_SOURCES = $(common_sources)
 run_unittests_SOURCES += datasrc_unittest.cc
 run_unittests_SOURCES += datasrc_unittest.cc
-run_unittests_SOURCES += sqlite3_unittest.cc
 run_unittests_SOURCES += static_unittest.cc
 run_unittests_SOURCES += static_unittest.cc
 run_unittests_SOURCES += query_unittest.cc
 run_unittests_SOURCES += query_unittest.cc
 run_unittests_SOURCES += cache_unittest.cc
 run_unittests_SOURCES += cache_unittest.cc
 run_unittests_SOURCES += test_datasrc.h test_datasrc.cc
 run_unittests_SOURCES += test_datasrc.h test_datasrc.cc
 run_unittests_SOURCES += rbtree_unittest.cc
 run_unittests_SOURCES += rbtree_unittest.cc
-#run_unittests_SOURCES += zonetable_unittest.cc
-#run_unittests_SOURCES += memory_datasrc_unittest.cc
 run_unittests_SOURCES += logger_unittest.cc
 run_unittests_SOURCES += logger_unittest.cc
-run_unittests_SOURCES += database_unittest.cc
 run_unittests_SOURCES += client_unittest.cc
 run_unittests_SOURCES += client_unittest.cc
-run_unittests_SOURCES += sqlite3_accessor_unittest.cc
 if !USE_STATIC_LINK
 if !USE_STATIC_LINK
 # This test uses dynamically loadable module.  It will cause various
 # This test uses dynamically loadable module.  It will cause various
 # troubles with static link such as "missing" symbols in the static object
 # troubles with static link such as "missing" symbols in the static object
@@ -42,24 +62,35 @@ if !USE_STATIC_LINK
 # in this case.
 # in this case.
 run_unittests_SOURCES += factory_unittest.cc
 run_unittests_SOURCES += factory_unittest.cc
 endif
 endif
-# for the dlopened types we have tests for, we also need to include the
-# sources
-run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
-#run_unittests_SOURCES += $(top_srcdir)/src/lib/datasrc/memory_datasrc.cc
 
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
 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/libdatasrc.la
-run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
-run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
-run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
-run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
-run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD = $(common_ldadd)
+
+
+# SQlite3 datasource tests
+run_unittests_sqlite3_SOURCES = $(common_sources)
+run_unittests_sqlite3_SOURCES += database_unittest.cc
+run_unittests_sqlite3_SOURCES += sqlite3_unittest.cc
+run_unittests_sqlite3_SOURCES += sqlite3_accessor_unittest.cc
+run_unittests_sqlite3_SOURCES += $(top_srcdir)/src/lib/datasrc/sqlite3_accessor.cc
+
+run_unittests_sqlite3_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_sqlite3_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
+
+run_unittests_sqlite3_LDADD = $(common_ldadd)
+
+# In-memory datasource tests
+run_unittests_memory_SOURCES = $(common_sources)
+run_unittests_memory_SOURCES += memory_datasrc_unittest.cc
+run_unittests_memory_SOURCES += $(top_srcdir)/src/lib/datasrc/memory_datasrc.cc
+
+run_unittests_memory_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_memory_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
+
+run_unittests_memory_LDADD = $(common_ldadd)
+
 endif
 endif
 
 
 noinst_PROGRAMS = $(TESTS)
 noinst_PROGRAMS = $(TESTS)

+ 22 - 0
tests/lettuce/configurations/xfrin/retransfer_master.conf

@@ -0,0 +1,22 @@
+{
+    "version": 2,
+    "Logging": {
+        "loggers": [ {
+            "debuglevel": 99,
+            "severity": "DEBUG",
+            "name": "auth"
+        } ]
+    },
+    "Auth": {
+        "database_file": "data/example.org.sqlite3",
+        "listen_on": [ {
+            "port": 47807,
+            "address": "127.0.0.1"
+        } ]
+    },
+    "Xfrout": {
+        "zone_config": [ {
+            "origin": "example.org"
+        } ]
+    }
+}

+ 17 - 0
tests/lettuce/configurations/xfrin/retransfer_slave.conf

@@ -0,0 +1,17 @@
+{
+    "version": 2,
+    "Logging": {
+        "loggers": [ {
+            "debuglevel": 99,
+            "severity": "DEBUG",
+            "name": "auth"
+        } ]
+    },
+    "Auth": {
+        "database_file": "data/test_nonexistent_db.sqlite3",
+        "listen_on": [ {
+            "port": 47806,
+            "address": "127.0.0.1"
+        } ]
+    }
+}

+ 43 - 10
tests/lettuce/features/terrain/bind10_control.py

@@ -18,8 +18,10 @@ import subprocess
 import re
 import re
 
 
 @step('start bind10(?: with configuration (\S+))?' +\
 @step('start bind10(?: with configuration (\S+))?' +\
-      '(?: with cmdctl port (\d+))?(?: as (\S+))?')
-def start_bind10(step, config_file, cmdctl_port, process_name):
+      '(?: with cmdctl port (\d+))?' +\
+      '(?: with msgq socket file (\S+))?' +\
+      '(?: as (\S+))?')
+def start_bind10(step, config_file, cmdctl_port, msgq_sockfile, process_name):
     """
     """
     Start BIND 10 with the given optional config file, cmdctl port, and
     Start BIND 10 with the given optional config file, cmdctl port, and
     store the running process in world with the given process name.
     store the running process in world with the given process name.
@@ -29,6 +31,8 @@ def start_bind10(step, config_file, cmdctl_port, process_name):
                 directory.
                 directory.
     cmdctl_port ('with cmdctl port <portnr>', optional): The port on which
     cmdctl_port ('with cmdctl port <portnr>', optional): The port on which
                 b10-cmdctl listens for bindctl commands. Defaults to 47805.
                 b10-cmdctl listens for bindctl commands. Defaults to 47805.
+    msgq_sockfile ('with msgq socket file', optional): The msgq socket file
+                that will be used for internal communication
     process_name ('as <name>', optional). This is the name that can be used
     process_name ('as <name>', optional). This is the name that can be used
                  in the following steps of the scenario to refer to this
                  in the following steps of the scenario to refer to this
                  BIND 10 instance. Defaults to 'bind10'.
                  BIND 10 instance. Defaults to 'bind10'.
@@ -57,10 +61,10 @@ def start_bind10(step, config_file, cmdctl_port, process_name):
     world.processes.add_process(step, process_name, args)
     world.processes.add_process(step, process_name, args)
 
 
     # check output to know when startup has been completed
     # check output to know when startup has been completed
-    message = world.processes.wait_for_stderr_str(process_name,
-                                                  ["BIND10_STARTUP_COMPLETE",
-                                                   "BIND10_STARTUP_ERROR"])
-    assert message == "BIND10_STARTUP_COMPLETE", "Got: " + str(message)
+    (message, line) = world.processes.wait_for_stderr_str(process_name,
+                                                     ["BIND10_STARTUP_COMPLETE",
+                                                      "BIND10_STARTUP_ERROR"])
+    assert message == "BIND10_STARTUP_COMPLETE", "Got: " + str(line)
 
 
 @step('wait for bind10 auth (?:of (\w+) )?to start')
 @step('wait for bind10 auth (?:of (\w+) )?to start')
 def wait_for_auth(step, process_name):
 def wait_for_auth(step, process_name):
@@ -75,15 +79,24 @@ def wait_for_auth(step, process_name):
     world.processes.wait_for_stderr_str(process_name, ['AUTH_SERVER_STARTED'],
     world.processes.wait_for_stderr_str(process_name, ['AUTH_SERVER_STARTED'],
                                         False)
                                         False)
 
 
-@step('have bind10 running(?: with configuration ([\w.]+))?')
-def have_bind10_running(step, config_file):
+@step('have bind10 running(?: with configuration ([\S]+))?' +\
+      '(?: with cmdctl port (\d+))?' +\
+      '(?: as ([\S]+))?')
+def have_bind10_running(step, config_file, cmdctl_port, process_name):
     """
     """
     Compound convenience step for running bind10, which consists of
     Compound convenience step for running bind10, which consists of
     start_bind10 and wait_for_auth.
     start_bind10 and wait_for_auth.
     Currently only supports the 'with configuration' option.
     Currently only supports the 'with configuration' option.
     """
     """
-    step.given('start bind10 with configuration ' + config_file)
-    step.given('wait for bind10 auth to start')
+    start_step = 'start bind10 with configuration ' + config_file
+    wait_step = 'wait for bind10 auth to start'
+    if cmdctl_port is not None:
+        start_step += ' with cmdctl port ' + str(cmdctl_port)
+    if process_name is not None:
+        start_step += ' as ' + process_name
+        wait_step = 'wait for bind10 auth of ' + process_name + ' to start'
+    step.given(start_step)
+    step.given(wait_step)
 
 
 @step('set bind10 configuration (\S+) to (.*)(?: with cmdctl port (\d+))?')
 @step('set bind10 configuration (\S+) to (.*)(?: with cmdctl port (\d+))?')
 def set_config_command(step, name, value, cmdctl_port):
 def set_config_command(step, name, value, cmdctl_port):
@@ -106,3 +119,23 @@ def set_config_command(step, name, value, cmdctl_port):
     bindctl.stdin.write("quit\n")
     bindctl.stdin.write("quit\n")
     result = bindctl.wait()
     result = bindctl.wait()
     assert result == 0, "bindctl exit code: " + str(result)
     assert result == 0, "bindctl exit code: " + str(result)
+
+@step('send bind10 the command (.+)(?: with cmdctl port (\d+))?')
+def send_command(step, command, cmdctl_port):
+    """
+    Run bindctl, send the given command, and exit bindctl.
+    Parameters:
+    command ('the command <command>'): The command to send.
+    cmdctl_port ('with cmdctl port <portnr>', optional): cmdctl port to send
+                the command to. Defaults to 47805.
+    Fails if cmdctl does not exit with status code 0.
+    """
+    if cmdctl_port is None:
+        cmdctl_port = '47805'
+    args = ['bindctl', '-p', cmdctl_port]
+    bindctl = subprocess.Popen(args, 1, None, subprocess.PIPE,
+                               subprocess.PIPE, None)
+    bindctl.stdin.write(command + "\n")
+    bindctl.stdin.write("quit\n")
+    result = bindctl.wait()
+    assert result == 0, "bindctl exit code: " + str(result)

+ 19 - 7
tests/lettuce/features/terrain/steps.py

@@ -30,8 +30,8 @@ def stop_a_named_process(step, process_name):
     """
     """
     world.processes.stop_process(process_name)
     world.processes.stop_process(process_name)
 
 
-@step('wait for (new )?(\w+) stderr message (\w+)')
-def wait_for_message(step, new, process_name, message):
+@step('wait for (new )?(\w+) stderr message (\w+)(?: not (\w+))?')
+def wait_for_message(step, new, process_name, message, not_message):
     """
     """
     Block until the given message is printed to the given process's stderr
     Block until the given message is printed to the given process's stderr
     output.
     output.
@@ -40,12 +40,18 @@ def wait_for_message(step, new, process_name, message):
                              this step was used for this process.
                              this step was used for this process.
     process_name ('<name> stderr'): Name of the process to check the output of.
     process_name ('<name> stderr'): Name of the process to check the output of.
     message ('message <message>'): Output (part) to wait for.
     message ('message <message>'): Output (part) to wait for.
+    not_message ('not <message>'): Output (part) to wait for, and fail
     Fails if the message is not found after 10 seconds.
     Fails if the message is not found after 10 seconds.
     """
     """
-    world.processes.wait_for_stderr_str(process_name, [message], new)
+    strings = [message]
+    if not_message is not None:
+        strings.append(not_message)
+    (found, line) = world.processes.wait_for_stderr_str(process_name, strings, new)
+    if not_message is not None:
+        assert found != not_message, line
 
 
-@step('wait for (new )?(\w+) stdout message (\w+)')
-def wait_for_message(step, process_name, message):
+@step('wait for (new )?(\w+) stdout message (\w+)(?: not (\w+))?')
+def wait_for_message(step, process_name, message, not_message):
     """
     """
     Block until the given message is printed to the given process's stdout
     Block until the given message is printed to the given process's stdout
     output.
     output.
@@ -53,10 +59,16 @@ def wait_for_message(step, process_name, message):
     new: (' new', optional): Only check the output printed since last time
     new: (' new', optional): Only check the output printed since last time
                              this step was used for this process.
                              this step was used for this process.
     process_name ('<name> stderr'): Name of the process to check the output of.
     process_name ('<name> stderr'): Name of the process to check the output of.
-    message ('message <message>'): Output (part) to wait for.
+    message ('message <message>'): Output (part) to wait for, and succeed.
+    not_message ('not <message>'): Output (part) to wait for, and fail
     Fails if the message is not found after 10 seconds.
     Fails if the message is not found after 10 seconds.
     """
     """
-    world.processes.wait_for_stdout_str(process_name, [message], new)
+    strings = [message]
+    if not_message is not None:
+        strings.append(not_message)
+    (found, line) = world.processes.wait_for_stdout_str(process_name, strings, new)
+    if not_message is not None:
+        assert found != not_message, line
 
 
 @step('the file (\S+) should (not )?exist')
 @step('the file (\S+) should (not )?exist')
 def check_existence(step, file_name, should_not_exist):
 def check_existence(step, file_name, should_not_exist):

+ 9 - 6
tests/lettuce/features/terrain/terrain.py

@@ -173,7 +173,8 @@ class RunningProcess:
         strings: Array of strings to look for.
         strings: Array of strings to look for.
         only_new: If true, only check output since last time this method was
         only_new: If true, only check output since last time this method was
                   called. If false, first check earlier output.
                   called. If false, first check earlier output.
-        Returns the matched string.
+        Returns a tuple containing the matched string, and the complete line
+        it was found in.
         Fails if none of the strings was read after 10 seconds
         Fails if none of the strings was read after 10 seconds
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         """
         """
@@ -183,7 +184,7 @@ class RunningProcess:
                 for string in strings:
                 for string in strings:
                     if line.find(string) != -1:
                     if line.find(string) != -1:
                         full_file.close()
                         full_file.close()
-                        return string
+                        return (string, line)
         wait_count = 0
         wait_count = 0
         while wait_count < OUTPUT_WAIT_MAX_INTERVALS:
         while wait_count < OUTPUT_WAIT_MAX_INTERVALS:
             where = running_file.tell()
             where = running_file.tell()
@@ -191,7 +192,7 @@ class RunningProcess:
             if line:
             if line:
                 for string in strings:
                 for string in strings:
                     if line.find(string) != -1:
                     if line.find(string) != -1:
-                        return string
+                        return (string, line)
             else:
             else:
                 wait_count += 1
                 wait_count += 1
                 time.sleep(OUTPUT_WAIT_INTERVAL)
                 time.sleep(OUTPUT_WAIT_INTERVAL)
@@ -205,7 +206,8 @@ class RunningProcess:
         strings: Array of strings to look for.
         strings: Array of strings to look for.
         only_new: If true, only check output since last time this method was
         only_new: If true, only check output since last time this method was
                   called. If false, first check earlier output.
                   called. If false, first check earlier output.
-        Returns the matched string.
+        Returns a tuple containing the matched string, and the complete line
+        it was found in.
         Fails if none of the strings was read after 10 seconds
         Fails if none of the strings was read after 10 seconds
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         """
         """
@@ -219,7 +221,8 @@ class RunningProcess:
         strings: Array of strings to look for.
         strings: Array of strings to look for.
         only_new: If true, only check output since last time this method was
         only_new: If true, only check output since last time this method was
                   called. If false, first check earlier output.
                   called. If false, first check earlier output.
-        Returns the matched string.
+        Returns a tuple containing the matched string, and the complete line
+        it was found in.
         Fails if none of the strings was read after 10 seconds
         Fails if none of the strings was read after 10 seconds
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         (OUTPUT_WAIT_INTERVAL * OUTPUT_WAIT_MAX_INTERVALS).
         """
         """
@@ -249,7 +252,7 @@ class RunningProcesses:
         Fails if a process with the given name is already running.
         Fails if a process with the given name is already running.
         """
         """
         assert process_name not in self.processes,\
         assert process_name not in self.processes,\
-            "Process " + name + " already running"
+            "Process " + process_name + " already running"
         self.processes[process_name] = RunningProcess(step, process_name, args)
         self.processes[process_name] = RunningProcess(step, process_name, args)
 
 
     def get_process(self, process_name):
     def get_process(self, process_name):

+ 10 - 0
tests/lettuce/features/xfrin_bind10.feature

@@ -0,0 +1,10 @@
+Feature: Xfrin 
+    Tests for Xfrin, specific for BIND 10 behaviour.
+    
+    Scenario: Retransfer command
+    Given I have bind10 running with configuration xfrin/retransfer_master.conf with cmdctl port 47804 as master
+    And I have bind10 running with configuration xfrin/retransfer_slave.conf
+    A query for www.example.org should have rcode REFUSED
+    When I send bind10 the command Xfrin retransfer example.org IN 127.0.0.1 47807
+    Then wait for new bind10 stderr message XFRIN_XFR_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
+    A query for www.example.org should have rcode NOERROR