Parcourir la source

[1678] initial test multiinstance auth only

test fails because of 1705
Jelte Jansen il y a 13 ans
Parent
commit
324be1acbd

+ 1 - 0
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"}}}}

+ 36 - 0
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

+ 90 - 0
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 <name> should (not) have changed'
+       Arguments:
+       process name ('process <name>') 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 <portnr>', 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):
     """

+ 7 - 1
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