]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Move test algorithm configuration to isctest
authorTom Krizek <tkrizek@isc.org>
Thu, 4 Jan 2024 16:27:32 +0000 (17:27 +0100)
committerNicki Křížek <nicki@isc.org>
Mon, 5 Aug 2024 15:54:09 +0000 (17:54 +0200)
Instead of invoking get_algorithms.py script repeatedly (which may yield
different results), move the algorithm configuration to an isctest
module. This ensures the variables are consistent across the entire test
run.

(cherry picked from commit 8302db407c836109c0d313ae82060c42aeef0230)

bin/tests/system/conf.sh
bin/tests/system/conftest.py
bin/tests/system/isctest/vars/__init__.py
bin/tests/system/isctest/vars/algorithms.py [moved from bin/tests/system/get_algorithms.py with 69% similarity, mode: 0644]
bin/tests/system/isctest/vars/all.py
bin/tests/system/mkeys/setup.sh
bin/tests/system/mkeys/tests.sh
bin/tests/system/mkeys/tests_sh_mkeys.py
bin/tests/system/pytest.ini

index e3e9a08fb938d84afa69ede5fbf8b86c8bb1d2f3..320cf647952213c6634fcdd8989224d1a05344b6 100644 (file)
@@ -99,42 +99,6 @@ send() {
   $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
 }
 
-#
-# Useful variables in test scripts
-#
-
-# The following script sets the following algorithm-related variables. These
-# are selected randomly at runtime from a list of supported algorithms. The
-# randomization is deterministic and remains stable for a period of time for a
-# given platform.
-#
-# Default algorithm for testing.
-# DEFAULT_ALGORITHM
-# DEFAULT_ALGORITHM_NUMBER
-# DEFAULT_BITS
-#
-# This is an alternative algorithm for test cases that require more than one
-# algorithm (for example algorithm rollover). Must be different from
-# DEFAULT_ALGORITHM.
-# ALTERNATIVE_ALGORITHM
-# ALTERNATIVE_ALGORITHM_NUMBER
-# ALTERNATIVE_BITS
-#
-# This is an algorithm that is used for tests against the "disable-algorithms"
-# configuration option. Must be different from above algorithms.
-# DISABLED_ALGORITHM
-# DISABLED_ALGORITHM_NUMBER
-# DISABLED_BITS
-#
-# There are multiple algoritms sets to choose from (see get_algorithms.py). To
-# override the default choice, set the ALGORITHM_SET env var (see mkeys system
-# test for example).
-eval "$($PYTHON "$TOP_SRCDIR/bin/tests/system/get_algorithms.py")"
-
-# Default HMAC algorithm.
-# also update _common/rndc.conf and _common/rndc.key when updating DEFAULT_HMAC
-export DEFAULT_HMAC=hmac-sha256
-
 #
 # Useful functions in test scripts
 #
index 5585d1e402ca0d3849cb07396f25059e4fd76baf..c578e4a8fdebfaadd9b2d1bdaaab2ea7860ba825 100644 (file)
@@ -277,6 +277,17 @@ def wait_for_zones_loaded(request, servers):
             watcher.wait_for_line("all zones loaded")
 
 
+@pytest.fixture(scope="module", autouse=True)
+def configure_algorithm_set(request):
+    """Configure the algorithm set to use in tests."""
+    mark = _get_marker(request.node, "algorithm_set")
+    if not mark:
+        name = None
+    else:
+        name = mark.args[0]
+    isctest.vars.set_algorithm_set(name)
+
+
 @pytest.fixture(autouse=True)
 def logger(request, system_test_name):
     """Sets up logging facility specific to a particular test."""
index 7c06a247a2d0316fdb3b47aab11f7a36a8aa18a2..6ed7020344ec1e8fcf21ea60ea874db92a6f96a3 100644 (file)
 import os
 
 from .all import ALL
+from .algorithms import set_algorithm_set
 from .openssl import parse_openssl_config
 from .. import log
 
 
 def init_vars():
     """Initializes the environment variables."""
+    set_algorithm_set(os.getenv("ALGORITHM_SET"))
     parse_openssl_config(ALL["OPENSSL_CONF"])
 
     os.environ.update(ALL)
old mode 100755 (executable)
new mode 100644 (file)
similarity index 69%
rename from bin/tests/system/get_algorithms.py
rename to bin/tests/system/isctest/vars/algorithms.py
index 663b986..4188864
@@ -1,5 +1,3 @@
-#!/usr/bin/python3
-
 # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 #
 # SPDX-License-Identifier: MPL-2.0
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
-# This script is a 'port' broker.  It keeps track of ports given to the
-# individual system subtests, so every test is given a unique port range.
-
-import logging
 import os
 from pathlib import Path
 import platform
 import random
 import subprocess
 import time
-from typing import Dict, List, NamedTuple, Union
-
-# Uncomment to enable DEBUG logging
-# logging.basicConfig(
-#     format="get_algorithms.py %(levelname)s %(message)s", level=logging.DEBUG
-# )
+from typing import Dict, List, NamedTuple, Optional, Union
+
+from .basic import BASIC_VARS
+from .. import log
+
+# Algorithms are selected randomly at runtime from a list of supported
+# algorithms. The randomization is deterministic and remains stable for a
+# period of time for a given platform.
+ALG_VARS = {
+    # There are multiple algoritms sets to choose from (see ALGORITHM_SETS). To
+    # override the default choice, set the ALGORITHM_SET env var prior to
+    # loading this module or call set_algorithm_set().
+    "ALGORITHM_SET": "none",
+    "DEFAULT_ALGORITHM": "",
+    "DEFAULT_ALGORITHM_NUMBER": "",
+    "DEFAULT_BITS": "",
+    # Alternative algorithm for test cases that require more than one algorithm
+    # (for example algorithm rollover). Must be different from
+    # DEFAULT_ALGORITHM.
+    "ALTERNATIVE_ALGORITHM": "",
+    "ALTERNATIVE_ALGORITHM_NUMBER": "",
+    "ALTERNATIVE_BITS": "",
+    # Algorithm that is used for tests against the "disable-algorithms"
+    # configuration option. Must be different from above algorithms.
+    "DISABLED_ALGORITHM": "",
+    "DISABLED_ALGORITHM_NUMBER": "",
+    "DISABLED_BITS": "",
+    # Default HMAC algorithm. Must match the rndc configuration in
+    # bin/tests/system/_common (rndc.conf, rndc.key)
+    "DEFAULT_HMAC": "hmac-sha256",
+}
 
 STABLE_PERIOD = 3600 * 3
 """number of secs during which algorithm selection remains stable"""
@@ -93,57 +112,46 @@ ALGORITHM_SETS = {
     # ),
 }
 
-TESTCRYPTO = Path(__file__).resolve().parent / "testcrypto.sh"
-
-KEYGEN = os.getenv("KEYGEN", "")
-if not KEYGEN:
-    raise RuntimeError("KEYGEN environment variable has to be set")
+# TODO rewrite testcrypto.sh to python
+TESTCRYPTO = Path(__file__).resolve().parent.parent.parent / "testcrypto.sh"
 
-ALGORITHM_SET = os.getenv("ALGORITHM_SET", "stable")
-assert ALGORITHM_SET in ALGORITHM_SETS, f'ALGORITHM_SET "{ALGORITHM_SET}" unknown'
-logging.debug('choosing from ALGORITHM_SET "%s"', ALGORITHM_SET)
 
-
-def is_supported(alg: Algorithm) -> bool:
+def _is_supported(alg: Algorithm) -> bool:
     """Test whether a given algorithm is supported on the current platform."""
     try:
         subprocess.run(
             f"{TESTCRYPTO} -q {alg.name}",
             shell=True,
             check=True,
-            env={
-                "KEYGEN": KEYGEN,
-                "TMPDIR": os.getenv("TMPDIR", "/tmp"),
-            },
+            env=BASIC_VARS,
             stdout=subprocess.DEVNULL,
         )
     except subprocess.CalledProcessError as exc:
-        logging.debug(exc)
-        logging.info("algorithm %s not supported", alg.name)
+        log.debug(exc)
+        log.info("algorithm %s not supported", alg.name)
         return False
     return True
 
 
-def filter_supported(algs: AlgorithmSet) -> AlgorithmSet:
+def _filter_supported(algs: AlgorithmSet) -> AlgorithmSet:
     """Select supported algorithms from the set."""
     filtered = {}
     for alg_type in algs._fields:
         candidates = getattr(algs, alg_type)
         if isinstance(candidates, Algorithm):
             candidates = [candidates]
-        supported = list(filter(is_supported, candidates))
+        supported = list(filter(_is_supported, candidates))
         if len(supported) == 1:
             supported = supported.pop()
         elif not supported:
             raise RuntimeError(
-                f'no {alg_type.upper()} algorithm from "{ALGORITHM_SET}" set '
-                "supported on this platform"
+                f"no {alg_type.upper()} algorithm " "supported on this platform"
             )
         filtered[alg_type] = supported
     return AlgorithmSet(**filtered)
 
 
-def select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> AlgorithmSet:
+def _select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> AlgorithmSet:
     """Select random DEFAULT, ALTERNATIVE and DISABLED algorithms from the set.
 
     The algorithm selection is deterministic for a given time period and
@@ -200,9 +208,11 @@ def select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> AlgorithmS
     return AlgorithmSet(default, alternative, disabled)
 
 
-def algorithms_env(algs: AlgorithmSet) -> Dict[str, str]:
+def _algorithms_env(algs: AlgorithmSet, name: str) -> Dict[str, str]:
     """Return environment variables with selected algorithms as a dict."""
-    algs_env: Dict[str, str] = {}
+    algs_env = {
+        "ALGORITHM_SET": name,
+    }
 
     def set_alg_env(alg: Algorithm, prefix):
         algs_env[f"{prefix}_ALGORITHM"] = alg.name
@@ -217,25 +227,23 @@ def algorithms_env(algs: AlgorithmSet) -> Dict[str, str]:
     set_alg_env(algs.alternative, "ALTERNATIVE")
     set_alg_env(algs.disabled, "DISABLED")
 
-    logging.info("selected algorithms: %s", algs_env)
+    log.info("selected algorithms: %s", algs_env)
     return algs_env
 
 
-def main():
-    try:
-        algs = ALGORITHM_SETS[ALGORITHM_SET]
-        algs = filter_supported(algs)
-        algs = select_random(algs)
-        algs_env = algorithms_env(algs)
-    except Exception:
-        # if anything goes wrong, the conf.sh ignores error codes, so make sure
-        # we set an environment variable to an error value that can be checked
-        # later by the test runner and/or tests themselves
-        print("export ALGORITHM_SET=error")
-        raise
-    for name, value in algs_env.items():
-        print(f"export {name}={value}")
-
-
-if __name__ == "__main__":
-    main()
+def set_algorithm_set(name: Optional[str]):
+    if name is None:
+        name = "stable"
+    assert name in ALGORITHM_SETS, f'ALGORITHM_SET "{name}" unknown'
+    if name == ALG_VARS["ALGORITHM_SET"]:
+        log.debug('algorithm set already configured: "%s"', name)
+        return
+    log.debug('choosing from ALGORITHM_SET "%s"', name)
+
+    algs = ALGORITHM_SETS[name]
+    algs = _filter_supported(algs)
+    algs = _select_random(algs)
+    algs_env = _algorithms_env(algs, name)
+
+    ALG_VARS.update(algs_env)
+    os.environ.update(algs_env)
index 3e6d49dc749f237f58f076ed41f997fd20969dee..3478a84a545ab9cf826586fd9424183b0f3f897d 100644 (file)
@@ -15,6 +15,7 @@ from collections import ChainMap
 from .autoconf import AC_VARS  # type: ignore
 
 # pylint: enable=import-error
+from .algorithms import ALG_VARS
 from .basic import BASIC_VARS
 from .dirs import DIR_VARS
 from .openssl import OPENSSL_VARS
@@ -52,4 +53,4 @@ class VarLookup(ChainMap):
         return iter(self.keys())
 
 
-ALL = VarLookup(AC_VARS, BASIC_VARS, OPENSSL_VARS, PORT_VARS, DIR_VARS)
+ALL = VarLookup(AC_VARS, BASIC_VARS, OPENSSL_VARS, PORT_VARS, DIR_VARS, ALG_VARS)
index 7251e30f17a4e1f82669e57913a7b6d51b255b54..4b5e752afd52211717163756cb4427cb13990e38 100644 (file)
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
+# Explicitly setting ALGORITHM_SET is only needed is the script is executed
+# standalone without the pytest runner (e.g. for debugging).
 export ALGORITHM_SET="ecc_default"
-. ../conf.sh
 
-# Ensure the selected algorithm set is okay.
-if [ "$ALGORITHM_SET" = "error" ]; then
-  echofail "Algorithm selection failed." >&2
-  exit 1
-fi
+. ../conf.sh
 
 copy_setports ns1/named1.conf.in ns1/named.conf
 copy_setports ns2/named.conf.in ns2/named.conf
index 40248f96d985bd64e021a49082cabbeb6c624ecc..b460121b04112ea21b5c60ef727e309bbf789caf 100644 (file)
@@ -13,7 +13,6 @@
 
 set -e
 
-export ALGORITHM_SET="ecc_default"
 #shellcheck source=conf.sh
 . ../conf.sh
 
index 141ee838aa7f33b52aa4b0cc5671420d95a4b279..48d79acf28b39f3529249c4da95d9a7c73158f5f 100644 (file)
@@ -9,6 +9,10 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
+import pytest
+
+pytestmark = pytest.mark.algorithm_set("ecc_default")
+
 
 def test_mkeys(run_tests_sh):
     run_tests_sh()
index ff17998e3523afecc034a39bf4f36b178e18ff15..766b3dad2ea73675a35d7c4fcc457996080bfbb1 100644 (file)
@@ -20,3 +20,4 @@ junit_logging = log
 junit_log_passing_tests = 0
 markers =
     requires_zones_loaded: ensures the test does not start until the specified named instances load all configured zones
+    algorithm_set: use to select desired algorithms from isctest/vars/algorithms.py