From: Jelte Jansen Date: Thu, 23 Feb 2012 15:24:34 +0000 (+0100) Subject: [1678] initial test multiinstance auth only X-Git-Tag: trac2351_base~226^2~116^2~164^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=324be1acbdb7d432f4204d9cd6ed28e71a4fe7cf;p=thirdparty%2Fkea.git [1678] initial test multiinstance auth only test fails because of 1705 --- diff --git a/tests/lettuce/configurations/multi_instance/multi_auth.config.orig b/tests/lettuce/configurations/multi_instance/multi_auth.config.orig new file mode 100644 index 0000000000..548542cf8c --- /dev/null +++ b/tests/lettuce/configurations/multi_instance/multi_auth.config.orig @@ -0,0 +1 @@ +{"version": 2, "Auth": {"listen_on": [{"port": 47806, "address": "0.0.0.0"}]}, "Boss": {"components": {"b10-auth": {"kind": "needed", "special": "auth"}, "b10-cmdctl": {"kind": "needed", "special": "cmdctl"}}}} diff --git a/tests/lettuce/features/multi_instance.feature b/tests/lettuce/features/multi_instance.feature new file mode 100644 index 0000000000..6ae97187c5 --- /dev/null +++ b/tests/lettuce/features/multi_instance.feature @@ -0,0 +1,36 @@ +Feature: Multiple instances + This feature tests whether multiple instances can be run, and whether + removing them does not affect the running of other instances + + Scenario: Multiple instances + Given I have bind10 running with configuration multi_instance/multi_auth.config + And bind10 module Auth should be running + # this also checks whether the process is running according to Boss + If I remember the pid of process b10-auth + And remember the pid of process b10-auth-2 + + A query for example.com should have rcode REFUSED + + When I remove bind10 configuration Boss/components value b10-auth-2 + + Then the pid of process b10-auth should not have changed + # From here on out it fails because of #1705 + And a query for example.com should have rcode REFUSED + + When I send bind10 the following commands + """ + config add Boss/components b10-auth-2 + config set Boss/components/b10-auth-2/special auth + config set Boss/components/b10-auth-2/process b10-auth + config set Boss/components/b10-auth-2/kind needed + config commit + """ + And wait for new bind10 stderr message AUTH_SERVER_STARTED + And remember the pid of process b10-auth-2 + + Then the pid of process b10-auth should not have changed + A query for example.com should have rcode REFUSED + + When I remove bind10 configuration Boss/components value b10-auth + Then the pid of process b10-auth-2 should not have changed + A query for example.com should have rcode REFUSED diff --git a/tests/lettuce/features/terrain/bind10_control.py b/tests/lettuce/features/terrain/bind10_control.py index 7ccd2b3b03..ea85bbc662 100644 --- a/tests/lettuce/features/terrain/bind10_control.py +++ b/tests/lettuce/features/terrain/bind10_control.py @@ -16,6 +16,7 @@ from lettuce import * import subprocess import re +import json @step('start bind10(?: with configuration (\S+))?' +\ '(?: with cmdctl port (\d+))?' +\ @@ -167,6 +168,81 @@ def check_bindctl_output(step, stderr, notv, string): "' was found in bindctl output:\n" +\ output +def parse_bindctl_output_as_data_structure(): + """Helper function for data-related command tests: evaluates the + last output of bindctl as a data structure that can then be + inspected. + If the bindctl output is not valid (json) data, this call will + fail with an assertion failure. + If it is valid, it is parsed and returned as whatever data + structure it represented. + """ + # strip the 'Exit from bindctl' message. Why is it even there? + output = world.last_bindctl_stdout.replace("Exit from bindctl", "") + try: + return json.loads(output) + except ValueError as ve: + assert False, "Last bindctl output does not appear to be a " +\ + "parseable data structure: " + str(ve) + +@step("remember the pid of process ([\S]+)") +def remember_pid(step, process_name): + """Stores the PID of the process with the given name as returned by + Boss show_processes command. + Fails if the process with the given name does not appear to exist. + Stores the component_name->pid value in the dict world.process_pids. + This should only be used by the related step + 'the pid of process should (not) have changed' + Arguments: + process name ('process ') the name of the component to store + the pid of. + """ + step.given('send bind10 the command Boss show_processes') + running_processes = parse_bindctl_output_as_data_structure() + # show_processes output is a list of lists, where the inner lists + # are of the form [ pid, "name" ] + # Not checking data form; errors will show anyway (if these turn + # out to be too vague, we can change this) + found = False + if world.process_pids is None: + world.process_pids = {} + for process in running_processes: + if process[1] == process_name: + world.process_pids[process_name] = process[0] + found = True + assert found, "Process named " + process_name +\ + " not found in output of Boss show_processes"; + +@step('pid of process ([\S]+) should not have changed') +def check_pid(step, process_name): + """Checks the PID of the process with the given name as returned by + Boss show_processes command. + Fails if the process with the given name does not appear to exist. + Fails if the process with the given name exists, but has a different + pid than it had when the step 'remember the pid of process' was + called. + Fails if that step has not been called (since world.process_pids + does not exist). + """ + step.given('send bind10 the command Boss show_processes') + running_processes = parse_bindctl_output_as_data_structure() + # show_processes output is a list of lists, where the inner lists + # are of the form [ pid, "name" ] + # Not checking data form; errors will show anyway (if these turn + # out to be too vague, we can change this) + found = False + assert world.process_pids is not None, "No process pids stored" + assert process_name in world.process_pids, "Process named " +\ + process_name +\ + " was not stored" + for process in running_processes: + if process[1] == process_name: + assert world.process_pids[process_name] == process[0] + found = True + assert found, "Process named " + process_name +\ + " not found in output of Boss show_processes"; + + @step('set bind10 configuration (\S+) to (.*)(?: with cmdctl port (\d+))?') def config_set_command(step, name, value, cmdctl_port): """ @@ -183,6 +259,20 @@ def config_set_command(step, name, value, cmdctl_port): "quit"] run_bindctl(commands, cmdctl_port) +@step('send bind10 the following commands(?: with cmdctl port (\d+))?') +def send_multiple_commands(step, cmdctl_port): + """ + Run bindctl, and send it the given multiline set of commands. + A quit command is always appended. + cmdctl_port ('with cmdctl port ', optional): cmdctl port to send + the command to. Defaults to 47805. + Fails if cmdctl does not exit with status code 0. + """ + commands = step.multiline.split("\n") + # Always add quit + commands.append("quit") + run_bindctl(commands, cmdctl_port) + @step('remove bind10 configuration (\S+)(?: value (\S+))?(?: with cmdctl port (\d+))?') def config_remove_command(step, name, value, cmdctl_port): """ diff --git a/tests/lettuce/features/terrain/terrain.py b/tests/lettuce/features/terrain/terrain.py index 90531a1bcb..2bfddd6711 100644 --- a/tests/lettuce/features/terrain/terrain.py +++ b/tests/lettuce/features/terrain/terrain.py @@ -45,7 +45,9 @@ copylist = [ ["configurations/example.org.config.orig", "configurations/example.org.config"], ["configurations/resolver/resolver_basic.config.orig", - "configurations/resolver/resolver_basic.config"] + "configurations/resolver/resolver_basic.config"], + ["configurations/multi_instance/multi_auth.config.orig", + "configurations/multi_instance/multi_auth.config"] ] # This is a list of files that, if present, will be removed before a scenario @@ -343,6 +345,10 @@ def initialize(scenario): # Convenience variable to access the last query result from querying.py world.last_query_result = None + # For slightly better errors, initialize a process_pids for the relevant + # steps + world.process_pids = 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