BIND 10 trac1290, updated. aa35477883e1a5b1740092296d463ecfd277dbbb [1290] add example test with two instances of bind10
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Oct 20 15:57:50 UTC 2011
The branch, trac1290 has been updated
via aa35477883e1a5b1740092296d463ecfd277dbbb (commit)
via 701074ebbf30930b92f8b06d9cc88428aed8db5f (commit)
via e009438536339927f645f9a272c23e43cd0660fc (commit)
from c3bde52d5e1e2748f9d60aa8740fa044260913d5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit aa35477883e1a5b1740092296d463ecfd277dbbb
Author: Jelte Jansen <jelte at isc.org>
Date: Thu Oct 20 17:57:37 2011 +0200
[1290] add example test with two instances of bind10
commit 701074ebbf30930b92f8b06d9cc88428aed8db5f
Author: Jelte Jansen <jelte at isc.org>
Date: Thu Oct 20 17:14:26 2011 +0200
[1290] generalized a few steps so we can use multiple processes
commit e009438536339927f645f9a272c23e43cd0660fc
Author: Jelte Jansen <jelte at isc.org>
Date: Thu Oct 20 16:09:41 2011 +0200
[1290] move some things to terrain.py
-----------------------------------------------------------------------
Summary of changes:
src/lib/python/isc/bind10/sockcreator.py | 3 +-
tests/lettuce/README | 3 +-
tests/lettuce/configurations/example2.org.config | 1 +
tests/lettuce/features/bind10_control.py | 81 ++++++++++++-------
tests/lettuce/features/querying.py | 2 +-
tests/lettuce/features/server_from_sqlite3.feature | 28 +++++--
tests/lettuce/features/steps.py | 38 ++++------
tests/lettuce/features/terrain.py | 52 +++++++++++++
8 files changed, 146 insertions(+), 62 deletions(-)
create mode 100644 tests/lettuce/configurations/example2.org.config
create mode 100644 tests/lettuce/features/terrain.py
-----------------------------------------------------------------------
diff --git a/src/lib/python/isc/bind10/sockcreator.py b/src/lib/python/isc/bind10/sockcreator.py
index 8e5b019..33ccd41 100644
--- a/src/lib/python/isc/bind10/sockcreator.py
+++ b/src/lib/python/isc/bind10/sockcreator.py
@@ -17,6 +17,7 @@ import socket
import struct
import os
import subprocess
+import copy
from isc.log_messages.bind10_messages import *
from libutil_io_python import recv_fd
@@ -207,7 +208,7 @@ class Creator(Parser):
# stdin as well as stdout, so we dup it before passing it there.
remote2 = socket.fromfd(remote.fileno(), socket.AF_UNIX,
socket.SOCK_STREAM)
- env = os.environ
+ env = copy.deepcopy(os.environ)
env['PATH'] = path
self.__process = subprocess.Popen(['b10-sockcreator'], env=env,
stdin=remote.fileno(),
diff --git a/tests/lettuce/README b/tests/lettuce/README
index 1db6180..c5dfe52 100644
--- a/tests/lettuce/README
+++ b/tests/lettuce/README
@@ -25,7 +25,8 @@ This port must be free. (TODO: can we make this run-time discovered?).
Port 47805 is used for cmdctl, and must also be available.
The bind10 main script, bindctl script, and dig must all be in the default
-search path of your environment.
+search path of your environment, and BIND 10 must not be running if you use
+the installed version when you run the tests.
To run the tests, just run 'lettuce' in this directory.
diff --git a/tests/lettuce/configurations/example2.org.config b/tests/lettuce/configurations/example2.org.config
new file mode 100644
index 0000000..369ca14
--- /dev/null
+++ b/tests/lettuce/configurations/example2.org.config
@@ -0,0 +1 @@
+{"version": 2, "Logging": {"loggers": [{"severity": "DEBUG", "name": "auth", "debuglevel": 99}]}, "Auth": {"database_file": "data/example.org.sqlite3", "listen_on": [{"port": 47807, "address": "127.0.0.1"}]}}
diff --git a/tests/lettuce/features/bind10_control.py b/tests/lettuce/features/bind10_control.py
index 1896c44..675d572 100644
--- a/tests/lettuce/features/bind10_control.py
+++ b/tests/lettuce/features/bind10_control.py
@@ -1,70 +1,91 @@
from lettuce import *
import subprocess
- at world.absorb
-def shutdown_server():
- if world.bind10 is not None:
- world.bind10.terminate()
- world.bind10.wait()
- world.bind10 = None
-
def check_lines(output, lines):
for line in lines:
if output.find(line) != -1:
return line
@world.absorb
-def wait_for_output_lines(lines, examine_past = True):
- assert world.bind10 is not None
+def wait_for_output_lines_stdout(process_name, lines, examine_past = True):
+ assert process_name in world.processes
+ if examine_past:
+ for output in world.processes_stdout[process_name]:
+ for line in lines:
+ if output.find(line) != -1:
+ return line
+ found = False
+ while not found:
+ output = world.processes[process_name].stdout.readline()
+ # store any line, for examine_skipped
+ world.processes_stdout[process_name].append(output)
+ for line in lines:
+ if output.find(line) != -1:
+ return line
+
+ at world.absorb
+def wait_for_output_lines_stderr(process_name, lines, examine_past = True):
+ assert process_name in world.processes,\
+ "No process named '" + process_name + "' known"
if examine_past:
- for output in world.bind10_output:
+ for output in world.processes_stderr[process_name]:
for line in lines:
if output.find(line) != -1:
return line
found = False
while not found:
- output = world.bind10.stderr.readline()
+ output = world.processes[process_name].stderr.readline()
# store any line, for examine_skipped
- world.bind10_output.append(output)
+ world.processes_stderr[process_name].append(output)
for line in lines:
if output.find(line) != -1:
return line
- at step('start bind10(?: with configuration ([\w.]+))?')
-def start_bind10(step, config_file):
+ at step('start bind10(?: with configuration (\S+))?' +\
+ '(?: with cmdctl port (\d+))?(?: as (\S+))?')
+def start_bind10(step, config_file, cmdctl_port, process_name):
args = [ 'bind10', '-v' ]
if config_file is not None:
args.append('-p')
args.append("configurations/")
args.append('-c')
args.append(config_file)
+ if cmdctl_port is None:
args.append('--cmdctl-port=47805')
+ else:
+ args.append('--cmdctl-port=' + cmdctl_port)
+ if process_name is None:
+ process_name = "bind10"
+ else:
+ args.append('-m')
+ args.append(process_name + '_msgq.socket')
- world.bind10 = subprocess.Popen(args, 1, None, subprocess.PIPE,
- subprocess.PIPE, subprocess.PIPE)
+ assert process_name not in world.processes,\
+ "There already seems to be a process named " + process_name
+ world.processes[process_name] = subprocess.Popen(args, 1, None,
+ subprocess.PIPE,
+ subprocess.PIPE,
+ subprocess.PIPE)
+ world.processes_stdout[process_name] = []
+ world.processes_stderr[process_name] = []
# check output to know when startup has been completed
# TODO what to do on failure?
- message = world.wait_for_output_lines(["BIND10_STARTUP_COMPLETE",
- "BIND10_STARTUP_ERROR"])
- assert message == "BIND10_STARTUP_COMPLETE"
+ message = world.wait_for_output_lines_stderr(process_name,
+ ["BIND10_STARTUP_COMPLETE",
+ "BIND10_STARTUP_ERROR"])
+ assert message == "BIND10_STARTUP_COMPLETE", "Got: " + message
- at step('wait for bind10 auth to start')
-def wait_for_auth(step):
- world.wait_for_output_lines(['AUTH_SERVER_STARTED'])
+ at step('wait for bind10 auth (?:of (\w+) )?to start')
+def wait_for_auth(step, process_name):
+ if process_name is None:
+ process_name = "bind10"
+ world.wait_for_output_lines_stderr(process_name, ['AUTH_SERVER_STARTED'])
@step('have bind10 running(?: with configuration ([\w.]+))?')
def have_bind10_running(step, config_file):
step.given('start bind10 with configuration ' + config_file)
step.given('wait for bind10 auth to start')
- at step('wait for log message (\w+)')
-def wait_for_message(step, message):
- world.wait_for_output_lines([message], False)
-
- at step('stop bind10')
-def stop_the_server(step):
- world.shutdown_server()
-
@step('set bind10 configuration (\S+) to (.*)')
def set_config_command(step, name, value):
args = ['bindctl', '-p', '47805']
diff --git a/tests/lettuce/features/querying.py b/tests/lettuce/features/querying.py
index 96a7e3e..0b4a50d 100644
--- a/tests/lettuce/features/querying.py
+++ b/tests/lettuce/features/querying.py
@@ -40,7 +40,7 @@ class QueryResult(object):
"([0-9]+), AUTHORITY: ([0-9]+), ADDITIONAL: ([0-9]+)")
def __init__(self, name, qtype, qclass, address, port):
- args = [ 'dig', '@' + address, '-p', str(port) ]
+ args = [ 'dig', '+tries=1', '@' + address, '-p', str(port) ]
if qtype is not None:
args.append('-t')
args.append(str(qtype))
diff --git a/tests/lettuce/features/server_from_sqlite3.feature b/tests/lettuce/features/server_from_sqlite3.feature
index 3eb2c4a..c8f84f4 100644
--- a/tests/lettuce/features/server_from_sqlite3.feature
+++ b/tests/lettuce/features/server_from_sqlite3.feature
@@ -7,7 +7,7 @@ Feature: SQLite3 backend
Given I have no database
When I start bind10 with configuration no_db_file.config
Then wait for bind10 auth to start
- Then stop bind10
+ Then stop process bind10
I should see a database file
Scenario: example.org queries
@@ -63,13 +63,29 @@ Feature: SQLite3 backend
When I start bind10 with configuration example.org.config
Then wait for bind10 auth to start
- Wait for log message CMDCTL_STARTED
+ Wait for bind10 stderr message CMDCTL_STARTED
A query for www.example.org should have rcode NOERROR
- Wait for log message AUTH_SEND_NORMAL_RESPONSE
+ Wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
Then set bind10 configuration Auth/database_file to data/empty_db.sqlite3
- And wait for log message DATASRC_SQLITE_OPEN
+ And wait for bind10 stderr message DATASRC_SQLITE_OPEN
A query for www.example.org should have rcode REFUSED
- Wait for log message AUTH_SEND_NORMAL_RESPONSE
+ Wait for bind10 stderr message AUTH_SEND_NORMAL_RESPONSE
Then set bind10 configuration Auth/database_file to data/example.org.sqlite3
- And wait for log message DATASRC_SQLITE_OPEN
+ And wait for bind10 stderr message DATASRC_SQLITE_OPEN
A query for www.example.org should have rcode NOERROR
+
+ Scenario: two bind10 instances
+ # This is more a test of the test system, start 2 bind10's
+ When I start bind10 with configuration example.org.config as bind10_one
+ And I start bind10 with configuration example2.org.config with cmdctl port 47804 as bind10_two
+
+ Then wait for bind10 auth of bind10_one to start
+ Then wait for bind10 auth of bind10_two to start
+ A query for www.example.org to 127.0.0.1:47806 should have rcode NOERROR
+ A query for www.example.org to 127.0.0.1:47807 should have rcode NOERROR
+
+ Then set bind10 configuration Auth/database_file to data/empty_db.sqlite3
+ And wait for bind10_one stderr message DATASRC_SQLITE_OPEN
+
+ A query for www.example.org to 127.0.0.1:47806 should have rcode REFUSED
+ A query for www.example.org to 127.0.0.1:47807 should have rcode NOERROR
diff --git a/tests/lettuce/features/steps.py b/tests/lettuce/features/steps.py
index ab06c4e..d11a601 100644
--- a/tests/lettuce/features/steps.py
+++ b/tests/lettuce/features/steps.py
@@ -1,30 +1,22 @@
-from lettuce import *
-import subprocess
-import os.path
-import shutil
+#
+# This file contains a number of common steps that are general and may be used
+# By a lot of feature files.
+#
-copylist = [
-["configurations/example.org.config.orig", "configurations/example.org.config"]
-]
+from lettuce import *
+import os
- at before.each_scenario
-def initialize(feature):
- # just make sure our cleanup won't fail if we never did
- # run the bind10 instance
- world.bind10 = None
- world.bind10_output = []
- world.last_query_result = None
+ at step('stop process (\w+)')
+def stop_a_named_process(step, process_name):
+ world.stop_process(process_name)
- # Some tests can modify the settings. If the tests fail half-way, or
- # don't clean up, this can leave configurations or data in a bad state,
- # so we copy them from originals before each scenario
- for item in copylist:
- shutil.copy(item[0], item[1])
+ at step('wait for (\w+) stderr message (\w+)')
+def wait_for_message(step, process_name, message):
+ world.wait_for_output_lines_stderr(process_name, [message], False)
- at after.each_scenario
-def cleanup(feature):
- world.shutdown_server()
- world.bind10_output = []
+ at step('wait for (\w+) stdout message (\w+)')
+def wait_for_message(step, process_name, message):
+ world.wait_for_output_lines_stdout(process_name, [message], False)
@step('Given I have no database')
def given_i_have_no_database(step):
diff --git a/tests/lettuce/features/terrain.py b/tests/lettuce/features/terrain.py
new file mode 100644
index 0000000..5de0838
--- /dev/null
+++ b/tests/lettuce/features/terrain.py
@@ -0,0 +1,52 @@
+#
+# This is the 'terrain' in which the lettuce lives. By convention, this is
+# where global setup and teardown is defined.
+#
+# We declare some attributes of the global 'world' variables here, so the
+# tests can safely assume they are present.
+#
+# We also use it to provide scenario invariants, such as resetting data.
+#
+from lettuce import *
+import subprocess
+import os.path
+import shutil
+
+# This is a list of files that are freshly copied before each scenario
+# The first element is the original, the second is the target that will be
+# used by the tests that need them
+copylist = [
+["configurations/example.org.config.orig", "configurations/example.org.config"]
+]
+
+ at before.each_scenario
+def initialize(feature):
+ # just make sure our cleanup won't fail if we never did
+ # run the bind10 instance
+ world.processes = {}
+ world.processes_stdout = {}
+ world.processes_stderr = {}
+ world.last_query_result = None
+
+ # Some tests can modify the settings. If the tests fail half-way, or
+ # don't clean up, this can leave configurations or data in a bad state,
+ # so we copy them from originals before each scenario
+ for item in copylist:
+ shutil.copy(item[0], item[1])
+
+ at after.each_scenario
+def cleanup(feature):
+ # Stop any running processes we may have had around
+ for name in world.processes:
+ world.processes[name].terminate()
+ world.processes[name].wait()
+ world.processes_stdout[name] = []
+ world.processes_stderr[name] = []
+
+ at world.absorb
+def stop_process(process_name):
+ if process_name in world.processes:
+ p = world.processes[process_name]
+ p.terminate()
+ p.wait()
+ del world.processes[process_name]
More information about the bind10-changes
mailing list