diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 572c498659..9506d636d9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -397,7 +397,7 @@ stages: || (test -s config.log && cat config.log; exit 1) .git-clone-bind9-qa: &git_clone_bind9-qa - - git clone --depth 1 https://gitlab.isc.org/isc-projects/bind9-qa.git + - git clone --depth 1 https://gitlab.isc.org/isc-projects/bind9-qa.git "$CI_PROJECT_DIR"/bind9-qa # change directory to the workspace before including this .find_python: &find_python @@ -410,7 +410,7 @@ stages: .parse_tsan: &parse_tsan - *find_python - - find -name 'tsan.*' -exec "$PYTHON" util/parse_tsan.py {} \; + - find -name 'tsan.*' -exec "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/parse_tsan.py {} \; .check_readline_setup: &check_readline_setup - if [[ -n "${WITHOUT_READLINE}" ]]; then @@ -535,7 +535,9 @@ stages: -F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MIN]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MIN" -F "variables[SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MAX]=$SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_DRIFT_MAX" https://gitlab.isc.org/api/v4/projects/188/trigger/pipeline | jq .id) - - util/ci-wait-shotgun.py $PIPELINE_ID + - *git_clone_bind9-qa + - > + "$CI_PROJECT_DIR"/bind9-qa/ci/wait_shotgun.py $PIPELINE_ID needs: - job: ci-variables artifacts: true @@ -557,14 +559,14 @@ stages: - *fips_feature_test - *find_pytest - *find_python - - ( if [ "${CI_DISPOSABLE_ENVIRONMENT}" = "true" ]; then sleep 3000; "$PYTHON" "${CI_PROJECT_DIR}/util/get-running-system-tests.py"; fi ) & + - *git_clone_bind9-qa + - ( if [ "${CI_DISPOSABLE_ENVIRONMENT}" = "true" ]; then sleep 3000; "$PYTHON" "${CI_PROJECT_DIR}/bind9-qa/ci/get_running_system_tests.py"; fi ) & - cd bin/tests/system - RET=0 - > ("$PYTEST" --junit-xml="$CI_PROJECT_DIR"/junit_pytest.xml -n "$TEST_PARALLEL_JOBS" | tee pytest.out.txt) || RET=1 - - *git_clone_bind9-qa - > - "$PYTHON" bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_pytest.xml --output "$CI_PROJECT_DIR"/junit.xml + "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_pytest.xml --output "$CI_PROJECT_DIR"/junit.xml - (exit $RET) - '( ! grep -F "grep: warning:" pytest.out.txt )' - test "$CLEAN_BUILD_ARTIFACTS_ON_SUCCESS" -eq 0 || ( cd ../../.. && make clean >/dev/null 2>&1 ) @@ -598,10 +600,10 @@ stages: - cd "$CI_PROJECT_DIR" - *find_python - > - "$PYTHON" bin/tests/convert-trs-to-junit.py . > "$CI_PROJECT_DIR"/junit_system.xml + "$PYTHON" bin/tests/convert_trs_to_junit.py . > "$CI_PROJECT_DIR"/junit_system.xml - *git_clone_bind9-qa - > - "$PYTHON" bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_system.xml --output "$CI_PROJECT_DIR"/junit.xml + "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_system.xml --output "$CI_PROJECT_DIR"/junit.xml - (exit $RET) after_script: - cat bin/tests/system/test-suite.log || true @@ -630,9 +632,9 @@ stages: - *find_python - *git_clone_bind9-qa - > - "$PYTHON" "$CI_PROJECT_DIR"/bin/tests/convert-trs-to-junit.py . > "$CI_PROJECT_DIR"/junit_unit.xml + "$PYTHON" "$CI_PROJECT_DIR"/bin/tests/convert_trs_to_junit.py . > "$CI_PROJECT_DIR"/junit_unit.xml - > - "$PYTHON" bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_unit.xml --output "$CI_PROJECT_DIR"/junit.xml + "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_unit.xml --output "$CI_PROJECT_DIR"/junit.xml - (exit $RET) - test "$CLEAN_BUILD_ARTIFACTS_ON_SUCCESS" -eq 0 || make clean >/dev/null 2>&1 artifacts: @@ -664,7 +666,7 @@ stages: - make -j${BUILD_PARALLEL_JOBS:-1} V=1 - *setup_interfaces - *git_clone_bind9-qa - - cd bind9-qa/respdiff + - cd "$CI_PROJECT_DIR"/bind9-qa/respdiff needs: [] artifacts: paths: @@ -714,7 +716,7 @@ vulture: <<: *quick_checks_job <<: *python_triggering_rules script: - - vulture --exclude "*ans.py,conftest.py,re_compile_checker.py,isctest" --ignore-names "after_servers_start,bootstrap,pytestmark,autouse_*" bin/tests/system/ + - vulture ci-variables: <<: *quick_checks_job @@ -736,7 +738,8 @@ ci-orphaned-anchors: <<: *quick_checks_job script: - *git_clone_bind9-qa - - bind9-qa/ci-orphaned-anchors/check-orphaned-anchors-ci.py .gitlab-ci.yml + - > + "$CI_PROJECT_DIR"/bind9-qa/ci-orphaned-anchors/check_orphaned_anchors_ci.py .gitlab-ci.yml rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' changes: @@ -783,7 +786,7 @@ doctest: "$PYTEST" --noconftest --doctest-modules --junit-xml="$CI_PROJECT_DIR/junit_doctest.xml" || RET=1 - *git_clone_bind9-qa - > - "$PYTHON" bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR/junit_doctest.xml" --output "$CI_PROJECT_DIR/junit.xml" + "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR/junit_doctest.xml" --output "$CI_PROJECT_DIR/junit.xml" - (exit $RET) needs: - job: autoreconf @@ -796,12 +799,14 @@ doctest: pylint: <<: *quick_checks_job <<: *python_triggering_rules - variables: - PYTHONPATH: "${CI_PROJECT_DIR}/bin/tests/system" script: - - pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/|^contrib/)') - # Ignore Pylint wrong-import-position error in system test to enable use of pytest.importorskip - - pylint --rcfile $CI_PROJECT_DIR/.pylintrc --load-plugins re_compile_checker --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE '(ans\.py|vulture_ignore_list\.py)') + - pylint $(git ls-files '*.py') + +ruff: + <<: *quick_checks_job + <<: *python_triggering_rules + script: + - ruff check reuse: <<: *quick_checks_job @@ -856,7 +861,8 @@ generate-stress-test-configs: <<: *quick_checks_job script: - *git_clone_bind9-qa - - bind9-qa/stress/generate-stress-test-configs.py > stress-test-configs.yml + - > + "$CI_PROJECT_DIR"/bind9-qa/stress/generate_stress_test_configs.py > stress-test-configs.yml artifacts: paths: - stress-test-configs.yml @@ -864,7 +870,9 @@ generate-stress-test-configs: generate-tsan-stress-test-configs: <<: *quick_checks_job script: - - util/generate-tsan-stress-jobs.py > tsan-stress-test-configs.yml + - *git_clone_bind9-qa + - > + "$CI_PROJECT_DIR"/bind9-qa/ci/generate_tsan_stress_jobs.py > tsan-stress-test-configs.yml artifacts: paths: - tsan-stress-test-configs.yml @@ -1101,7 +1109,7 @@ cross-version-config-tests: "$PYTEST" --setup-only --junit-xml="$CI_PROJECT_DIR"/junit_pytest.xml -n "${TEST_PARALLEL_JOBS:-1}" || RET=1 - *git_clone_bind9-qa - > - "$PYTHON" bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_pytest.xml --output "$CI_PROJECT_DIR"/junit.xml + "$PYTHON" "$CI_PROJECT_DIR"/bind9-qa/ci/postprocess_junit_files.py "$CI_PROJECT_DIR"/junit_pytest.xml --output "$CI_PROJECT_DIR"/junit.xml - (exit $RET) needs: - job: autoreconf @@ -2056,7 +2064,8 @@ publish: variables: GIT_DEPTH: 1 script: - - bind9-qa/releng/printing_press_mr.py --document "${DOCUMENT}" --metadata bind9-qa/releng/metadata.json ${FORCE_CVE_IDS:+--force-cve-ids ${FORCE_CVE_IDS}} ${FORCE_SECURITY_RELEASES:+--force-security-releases ${FORCE_SECURITY_RELEASES}} + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/printing_press_mr.py --document "${DOCUMENT}" --metadata "$CI_PROJECT_DIR"/bind9-qa/releng/metadata.json ${FORCE_CVE_IDS:+--force-cve-ids ${FORCE_CVE_IDS}} ${FORCE_SECURITY_RELEASES:+--force-security-releases ${FORCE_SECURITY_RELEASES}} artifacts: paths: - printing-press/ @@ -2114,7 +2123,8 @@ merge-tag: variables: GIT_DEPTH: 100 script: - - bind9-qa/releng/merge_tag.py --tag "$CI_COMMIT_TAG" + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/merge_tag.py --tag "$CI_COMMIT_TAG" rules: - *rule_tag_open_source artifacts: @@ -2127,11 +2137,13 @@ update-stable-tag: variables: GIT_DEPTH: 1 script: - - bind9-qa/releng/update_stable_tag.py --tag "$CI_COMMIT_TAG" + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/update_stable_tag.py --tag "$CI_COMMIT_TAG" # Work around https://github.com/readthedocs/readthedocs.org/issues/10838 - sleep 300 - rm -rf ./bind9 # remove already cloned project - - bind9-qa/releng/update_stable_tag.py --tag "$CI_COMMIT_TAG" + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/update_stable_tag.py --tag "$CI_COMMIT_TAG" rules: - *rule_tag_open_source artifacts: @@ -2165,7 +2177,8 @@ customer-git:branch: - *git_clone_bind9-qa script: - git checkout -b "$BRANCH" # ensure refs/heads/$BRANCH exists; GitLab clones with detached HEAD - - bind9-qa/releng/push_to_customer_repository.py --branch "$BRANCH" --customer "$CUSTOMER" --force + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/push_to_customer_repository.py --branch "$BRANCH" --customer "$CUSTOMER" --force customer-git:tag: <<: *customer_git @@ -2178,7 +2191,8 @@ customer-git:tag: - *git_clone_bind9-qa - git clone --depth 1 "https://token:${ISC_CUSTOMERS_WRITE_TOKEN}@gitlab.isc.org/isc-customers/isc-customer-settings.git" script: - - bind9-qa/releng/push_to_customer_repository.py --tag "$CI_COMMIT_TAG" --entitlements isc-customer-settings/entitlements.yaml --force + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/push_to_customer_repository.py --tag "$CI_COMMIT_TAG" --entitlements isc-customer-settings/entitlements.yaml --force # Respdiff tests @@ -2250,7 +2264,7 @@ respdiff-third-party: - autoreconf -fi - *configure - make -j${BUILD_PARALLEL_JOBS:-1} V=1 - - cd bind9-qa/respdiff + - cd "$CI_PROJECT_DIR"/bind9-qa/respdiff - bash respdiff.sh -s named -q "${PWD}/100k_mixed.txt" -c 3 -w "${PWD}/rspworkdir" "${CI_PROJECT_DIR}/version-under-test" "${CI_PROJECT_DIR}/bin/named/named" respdiff:recent-named: @@ -2402,14 +2416,16 @@ backports: script: # CI job token is not sufficient for push operations - git remote get-url origin | sed -e "s/gitlab-ci-token:$CI_JOB_TOKEN/oauth2:$BIND_TEAM_WRITE_TOKEN/" | xargs git remote set-url --push origin - - bind9-qa/releng/backport_mr.py $CI_PROJECT_ID "$MERGE_REQUEST_ID" + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/backport_mr.py $CI_PROJECT_ID "$MERGE_REQUEST_ID" merged-metadata: <<: *post_merge rules: - if: '$CI_PIPELINE_SOURCE == "push" && ($CI_COMMIT_REF_NAME =~ /^bind-9.[0-9]+(-sub)?$/ || $CI_COMMIT_REF_NAME =~ /^v9.[0-9]+.[0-9]+-release$/ || $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH)' script: - - bind9-qa/releng/after_merge.py "$CI_PROJECT_ID" "$MERGE_REQUEST_ID" + - > + "$CI_PROJECT_DIR"/bind9-qa/releng/after_merge.py "$CI_PROJECT_ID" "$MERGE_REQUEST_ID" auto-rebase-trigger: stage: postmerge diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 3fb33f3c9c..0000000000 --- a/.pylintrc +++ /dev/null @@ -1,28 +0,0 @@ -[IMPORTS] - -deprecated-modules= - dns.resolver, - -[MESSAGES CONTROL] - -disable= - C0103, # invalid-name - C0114, # missing-module-docstring - C0115, # missing-class-docstring - C0116, # missing-function-docstring - C0209, # consider-using-f-string - C0301, # line-too-long, handled better by black - C0302, # too-many-lines - C0415, # import-outside-toplevel - R0801, # duplicate-code - R0901, # too-many-ancestors - R0902, # too-many-instance-attributes - R0903, # too-few-public-methods - R0904, # too-many-public-methods - R0911, # too-many-return-statements - R0912, # too-many-branches - R0913, # too-many-arguments - R0914, # too-many-locals - R0915, # too-many-statements - R0916, # too-many-boolean-expressions - R0917, # too-many-positional-arguments diff --git a/bin/tests/Makefile.am b/bin/tests/Makefile.am index 56e81b118a..2dd2067ba6 100644 --- a/bin/tests/Makefile.am +++ b/bin/tests/Makefile.am @@ -1,6 +1,6 @@ include $(top_srcdir)/Makefile.top -EXTRA_DIST = convert-trs-to-junit.py +EXTRA_DIST = convert_trs_to_junit.py SUBDIRS = system diff --git a/bin/tests/convert-trs-to-junit.py b/bin/tests/convert_trs_to_junit.py similarity index 91% rename from bin/tests/convert-trs-to-junit.py rename to bin/tests/convert_trs_to_junit.py index 927506a827..1e3bc3e79d 100755 --- a/bin/tests/convert-trs-to-junit.py +++ b/bin/tests/convert_trs_to_junit.py @@ -6,24 +6,22 @@ # # Convert automake .trs files into JUnit format suitable for Gitlab +from xml.etree import ElementTree +from xml.etree.ElementTree import Element, SubElement + import argparse import os import sys -from xml.etree import ElementTree -from xml.etree.ElementTree import Element -from xml.etree.ElementTree import SubElement -# getting explicit encoding specification right for Python 2/3 would be messy, -# so let's hope for the best def read_whole_text(filename): - with open(filename) as inf: # pylint: disable-msg=unspecified-encoding + with open(filename, encoding="utf-8") as inf: return inf.read().strip() def read_trs_result(filename): result = None - with open(filename, "r") as trs: # pylint: disable-msg=unspecified-encoding + with open(filename, "r", encoding="utf-8") as trs: for line in trs: items = line.split() if len(items) < 2: @@ -125,7 +123,7 @@ def check_directory(path): os.listdir(path) return path except OSError as ex: - msg = "Path {} cannot be listed as a directory: {}".format(path, ex) + msg = f"Path {path} cannot be listed as a directory: {ex}" raise argparse.ArgumentTypeError(msg) diff --git a/bin/tests/system/addzone/tests_rndc_deadlock.py b/bin/tests/system/addzone/tests_rndc_deadlock.py index f805897f29..1e20fdb0a0 100755 --- a/bin/tests/system/addzone/tests_rndc_deadlock.py +++ b/bin/tests/system/addzone/tests_rndc_deadlock.py @@ -68,7 +68,7 @@ def test_rndc_deadlock(ns3): # Create 4 worker threads running "rndc" commands in a loop. with concurrent.futures.ThreadPoolExecutor() as executor: for i in range(1, 5): - domain = "example%d" % i + domain = f"example{i}" executor.submit(rndc_loop, test_state, domain, ns3) # Run "rndc status" 10 times, with 1-second pauses between attempts. diff --git a/bin/tests/system/ans.py b/bin/tests/system/ans.py index 9dbdee11c1..3b822720a5 100644 --- a/bin/tests/system/ans.py +++ b/bin/tests/system/ans.py @@ -9,9 +9,7 @@ file, you can obtain one at https://mozilla.org/MPL/2.0/. See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. -""" -""" This is a bare-bones DNS server that only serves data from zone files. It is meant to be used as a replacement for full-blown named instances in system tests when a given server is only required to return zone-based data. @@ -34,9 +32,7 @@ useful in other system tests, please consider opening a merge request extending isctest/asyncserver.py. """ -from isctest.asyncserver import ( - AsyncDnsServer, -) +from isctest.asyncserver import AsyncDnsServer def main() -> None: diff --git a/bin/tests/system/bailiwick/ans1/ans.py b/bin/tests/system/bailiwick/ans1/ans.py index 859e77491f..75bf8790b2 100644 --- a/bin/tests/system/bailiwick/ans1/ans.py +++ b/bin/tests/system/bailiwick/ans1/ans.py @@ -11,18 +11,14 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rdatatype import dns.rrset -from isctest.asyncserver import ( - DnsResponseSend, - QueryContext, - ResponseAction, -) +from isctest.asyncserver import DnsResponseSend, QueryContext, ResponseAction -from bailiwick_ans import ResponseSpoofer, spoofing_server +from ..bailiwick_ans import ResponseSpoofer, spoofing_server ATTACKER_IP = "10.53.0.3" TTL = 3600 diff --git a/bin/tests/system/bailiwick/ans2/ans.py b/bin/tests/system/bailiwick/ans2/ans.py index 151a2c6ccc..a1010cc5d6 100644 --- a/bin/tests/system/bailiwick/ans2/ans.py +++ b/bin/tests/system/bailiwick/ans2/ans.py @@ -11,18 +11,14 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rdatatype import dns.rrset -from isctest.asyncserver import ( - DnsResponseSend, - QueryContext, - ResponseAction, -) +from isctest.asyncserver import DnsResponseSend, QueryContext, ResponseAction -from bailiwick_ans import ResponseSpoofer, spoofing_server +from ..bailiwick_ans import ResponseSpoofer, spoofing_server ATTACKER_IP = "10.53.0.3" TTL = 3600 diff --git a/bin/tests/system/bailiwick/bailiwick_ans.py b/bin/tests/system/bailiwick/bailiwick_ans.py index 28353a0a09..109516799f 100644 --- a/bin/tests/system/bailiwick/bailiwick_ans.py +++ b/bin/tests/system/bailiwick/bailiwick_ans.py @@ -11,8 +11,6 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import Dict, List, Optional, Type - import abc import dns.name @@ -30,14 +28,14 @@ from isctest.asyncserver import ( class ResponseSpoofer(ResponseHandler, abc.ABC): - spoofers: Dict[str, Type["ResponseSpoofer"]] = {} + spoofers: dict[str, type["ResponseSpoofer"]] = {} def __init_subclass__(cls, mode: str) -> None: assert mode not in cls.spoofers cls.spoofers[mode] = cls @classmethod - def get_spoofer(cls, mode: str) -> Optional["ResponseSpoofer"]: + def get_spoofer(cls, mode: str) -> "ResponseSpoofer | None": try: return cls.spoofers[mode]() except KeyError: @@ -66,11 +64,11 @@ class SetSpoofingModeCommand(ControlCommand): control_subdomain = "set-spoofing-mode" def __init__(self) -> None: - self._current_handler: Optional[ResponseSpoofer] = None + self._current_handler: ResponseSpoofer | None = None def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext - ) -> Optional[str]: + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> str | None: if len(args) != 1: qctx.response.set_rcode(dns.rcode.SERVFAIL) return "invalid control command" diff --git a/bin/tests/system/bailiwick/tests_bailiwick.py b/bin/tests/system/bailiwick/tests_bailiwick.py index bd844bd71a..8456cc6f51 100644 --- a/bin/tests/system/bailiwick/tests_bailiwick.py +++ b/bin/tests/system/bailiwick/tests_bailiwick.py @@ -9,20 +9,20 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import Dict import time import dns.message - +import dns.rrset import pytest -import isctest from isctest.instance import NamedInstance +import isctest + @pytest.fixture(autouse=True) -def autouse_flush_resolver_cache(servers: Dict[str, NamedInstance]) -> None: +def autouse_flush_resolver_cache(servers: dict[str, NamedInstance]) -> None: servers["ns4"].rndc("flush") @@ -78,7 +78,7 @@ def check_domain_hijack(ns4: NamedInstance) -> None: ) -def test_bailiwick_sibling_ns_referral(servers: Dict[str, NamedInstance]) -> None: +def test_bailiwick_sibling_ns_referral(servers: dict[str, NamedInstance]) -> None: set_spoofing_mode(ans1="sibling-ns", ans2="none") ns4 = servers["ns4"] @@ -86,7 +86,7 @@ def test_bailiwick_sibling_ns_referral(servers: Dict[str, NamedInstance]) -> Non check_domain_hijack(ns4) -def test_bailiwick_unsolicited_authority(servers: Dict[str, NamedInstance]) -> None: +def test_bailiwick_unsolicited_authority(servers: dict[str, NamedInstance]) -> None: set_spoofing_mode(ans1="none", ans2="unsolicited-ns") ns4 = servers["ns4"] @@ -95,7 +95,7 @@ def test_bailiwick_unsolicited_authority(servers: Dict[str, NamedInstance]) -> N check_domain_hijack(ns4) -def test_bailiwick_parent_glue(servers: Dict[str, NamedInstance]) -> None: +def test_bailiwick_parent_glue(servers: dict[str, NamedInstance]) -> None: set_spoofing_mode(ans1="none", ans2="parent-glue") ns4 = servers["ns4"] @@ -108,7 +108,7 @@ def test_bailiwick_parent_glue(servers: Dict[str, NamedInstance]) -> None: check_domain_hijack(ns4) -def test_bailiwick_spoofed_dname(servers: Dict[str, NamedInstance]) -> None: +def test_bailiwick_spoofed_dname(servers: dict[str, NamedInstance]) -> None: set_spoofing_mode(ans1="none", ans2="dname") ns4 = servers["ns4"] diff --git a/bin/tests/system/chain/ans3/ans.py b/bin/tests/system/chain/ans3/ans.py index f10387fbf4..a36ab41c70 100755 --- a/bin/tests/system/chain/ans3/ans.py +++ b/bin/tests/system/chain/ans3/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.name import dns.rcode diff --git a/bin/tests/system/chain/ans4/ans.py b/bin/tests/system/chain/ans4/ans.py index 2f0d8c3352..b21ba81fef 100755 --- a/bin/tests/system/chain/ans4/ans.py +++ b/bin/tests/system/chain/ans4/ans.py @@ -11,9 +11,9 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator from dataclasses import dataclass from enum import Enum -from typing import AsyncGenerator, List, Optional, Tuple import abc import logging @@ -123,7 +123,7 @@ class RecordGenerator(abc.ABC): def __init__(self, name_generator: ChainNameGenerator) -> None: self._name_generator = name_generator - def get_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def get_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: """ Return the lists of records and their signatures that should be generated in response to a given "action". @@ -155,7 +155,7 @@ class RecordGenerator(abc.ABC): raise NotImplementedError @abc.abstractmethod - def generate_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def generate_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: """ Return the lists of records and their signatures that should be generated in response to a given "action". @@ -170,7 +170,7 @@ class CnameRecordGenerator(RecordGenerator): response_count = 1 - def generate_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def generate_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: owner = self._name_generator.current_name target = self._name_generator.generate_next_name().to_text() response = self.create_rrset(owner, dns.rdatatype.CNAME, target) @@ -182,7 +182,7 @@ class DnameRecordGenerator(RecordGenerator): response_count = 2 - def generate_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def generate_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: dname_owner = self._name_generator.current_domain cname_owner = self._name_generator.current_name dname_target = self._name_generator.generate_next_sld().to_text() @@ -206,7 +206,7 @@ class XnameRecordGenerator(RecordGenerator): response_count = 1 - def generate_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def generate_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: owner = self._name_generator.current_name target = self._name_generator.generate_next_name_in_next_sld().to_text() response = self.create_rrset(owner, dns.rdatatype.CNAME, target) @@ -218,7 +218,7 @@ class FinalRecordGenerator(RecordGenerator): response_count = 1 - def generate_rrsets(self) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + def generate_rrsets(self) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: owner = self._name_generator.current_name response = self.create_rrset(owner, dns.rdatatype.A, "10.53.0.4") signature = self.create_rrset_signature(owner, response.rdtype) @@ -297,11 +297,11 @@ class ChainSetupCommand(ControlCommand): control_subdomain = "setup-chain" def __init__(self) -> None: - self._current_handler: Optional[ChainResponseHandler] = None + self._current_handler: ChainResponseHandler | None = None def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext - ) -> Optional[str]: + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> str | None: try: actions, selectors = self._parse_args(args) except ValueError as exc: @@ -320,8 +320,8 @@ class ChainSetupCommand(ControlCommand): return "chain response setup successful" def _parse_args( - self, args: List[str] - ) -> Tuple[List[ChainAction], List[ChainSelector]]: + self, args: list[str] + ) -> tuple[list[ChainAction], list[ChainSelector]]: try: delimiter = args.index("_") except ValueError as exc: @@ -335,7 +335,7 @@ class ChainSetupCommand(ControlCommand): return actions, selectors - def _parse_args_actions(self, args_actions: List[str]) -> List[ChainAction]: + def _parse_args_actions(self, args_actions: list[str]) -> list[ChainAction]: actions = [] for action in args_actions + ["FINAL"]: @@ -347,8 +347,8 @@ class ChainSetupCommand(ControlCommand): return actions def _parse_args_selectors( - self, args_selectors: List[str], actions: List[ChainAction] - ) -> List[ChainSelector]: + self, args_selectors: list[str], actions: list[ChainAction] + ) -> list[ChainSelector]: max_response_index = self._get_max_response_index(actions) selectors = [] @@ -366,19 +366,19 @@ class ChainSetupCommand(ControlCommand): return selectors - def _get_max_response_index(self, actions: List[ChainAction]) -> int: + def _get_max_response_index(self, actions: list[ChainAction]) -> int: rrset_generator_classes = [a.value for a in actions] return sum(g.response_count for g in rrset_generator_classes) def _prepare_answer( - self, actions: List[ChainAction], selectors: List[ChainSelector] - ) -> List[dns.rrset.RRset]: + self, actions: list[ChainAction], selectors: list[ChainSelector] + ) -> list[dns.rrset.RRset]: all_responses, all_signatures = self._generate_rrsets(actions) return self._select_rrsets(all_responses, all_signatures, selectors) def _generate_rrsets( - self, actions: List[ChainAction] - ) -> Tuple[List[dns.rrset.RRset], List[dns.rrset.RRset]]: + self, actions: list[ChainAction] + ) -> tuple[list[dns.rrset.RRset], list[dns.rrset.RRset]]: all_responses = [] all_signatures = [] name_generator = ChainNameGenerator() @@ -394,10 +394,10 @@ class ChainSetupCommand(ControlCommand): def _select_rrsets( self, - all_responses: List[dns.rrset.RRset], - all_signatures: List[dns.rrset.RRset], - selectors: List[ChainSelector], - ) -> List[dns.rrset.RRset]: + all_responses: list[dns.rrset.RRset], + all_signatures: list[dns.rrset.RRset], + selectors: list[ChainSelector], + ) -> list[dns.rrset.RRset]: rrsets = [] for selector in selectors: @@ -418,7 +418,7 @@ class ChainResponseHandler(DomainHandler): domains = ["domain.nil."] - def __init__(self, answer_rrsets: List[dns.rrset.RRset]): + def __init__(self, answer_rrsets: list[dns.rrset.RRset]): super().__init__() self._answer_rrsets = answer_rrsets @@ -441,7 +441,7 @@ class ChainResponseHandler(DomainHandler): qctx.response.use_edns() yield DnsResponseSend(qctx.response) - def _non_chain_answer(self, qctx: QueryContext) -> List[dns.rrset.RRset]: + def _non_chain_answer(self, qctx: QueryContext) -> list[dns.rrset.RRset]: owner = qctx.qname return [ RecordGenerator.create_rrset(owner, dns.rdatatype.A, "10.53.0.4"), @@ -449,14 +449,14 @@ class ChainResponseHandler(DomainHandler): ] @property - def _authority_rrsets(self) -> List[dns.rrset.RRset]: + def _authority_rrsets(self) -> list[dns.rrset.RRset]: owner = dns.name.from_text("domain.nil.") return [ RecordGenerator.create_rrset(owner, dns.rdatatype.NS, "ns1.domain.nil."), ] @property - def _additional_rrsets(self) -> List[dns.rrset.RRset]: + def _additional_rrsets(self) -> list[dns.rrset.RRset]: owner = dns.name.from_text("ns1.domain.nil.") return [ RecordGenerator.create_rrset(owner, dns.rdatatype.A, "10.53.0.4"), diff --git a/bin/tests/system/checkds/tests_checkds.py b/bin/tests/system/checkds/tests_checkds.py index 26265ad612..c0f834c42b 100755 --- a/bin/tests/system/checkds/tests_checkds.py +++ b/bin/tests/system/checkds/tests_checkds.py @@ -12,21 +12,19 @@ # information regarding copyright ownership. -from typing import NamedTuple, Tuple +from typing import NamedTuple import os import sys import time -import isctest -import pytest - -import dns.exception -import dns.message import dns.name import dns.rcode import dns.rdataclass import dns.rdatatype +import pytest + +import isctest pytestmark = [ pytest.mark.skipif( @@ -189,7 +187,7 @@ def keystate_check(server, zone, key): class CheckDSTest(NamedTuple): zone: str - logs_to_wait_for: Tuple[str] + logs_to_wait_for: tuple[str] expected_parent_state: str diff --git a/bin/tests/system/cipher-suites/tests_cipher_suites.py b/bin/tests/system/cipher-suites/tests_cipher_suites.py index 4b2ba07518..c20401bbce 100644 --- a/bin/tests/system/cipher-suites/tests_cipher_suites.py +++ b/bin/tests/system/cipher-suites/tests_cipher_suites.py @@ -11,10 +11,9 @@ from re import compile as Re +import dns.rcode import pytest -import dns.message - import isctest import isctest.mark diff --git a/bin/tests/system/conftest.py b/bin/tests/system/conftest.py index 49126d9788..639a51d767 100644 --- a/bin/tests/system/conftest.py +++ b/bin/tests/system/conftest.py @@ -9,23 +9,28 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import filecmp -import os from pathlib import Path from re import compile as Re + +import filecmp +import os import shutil import subprocess +import sys import tempfile import time -import sys import pytest pytest.register_assert_rewrite("isctest") -import isctest +# pylint: disable=wrong-import-position from isctest.vars.dirs import SYSTEM_TEST_DIR_GIT_PATH +import isctest + +# pylint: enable=wrong-import-position + # Silence warnings caused by passing a pytest fixture to another fixture. # pylint: disable=redefined-outer-name @@ -38,9 +43,7 @@ isctest.vars.init_vars() # ----------------------- Globals definition ----------------------------- -XDIST_WORKER = os.environ.get("PYTEST_XDIST_WORKER", "") FILE_DIR = os.path.abspath(Path(__file__).parent) -ENV_RE = Re(b"([^=]+)=(.*)") PRIORITY_TESTS = [ # Tests that are scheduled first. Speeds up parallel execution. "rpz/", @@ -70,25 +73,6 @@ def pytest_addoption(parser): ) -def pytest_configure(config): - # Ensure this hook only runs on the main pytest instance if xdist is - # used to spawn other workers. - if not XDIST_WORKER: - if config.pluginmanager.has_plugin("xdist") and config.option.numprocesses: - # system tests depend on module scope for setup & teardown - # enforce use "loadscope" scheduler or disable paralelism - try: - import xdist.scheduler.loadscope # pylint: disable=unused-import - except ImportError: - isctest.log.debug( - "xdist is too old and does not have " - "scheduler.loadscope, disabling parallelism" - ) - config.option.dist = "no" - else: - config.option.dist = "loadscope" - - def pytest_ignore_collect(collection_path): # System tests are executed in temporary directories inside # bin/tests/system. These temporary directories contain all files @@ -245,6 +229,11 @@ def control_port(): return int(os.environ["CONTROLPORT"]) +@pytest.fixture(scope="module") +def default_algorithm(): + return isctest.vars.algorithms.Algorithm.default() + + @pytest.fixture(scope="module") def system_test_name(request): """Name of the system test directory.""" @@ -272,7 +261,7 @@ def configure_algorithm_set(request): name = None else: name = mark.args[0] - isctest.vars.set_algorithm_set(name) + isctest.vars.algorithms.set_algorithm_set(name) @pytest.fixture(autouse=True) diff --git a/bin/tests/system/convert-junit-to-trs.py b/bin/tests/system/convert_junit_to_trs.py similarity index 88% rename from bin/tests/system/convert-junit-to-trs.py rename to bin/tests/system/convert_junit_to_trs.py index 9675825a50..429eaf09fe 100755 --- a/bin/tests/system/convert-junit-to-trs.py +++ b/bin/tests/system/convert_junit_to_trs.py @@ -6,9 +6,11 @@ # # Convert JUnit pytest output to automake .trs files +from pathlib import Path +from xml.etree import ElementTree + import argparse import sys -from xml.etree import ElementTree def junit_to_trs(junit_xml): @@ -16,7 +18,7 @@ def junit_to_trs(junit_xml): testcases = root.findall(".//testcase") if len(testcases) < 1: - print(":test-result: ERROR convert-junit-to-trs.py") + print(":test-result: ERROR convert_junit_to_trs.py") return 99 has_fail = False @@ -57,12 +59,13 @@ def main(): ) parser.add_argument( "junit_file", - type=argparse.FileType("r", encoding="utf-8"), + type=Path, help="junit xml result file", ) args = parser.parse_args() - junit_xml = args.junit_file.read() + with args.junit_file.open(encoding="utf-8") as junit_file: + junit_xml = junit_file.read() sys.exit(junit_to_trs(junit_xml)) diff --git a/bin/tests/system/cookie/ans10/ans.py b/bin/tests/system/cookie/ans10/ans.py index 0be47f173b..cada97ab57 100644 --- a/bin/tests/system/cookie/ans10/ans.py +++ b/bin/tests/system/cookie/ans10/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from cookie_ans import cookie_server +from ..cookie_ans import cookie_server def main() -> None: diff --git a/bin/tests/system/cookie/ans9/ans.py b/bin/tests/system/cookie/ans9/ans.py index 5c9b07f4ff..21836d97af 100644 --- a/bin/tests/system/cookie/ans9/ans.py +++ b/bin/tests/system/cookie/ans9/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from cookie_ans import cookie_server +from ..cookie_ans import cookie_server def main() -> None: diff --git a/bin/tests/system/cookie/cookie_ans.py b/bin/tests/system/cookie/cookie_ans.py index 72f0e0ab46..3b6f0406f2 100644 --- a/bin/tests/system/cookie/cookie_ans.py +++ b/bin/tests/system/cookie/cookie_ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.edns import dns.name @@ -20,12 +20,11 @@ import dns.tsigkeyring from isctest.asyncserver import ( AsyncDnsServer, - ResponseHandler, - DnsResponseSend, DnsProtocol, + DnsResponseSend, QueryContext, + ResponseHandler, ) - from isctest.name import prepend_label from isctest.vars.algorithms import ALG_VARS diff --git a/bin/tests/system/custom-test-driver b/bin/tests/system/custom-test-driver index 278cb377e2..a2f76910b1 100755 --- a/bin/tests/system/custom-test-driver +++ b/bin/tests/system/custom-test-driver @@ -146,7 +146,7 @@ else fi # Run junit to trs converter script. -./convert-junit-to-trs.py $junit_file >$trs_file +./convert_junit_to_trs.py $junit_file >$trs_file estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then diff --git a/bin/tests/system/database/tests_database.py b/bin/tests/system/database/tests_database.py index 89f818e9aa..8e4a0e7ae4 100644 --- a/bin/tests/system/database/tests_database.py +++ b/bin/tests/system/database/tests_database.py @@ -9,7 +9,8 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import dns + +import dns.rrset import isctest diff --git a/bin/tests/system/dialup/tests_dialup_zone_transfer.py b/bin/tests/system/dialup/tests_dialup_zone_transfer.py index 11cf4d9c4f..25d55f9f93 100644 --- a/bin/tests/system/dialup/tests_dialup_zone_transfer.py +++ b/bin/tests/system/dialup/tests_dialup_zone_transfer.py @@ -9,7 +9,9 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +import dns.flags import dns.message +import dns.rcode import pytest import isctest diff --git a/bin/tests/system/digdelv/ans4/ans.py b/bin/tests/system/digdelv/ans4/ans.py index 6f5346ff86..d162070c76 100644 --- a/bin/tests/system/digdelv/ans4/ans.py +++ b/bin/tests/system/digdelv/ans4/ans.py @@ -9,10 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from isctest.asyncserver import ( - AsyncDnsServer, - IgnoreAllQueries, -) +from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries def main() -> None: diff --git a/bin/tests/system/digdelv/ans5/ans.py b/bin/tests/system/digdelv/ans5/ans.py index a53045305d..1d7375791e 100644 --- a/bin/tests/system/digdelv/ans5/ans.py +++ b/bin/tests/system/digdelv/ans5/ans.py @@ -9,8 +9,9 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from collections.abc import AsyncGenerator + import logging -from typing import AsyncGenerator, List, Optional import dns.rcode import dns.rdatatype @@ -30,7 +31,7 @@ from isctest.asyncserver import ( class ErraticAxfrHandler(ResponseHandler): allowed_actions = ["no-response", "partial-axfr", "complete-axfr"] - def __init__(self, actions: List[str]) -> None: + def __init__(self, actions: list[str]) -> None: self.actions = actions self.counter = 0 for action in actions: @@ -68,10 +69,10 @@ class ResponseSequenceCommand(ControlCommand): control_subdomain = "response-sequence" def __init__(self) -> None: - self._current_handler: Optional[ResponseHandler] = None + self._current_handler: ResponseHandler | None = None def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext ) -> str: for action in args: if action not in ErraticAxfrHandler.allowed_actions: diff --git a/bin/tests/system/digdelv/ans6/ans.py b/bin/tests/system/digdelv/ans6/ans.py index 77e7141590..78b9ce7040 100644 --- a/bin/tests/system/digdelv/ans6/ans.py +++ b/bin/tests/system/digdelv/ans6/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.opcode import dns.rcode @@ -17,8 +17,8 @@ import dns.rcode from isctest.asyncserver import ( AsyncDnsServer, DnsResponseSend, - ResponseHandler, QueryContext, + ResponseHandler, ) diff --git a/bin/tests/system/digdelv/ans7/ans.py b/bin/tests/system/digdelv/ans7/ans.py index 768c01e224..a9a8a0966c 100644 --- a/bin/tests/system/digdelv/ans7/ans.py +++ b/bin/tests/system/digdelv/ans7/ans.py @@ -9,9 +9,8 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator -import dns import dns.rcode from isctest.asyncserver import ( diff --git a/bin/tests/system/digdelv/yamlget.py b/bin/tests/system/digdelv/yamlget.py index afa582dd9c..0919c13c60 100644 --- a/bin/tests/system/digdelv/yamlget.py +++ b/bin/tests/system/digdelv/yamlget.py @@ -13,8 +13,7 @@ import sys try: import yaml -# pylint: disable=bare-except -except: +except ImportError: print("No python yaml module, skipping") sys.exit(1) diff --git a/bin/tests/system/dispatch/ans3/ans.py b/bin/tests/system/dispatch/ans3/ans.py index 97b1f2cf1f..1099928b08 100644 --- a/bin/tests/system/dispatch/ans3/ans.py +++ b/bin/tests/system/dispatch/ans3/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.flags import dns.rcode diff --git a/bin/tests/system/dispatch/tests_connreset.py b/bin/tests/system/dispatch/tests_connreset.py index 01a1bbc5c0..e263580cad 100644 --- a/bin/tests/system/dispatch/tests_connreset.py +++ b/bin/tests/system/dispatch/tests_connreset.py @@ -11,10 +11,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import pytest -import isctest - import dns.message +import pytest + +import isctest pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/dns_import_checker.py b/bin/tests/system/dns_import_checker.py new file mode 100644 index 0000000000..0af3252cde --- /dev/null +++ b/bin/tests/system/dns_import_checker.py @@ -0,0 +1,177 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from pylint.checkers import BaseChecker + +import astroid + + +class DnsExplicitImportsChecker(BaseChecker): + name = "dns-explicit-imports" + + msgs = { + "W9001": ( + "Bare 'import dns' is discouraged; import required submodules explicitly", + "dns-bare-import", + "Emitted when the package root 'dns' is imported directly.", + ), + "W9002": ( + "Missing explicit import for '%s' (add `import %s`)", + "dns-missing-submodule-import", + "Emitted when code references dns.<...> but the corresponding module prefix " + "was not imported with `import dns.<...>`.", + ), + "W9003": ( + "Unused explicit import for '%s' (remove `import %s`)", + "dns-unused-submodule-import", + "Emitted when a dns.<...> module is imported explicitly but not used.", + ), + } + + def __init__(self, linter=None): + super().__init__(linter) + self._imported = {} + self._imported_aliases = set() + self._required = {} + + def visit_module(self, node): # pylint: disable=unused-argument + self._imported = {} + self._imported_aliases = set() + self._required = {} + + def leave_module(self, node): # pylint: disable=unused-argument + for mod, use_node in sorted(self._required.items()): + if mod in self._imported: + continue + prefix = mod + "." + if any(name.startswith(prefix) for name in self._imported): + continue + self.add_message( + "dns-missing-submodule-import", + node=use_node, + args=(mod, mod), + ) + for mod, import_node in sorted(self._imported.items()): + if mod in self._imported_aliases: + continue + if any( + name == mod or name.startswith(mod + ".") for name in self._required + ): + continue + self.add_message( + "dns-unused-submodule-import", + node=import_node, + args=(mod, mod), + ) + + def visit_import(self, node): + for name, _asname in node.names: + if name == "dns": + self.add_message("dns-bare-import", node=node) + continue + if name.startswith("dns."): + self._imported.setdefault(name, node) + if _asname: + self._imported_aliases.add(name) + + def visit_importfrom(self, node): # pylint: disable=unused-argument + return + + def visit_attribute(self, node): + parent = node.parent + # For `dns.a.b.c`, astroid visits intermediate attributes too. + # Process only the rightmost node to avoid duplicate bookkeeping. + if isinstance(parent, astroid.nodes.Attribute) and parent.expr is node: + return + + mod = self._dns_module_for_attribute(node) + if mod is None: + return + + self._required.setdefault(mod, node) + + @staticmethod + def _dns_attribute_nodes(node): + """ + Return the chain of Attribute nodes as a list. + + For `dns.a.b.c`, return the list of Attribute nodes for `dns.a`, `dns.a.b`, and `dns.a.b.c`. + + Return None if the chain is not rooted in `dns`. + """ + + if not isinstance(node, astroid.nodes.Attribute): + return None + + nodes = [] + expr = node + while isinstance(expr, astroid.nodes.Attribute): + nodes.append(expr) + expr = expr.expr + + if not isinstance(expr, astroid.nodes.Name) or expr.name != "dns": + return None + + return list(reversed(nodes)) + + @classmethod + def _dns_module_for_attribute(cls, node): + """ + For dns.a.b.c, return the longest dns.a.b... prefix that is likely to be a module, + or None if the chain is not rooted in dns. + """ + last_module = None + chain_nodes = cls._dns_attribute_nodes(node) + if chain_nodes is None: + return None + + full = "dns." + ".".join(part.attrname for part in chain_nodes) + # Prefer inferred module names to avoid treating classes/constants as + # modules (e.g. `dns.name.NameRelation` should resolve to `dns.name`). + for chain_node in chain_nodes: + inferred = cls._infer_module_name(chain_node) + if inferred is not None and full.startswith(inferred): + last_module = inferred + if last_module is not None: + return last_module + + # Fallback when inference is unavailable: assume the terminal segment + # is not a module symbol and require the parent path. + parts = full.split(".") + if len(parts) <= 2: + return full + return ".".join(parts[:-1]) + + @staticmethod + def _infer_module_name(node): + """Infer `dns.` for a node; return None if inference is unsure.""" + try: + for inferred in node.infer(): + if inferred is astroid.util.Uninferable: + continue + # Inference can return either a Module node directly or another + # symbol rooted in a module; normalize both to module name. + module = ( + inferred + if isinstance(inferred, astroid.nodes.Module) + else inferred.root() + ) + name = module.name + if name.startswith("dns."): + return name + # Inference can fail for dynamic/partial code; fall back gracefully. + except astroid.AstroidError: + pass + return None + + +def register(linter): + linter.register_checker(DnsExplicitImportsChecker(linter)) diff --git a/bin/tests/system/dnssec-malformed-dnskey/tests_malformed_dnskey.py b/bin/tests/system/dnssec-malformed-dnskey/tests_malformed_dnskey.py index d66644ce7b..cdb8932e7c 100644 --- a/bin/tests/system/dnssec-malformed-dnskey/tests_malformed_dnskey.py +++ b/bin/tests/system/dnssec-malformed-dnskey/tests_malformed_dnskey.py @@ -9,21 +9,22 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import base64 from re import compile as Re +import base64 import os -import pytest - -pytest.importorskip("cryptography") from cryptography.hazmat.primitives.asymmetric import ec - -import dns -import dns.dnssec -import dns.zone from dns.rdtypes.dnskeybase import Flag +import dns.dnssec +import dns.name +import dns.rdataclass +import dns.rdatatype +import dns.rdtypes.ANY.RRSIG +import dns.zone +import pytest + import isctest diff --git a/bin/tests/system/dnssec/ans10/ans.py b/bin/tests/system/dnssec/ans10/ans.py index d5d22e621e..b584151f0d 100644 --- a/bin/tests/system/dnssec/ans10/ans.py +++ b/bin/tests/system/dnssec/ans10/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rdatatype import dns.rrset diff --git a/bin/tests/system/dnstap/tests_dnstap.py b/bin/tests/system/dnstap/tests_dnstap.py index 67061ab9a5..1ec4cc17cf 100644 --- a/bin/tests/system/dnstap/tests_dnstap.py +++ b/bin/tests/system/dnstap/tests_dnstap.py @@ -14,11 +14,12 @@ import os import re -import isctest -import isctest.mark +import dns.rcode +import dns.rrset import pytest -import dns.rrset +import isctest +import isctest.mark pytestmark = [ isctest.mark.with_dnstap, diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py index ab7e3c9ada..77bca8be7f 100644 --- a/bin/tests/system/dnstap/ydump.py +++ b/bin/tests/system/dnstap/ydump.py @@ -17,8 +17,8 @@ except (ModuleNotFoundError, ImportError): print("No python yaml module, skipping") sys.exit(1) -import subprocess import pprint +import subprocess DNSTAP_READ = sys.argv[1] DATAFILE = sys.argv[2] diff --git a/bin/tests/system/doth/conftest.py b/bin/tests/system/doth/conftest.py index b95baeaab5..2c2104d2fd 100644 --- a/bin/tests/system/doth/conftest.py +++ b/bin/tests/system/doth/conftest.py @@ -14,6 +14,7 @@ import shutil import pytest + import isctest diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py index ca1fddbcc6..70ed382fc6 100755 --- a/bin/tests/system/doth/stress_http_quota.py +++ b/bin/tests/system/doth/stress_http_quota.py @@ -11,18 +11,16 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from functools import reduce +from resource import RLIMIT_NOFILE, getrlimit, setrlimit + import os -import sys +import random import socket import subprocess -import random +import sys import time -from functools import reduce -from resource import getrlimit -from resource import setrlimit -from resource import RLIMIT_NOFILE - MULTIDIG_INSTANCES = 10 CONNECT_TRIES = 5 @@ -137,9 +135,8 @@ class SubDIG: return command def run(self): - # pylint: disable=consider-using-with with open(os.devnull, "w", encoding="utf-8") as devnull: - self.sub_process = subprocess.Popen( + self.sub_process = subprocess.Popen( # pylint: disable=consider-using-with self.get_command(), shell=True, stdout=devnull ) @@ -228,8 +225,8 @@ def run_test(http_secure=True): assert subdig.alive(), "The single DIG instance is expected to be alive" assert multidig.alive(), ( "The DIG instances from the set are all expected to " - "be alive, but {} of them have completed" - ).format(multidig.completed()) + f"be alive, but {multidig.completed()} of them have completed" + ) # Let's close opened connections (in random order) to let all dig # processes to complete connector.disconnect_all() diff --git a/bin/tests/system/doth/tests_gnutls.py b/bin/tests/system/doth/tests_gnutls.py index 42ef3f6973..7053311deb 100644 --- a/bin/tests/system/doth/tests_gnutls.py +++ b/bin/tests/system/doth/tests_gnutls.py @@ -16,13 +16,12 @@ import struct import subprocess import time -import pytest - -import dns import dns.exception +import dns.message import dns.name import dns.rdataclass import dns.rdatatype +import pytest import isctest @@ -48,7 +47,7 @@ def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): "--no-ocsp", "--alpn=dot", "--logfile=gnutls-cli.log", - "--port=%d" % named_tlsport, + f"--port={named_tlsport}", "10.53.0.1", ] with open("gnutls-cli.err", "wb") as gnutls_cli_stderr, subprocess.Popen( diff --git a/bin/tests/system/dsdigest/tests_dsdigest.py b/bin/tests/system/dsdigest/tests_dsdigest.py index ccf1431e23..2a58ad2da2 100644 --- a/bin/tests/system/dsdigest/tests_dsdigest.py +++ b/bin/tests/system/dsdigest/tests_dsdigest.py @@ -10,6 +10,7 @@ # information regarding copyright ownership. import dns.flags +import dns.message import pytest import isctest diff --git a/bin/tests/system/ecdsa/tests_ecdsa.py b/bin/tests/system/ecdsa/tests_ecdsa.py index 08b4ee0e68..95fcaf9856 100644 --- a/bin/tests/system/ecdsa/tests_ecdsa.py +++ b/bin/tests/system/ecdsa/tests_ecdsa.py @@ -10,9 +10,9 @@ # information regarding copyright ownership. import os -import pytest import dns.flags +import pytest import isctest diff --git a/bin/tests/system/fetchlimit/ans4/ans.py b/bin/tests/system/fetchlimit/ans4/ans.py index cd7602366b..3b01eaa6a6 100644 --- a/bin/tests/system/fetchlimit/ans4/ans.py +++ b/bin/tests/system/fetchlimit/ans4/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype diff --git a/bin/tests/system/filters/common.py b/bin/tests/system/filters/common.py index e5ff22e977..12542a9ab6 100644 --- a/bin/tests/system/filters/common.py +++ b/bin/tests/system/filters/common.py @@ -9,9 +9,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import dns from dns import rdataclass, rdatatype +import dns.name + import isctest ARTIFACTS = [ diff --git a/bin/tests/system/filters/tests_filter_a_v4.py b/bin/tests/system/filters/tests_filter_a_v4.py index cb690eb352..e38a4f1422 100644 --- a/bin/tests/system/filters/tests_filter_a_v4.py +++ b/bin/tests/system/filters/tests_filter_a_v4.py @@ -11,8 +11,6 @@ import pytest -import isctest.mark - from filters.common import ( ARTIFACTS, check_filter, @@ -20,6 +18,8 @@ from filters.common import ( prime_cache, ) +import isctest.mark + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/filters/tests_filter_a_v6.py b/bin/tests/system/filters/tests_filter_a_v6.py index 1d33f2fd05..69d56c0dae 100644 --- a/bin/tests/system/filters/tests_filter_a_v6.py +++ b/bin/tests/system/filters/tests_filter_a_v6.py @@ -11,8 +11,6 @@ import pytest -import isctest.mark - from filters.common import ( ARTIFACTS, check_filter, @@ -20,6 +18,8 @@ from filters.common import ( prime_cache, ) +import isctest.mark + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/filters/tests_filter_aaaa_v4.py b/bin/tests/system/filters/tests_filter_aaaa_v4.py index 3c783a9cf3..7f5e612865 100644 --- a/bin/tests/system/filters/tests_filter_aaaa_v4.py +++ b/bin/tests/system/filters/tests_filter_aaaa_v4.py @@ -11,9 +11,6 @@ import pytest -import isctest -import isctest.mark - from filters.common import ( ARTIFACTS, check_filter, @@ -21,6 +18,8 @@ from filters.common import ( prime_cache, ) +import isctest.mark + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/filters/tests_filter_aaaa_v6.py b/bin/tests/system/filters/tests_filter_aaaa_v6.py index b973724e14..001a0dd5bf 100644 --- a/bin/tests/system/filters/tests_filter_aaaa_v6.py +++ b/bin/tests/system/filters/tests_filter_aaaa_v6.py @@ -11,8 +11,6 @@ import pytest -import isctest.mark - from filters.common import ( ARTIFACTS, check_filter, @@ -20,6 +18,8 @@ from filters.common import ( prime_cache, ) +import isctest.mark + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/filters/tests_filter_checkconf.py b/bin/tests/system/filters/tests_filter_checkconf.py index de5eae132f..46ab794c8a 100644 --- a/bin/tests/system/filters/tests_filter_checkconf.py +++ b/bin/tests/system/filters/tests_filter_checkconf.py @@ -15,10 +15,10 @@ import subprocess import pytest -import isctest - from filters.common import ARTIFACTS +import isctest + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/filters/tests_filter_dns64.py b/bin/tests/system/filters/tests_filter_dns64.py index 39c0bbc603..dfa71b76c1 100644 --- a/bin/tests/system/filters/tests_filter_dns64.py +++ b/bin/tests/system/filters/tests_filter_dns64.py @@ -11,10 +11,10 @@ import pytest -import isctest - from filters.common import ARTIFACTS +import isctest + pytestmark = pytest.mark.extra_artifacts(ARTIFACTS) diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py index b5b590aabf..9c854a6b76 100644 --- a/bin/tests/system/forward/ans11/ans.py +++ b/bin/tests/system/forward/ans11/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rdatatype import dns.rrset diff --git a/bin/tests/system/forward/ans6/ans.py b/bin/tests/system/forward/ans6/ans.py index fdcbe7d392..271439b37c 100644 --- a/bin/tests/system/forward/ans6/ans.py +++ b/bin/tests/system/forward/ans6/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.name import dns.rcode diff --git a/bin/tests/system/glue/tests_glue.py b/bin/tests/system/glue/tests_glue.py index 93b0164c39..4b08515535 100644 --- a/bin/tests/system/glue/tests_glue.py +++ b/bin/tests/system/glue/tests_glue.py @@ -10,6 +10,7 @@ # information regarding copyright ownership. +import dns.edns import dns.flags import dns.message import pytest diff --git a/bin/tests/system/isctest/__init__.py b/bin/tests/system/isctest/__init__.py index 4b5f299376..b1731f5cd5 100644 --- a/bin/tests/system/isctest/__init__.py +++ b/bin/tests/system/isctest/__init__.py @@ -9,17 +9,31 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from . import check -from . import instance -from . import hypothesis -from . import query -from . import kasp -from . import run -from . import template -from . import log -from . import vars # pylint: disable=redefined-builtin +from . import ( # pylint: disable=redefined-builtin + check, + hypothesis, + instance, + kasp, + log, + query, + run, + template, + vars, +) # isctest.mark module is intentionally NOT imported, because it relies on # environment variables which might not be set at the time of import of the # `isctest` package. To use the marks, manual `import isctest.mark` is needed # instead. + +__all__ = [ + "check", + "hypothesis", + "instance", + "kasp", + "log", + "query", + "run", + "template", + "vars", +] diff --git a/bin/tests/system/isctest/asyncserver.py b/bin/tests/system/isctest/asyncserver.py index 8e4ea245e5..080c08c380 100644 --- a/bin/tests/system/isctest/asyncserver.py +++ b/bin/tests/system/isctest/asyncserver.py @@ -11,21 +11,9 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator, Callable, Coroutine, Sequence from dataclasses import dataclass, field -from typing import ( - Any, - AsyncGenerator, - Callable, - Coroutine, - Dict, - List, - Optional, - Set, - Sequence, - Tuple, - Union, - cast, -) +from typing import Any, cast import abc import asyncio @@ -53,11 +41,10 @@ import dns.rdataset import dns.rdatatype import dns.rrset import dns.tsig -import dns.version import dns.zone _UdpHandler = Callable[ - [bytes, Tuple[str, int], asyncio.DatagramTransport], Coroutine[Any, Any, None] + [bytes, tuple[str, int], asyncio.DatagramTransport], Coroutine[Any, Any, None] ] @@ -75,7 +62,7 @@ class _AsyncUdpHandler(asyncio.DatagramProtocol): self, handler: _UdpHandler, ) -> None: - self._transport: Optional[asyncio.DatagramTransport] = None + self._transport: asyncio.DatagramTransport | None = None self._handler: _UdpHandler = handler def connection_made(self, transport: asyncio.BaseTransport) -> None: @@ -84,7 +71,7 @@ class _AsyncUdpHandler(asyncio.DatagramProtocol): """ self._transport = cast(asyncio.DatagramTransport, transport) - def datagram_received(self, data: bytes, addr: Tuple[str, int]) -> None: + def datagram_received(self, data: bytes, addr: tuple[str, int]) -> None: """ Called by asyncio when a datagram is received. """ @@ -109,9 +96,9 @@ class AsyncServer: def __init__( self, - udp_handler: Optional[_UdpHandler], - tcp_handler: Optional[_TcpHandler], - pidfile: Optional[str] = None, + udp_handler: _UdpHandler | None, + tcp_handler: _TcpHandler | None, + pidfile: str | None = None, ) -> None: logging.basicConfig( format="%(asctime)s %(levelname)8s %(message)s", @@ -133,12 +120,12 @@ class AsyncServer: logging.info("Setting up IPv4 listener at %s:%d", ipv4_address, port) logging.info("Setting up IPv6 listener at [%s]:%d", ipv6_address, port) - self._ip_addresses: Tuple[str, str] = (ipv4_address, ipv6_address) + self._ip_addresses: tuple[str, str] = (ipv4_address, ipv6_address) self._port: int = port - self._udp_handler: Optional[_UdpHandler] = udp_handler - self._tcp_handler: Optional[_TcpHandler] = tcp_handler - self._pidfile: Optional[str] = pidfile - self._work_done: Optional[asyncio.Future] = None + self._udp_handler: _UdpHandler | None = udp_handler + self._tcp_handler: _TcpHandler | None = tcp_handler + self._pidfile: str | None = pidfile + self._work_done: asyncio.Future | None = None def _get_ipv4_address_from_directory_name(self) -> str: containing_directory = pathlib.Path().absolute().stem @@ -186,7 +173,7 @@ class AsyncServer: loop.set_exception_handler(self._handle_exception) def _handle_exception( - self, _: asyncio.AbstractEventLoop, context: Dict[str, Any] + self, _: asyncio.AbstractEventLoop, context: dict[str, Any] ) -> None: assert self._work_done exception = context.get("exception", RuntimeError(context["message"])) @@ -269,15 +256,13 @@ class QueryContext: socket: Peer peer: Peer protocol: DnsProtocol - zone: Optional[dns.zone.Zone] = field(default=None, init=False) - soa: Optional[dns.rrset.RRset] = field(default=None, init=False) - node: Optional[dns.node.Node] = field(default=None, init=False) - answer: Optional[dns.rdataset.Rdataset] = field(default=None, init=False) - alias: Optional[dns.name.Name] = field(default=None, init=False) - _initialized_response: Optional[dns.message.Message] = field( - default=None, init=False - ) - _initialized_response_with_zone_data: Optional[dns.message.Message] = field( + zone: dns.zone.Zone | None = field(default=None, init=False) + soa: dns.rrset.RRset | None = field(default=None, init=False) + node: dns.node.Node | None = field(default=None, init=False) + answer: dns.rdataset.Rdataset | None = field(default=None, init=False) + alias: dns.name.Name | None = field(default=None, init=False) + _initialized_response: dns.message.Message | None = field(default=None, init=False) + _initialized_response_with_zone_data: dns.message.Message | None = field( default=None, init=False ) @@ -322,7 +307,7 @@ class ResponseAction(abc.ABC): """ @abc.abstractmethod - async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + async def perform(self) -> dns.message.Message | bytes | None: """ This method is expected to carry out arbitrary actions (e.g. wait for a specific amount of time, modify the answer, etc.) and then return the @@ -345,11 +330,11 @@ class DnsResponseSend(ResponseAction): """ response: dns.message.Message - authoritative: Optional[bool] = None + authoritative: bool | None = None delay: float = 0.0 acknowledge_hand_rolled_response: bool = False - async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + async def perform(self) -> dns.message.Message | bytes | None: """ Yield a potentially delayed response that is a dns.message.Message. """ @@ -395,7 +380,7 @@ class BytesResponseSend(ResponseAction): response: bytes delay: float = 0.0 - async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + async def perform(self) -> dns.message.Message | bytes | None: """ Yield a potentially delayed response that is a sequence of bytes. """ @@ -412,7 +397,7 @@ class ResponseDrop(ResponseAction): Action which does nothing - as if a packet was dropped. """ - async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + async def perform(self) -> dns.message.Message | bytes | None: return None @@ -430,7 +415,7 @@ class CloseConnection(ResponseAction): delay: float = 0.0 - async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + async def perform(self) -> dns.message.Message | bytes | None: if self.delay > 0: logging.info("Waiting %.1fs before closing TCP connection", self.delay) await asyncio.sleep(self.delay) @@ -512,7 +497,7 @@ class IgnoreAllConnections(ConnectionHandler): client socket, effectively ignoring all incoming connections. """ - _connections: Set[asyncio.StreamWriter] = field(default_factory=set) + _connections: set[asyncio.StreamWriter] = field(default_factory=set) async def handle( self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter, peer: Peer @@ -623,14 +608,14 @@ class QnameHandler(ResponseHandler): @property @abc.abstractmethod - def qnames(self) -> List[str]: + def qnames(self) -> list[str]: """ A list of QNAMEs handled by this class. """ raise NotImplementedError def __init__(self) -> None: - self._qnames: List[dns.name.Name] = [dns.name.from_text(d) for d in self.qnames] + self._qnames: list[dns.name.Name] = [dns.name.from_text(d) for d in self.qnames] def __str__(self) -> str: return f"{self.__class__.__name__}(QNAMEs: {', '.join(self.qnames)})" @@ -653,7 +638,7 @@ class QnameQtypeHandler(QnameHandler): @property @abc.abstractmethod - def qtypes(self) -> List[dns.rdatatype.RdataType]: + def qtypes(self) -> list[dns.rdatatype.RdataType]: """ A list of QTYPEs handled by this class. """ @@ -661,7 +646,7 @@ class QnameQtypeHandler(QnameHandler): def __init__(self) -> None: super().__init__() - self._qtypes: List[dns.rdatatype.RdataType] = self.qtypes + self._qtypes: list[dns.rdatatype.RdataType] = self.qtypes def __str__(self) -> str: return f"{self.__class__.__name__}(QNAMEs: {', '.join(self.qnames)}; QTYPEs: {', '.join(map(str, self.qtypes))})" @@ -687,7 +672,7 @@ class StaticResponseHandler(ResponseHandler): """ @property - def rcode(self) -> Optional[dns.rcode.Rcode]: + def rcode(self) -> dns.rcode.Rcode | None: """ Optional RCODE to be set in the response. """ @@ -715,7 +700,7 @@ class StaticResponseHandler(ResponseHandler): return [] @property - def authoritative(self) -> Optional[bool]: + def authoritative(self) -> bool | None: """ Whether to set the AA bit in the response. """ @@ -755,17 +740,17 @@ class DomainHandler(ResponseHandler): @property @abc.abstractmethod - def domains(self) -> List[str]: + def domains(self) -> list[str]: """ A list of domain names handled by this class. """ raise NotImplementedError def __init__(self) -> None: - self._domains: List[dns.name.Name] = sorted( + self._domains: list[dns.name.Name] = sorted( [dns.name.from_text(d) for d in self.domains], reverse=True ) - self._matched_domain: Optional[dns.name.Name] = None + self._matched_domain: dns.name.Name | None = None @property def matched_domain(self) -> dns.name.Name: @@ -833,7 +818,7 @@ class ForwarderHandler(ResponseHandler): logging.debug("[OUT] %s", self._query.hex()) cast(asyncio.DatagramTransport, transport).sendto(self._query) - def datagram_received(self, data: bytes, _: Tuple[str, int]) -> None: + def datagram_received(self, data: bytes, _: tuple[str, int]) -> None: logging.debug("[IN] %s", data.hex()) self._response.set_result(data) @@ -896,8 +881,8 @@ class _ZoneTreeNode: A node representing a zone with one origin. """ - zone: Optional[dns.zone.Zone] - children: List["_ZoneTreeNode"] = field(default_factory=list) + zone: dns.zone.Zone | None + children: list["_ZoneTreeNode"] = field(default_factory=list) class _ZoneTree: @@ -947,7 +932,7 @@ class _ZoneTree: node_from.children.remove(child) node_to.children.append(child) - def find_best_zone(self, name: dns.name.Name) -> Optional[dns.zone.Zone]: + def find_best_zone(self, name: dns.name.Name) -> dns.zone.Zone | None: """ Return the closest matching zone (if any) for the domain name. """ @@ -965,7 +950,7 @@ class _DnsMessageWithTsigDisabled(dns.message.Message): """ class _DisableTsigHandling(contextlib.ContextDecorator): - def __init__(self, message: Optional[dns.message.Message] = None) -> None: + def __init__(self, message: dns.message.Message | None = None) -> None: self.original_tsig_sign = dns.tsig.sign self.original_tsig_validate = dns.tsig.validate if message: @@ -977,7 +962,7 @@ class _DnsMessageWithTsigDisabled(dns.message.Message): from failing on messages initialized with `dns.message.from_wire(keyring=False)`. """ - def sign(*_: Any, **__: Any) -> Tuple[dns.rdata.Rdata, None]: + def sign(*_: Any, **__: Any) -> tuple[dns.rdata.Rdata, None]: assert self.tsig return self.tsig[0], None @@ -1054,16 +1039,16 @@ class AsyncDnsServer(AsyncServer): /, default_rcode: dns.rcode.Rcode = dns.rcode.REFUSED, default_aa: bool = False, - keyring: Union[ - Dict[dns.name.Name, dns.tsig.Key], None, _NoKeyringType - ] = _NoKeyringType(), + keyring: ( + dict[dns.name.Name, dns.tsig.Key] | None | _NoKeyringType + ) = _NoKeyringType(), acknowledge_manual_dname_handling: bool = False, ) -> None: super().__init__(self._handle_udp, self._handle_tcp, "ans.pid") self._zone_tree: _ZoneTree = _ZoneTree() - self._connection_handler: Optional[ConnectionHandler] = None - self._response_handlers: List[ResponseHandler] = [] + self._connection_handler: ConnectionHandler | None = None + self._response_handlers: list[ResponseHandler] = [] self._default_rcode = default_rcode self._default_aa = default_aa self._keyring = keyring @@ -1172,7 +1157,7 @@ class AsyncDnsServer(AsyncServer): raise ValueError(error) async def _handle_udp( - self, wire: bytes, addr: Tuple[str, int], transport: asyncio.DatagramTransport + self, wire: bytes, addr: tuple[str, int], transport: asyncio.DatagramTransport ) -> None: logging.debug("Received UDP message: %s", wire.hex()) socket_info = transport.get_extra_info("sockname") @@ -1215,7 +1200,7 @@ class AsyncDnsServer(AsyncServer): async def _read_tcp_query( self, reader: asyncio.StreamReader, peer: Peer - ) -> Optional[bytes]: + ) -> bytes | None: wire_length = await self._read_tcp_query_wire_length(reader, peer) if not wire_length: return None @@ -1224,7 +1209,7 @@ class AsyncDnsServer(AsyncServer): async def _read_tcp_query_wire_length( self, reader: asyncio.StreamReader, peer: Peer - ) -> Optional[int]: + ) -> int | None: logging.debug("Receiving TCP message length from %s...", peer) wire_length_bytes = await self._read_tcp_octets(reader, peer, 2) @@ -1237,7 +1222,7 @@ class AsyncDnsServer(AsyncServer): async def _read_tcp_query_wire( self, reader: asyncio.StreamReader, peer: Peer, wire_length: int - ) -> Optional[bytes]: + ) -> bytes | None: logging.debug("Receiving TCP message (%d octets) from %s...", wire_length, peer) wire = await self._read_tcp_octets(reader, peer, wire_length) @@ -1250,7 +1235,7 @@ class AsyncDnsServer(AsyncServer): async def _read_tcp_octets( self, reader: asyncio.StreamReader, peer: Peer, expected: int - ) -> Optional[bytes]: + ) -> bytes | None: buffer = b"" while len(buffer) < expected: @@ -1299,7 +1284,7 @@ class AsyncDnsServer(AsyncServer): ) def _log_response( - self, qctx: QueryContext, response: Optional[Union[dns.message.Message, bytes]] + self, qctx: QueryContext, response: dns.message.Message | bytes | None ) -> None: if not response: logging.info( @@ -1399,7 +1384,7 @@ class AsyncDnsServer(AsyncServer): async def _prepare_responses( self, qctx: QueryContext - ) -> AsyncGenerator[Optional[Union[dns.message.Message, bytes]], None]: + ) -> AsyncGenerator[dns.message.Message | bytes | None, None]: """ Yield response(s) either from response handlers or zone data. """ @@ -1592,7 +1577,7 @@ class ControllableAsyncDnsServer(AsyncDnsServer): return dns.name.from_text(self._CONTROL_DOMAIN) @functools.cached_property - def _commands(self) -> Dict[dns.name.Name, "ControlCommand"]: + def _commands(self) -> dict[dns.name.Name, "ControlCommand"]: return {} def install_control_commands(self, *commands: "ControlCommand") -> None: @@ -1613,7 +1598,7 @@ class ControllableAsyncDnsServer(AsyncDnsServer): async def _prepare_responses( self, qctx: QueryContext - ) -> AsyncGenerator[Optional[Union[dns.message.Message, bytes]], None]: + ) -> AsyncGenerator[dns.message.Message | bytes | None, None]: """ Detect and handle control queries, falling back to normal processing for non-control queries. @@ -1626,9 +1611,7 @@ class ControllableAsyncDnsServer(AsyncDnsServer): async for response in super()._prepare_responses(qctx): yield response - def _handle_control_command( - self, qctx: QueryContext - ) -> Optional[dns.message.Message]: + def _handle_control_command(self, qctx: QueryContext) -> dns.message.Message | None: """ Detect and handle control queries. @@ -1703,8 +1686,8 @@ class ControlCommand(abc.ABC): @abc.abstractmethod def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext - ) -> Optional[str]: + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> str | None: """ This method is expected to carry out arbitrary actions in response to a control query. Note that it is invoked synchronously (it is not a @@ -1742,11 +1725,11 @@ class ToggleResponsesCommand(ControlCommand): control_subdomain = "send-responses" def __init__(self) -> None: - self._current_handler: Optional[IgnoreAllQueries] = None + self._current_handler: IgnoreAllQueries | None = None def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext - ) -> Optional[str]: + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> str | None: if len(args) != 1: logging.error("Invalid %s query %s", self, qctx.qname) qctx.response.set_rcode(dns.rcode.SERVFAIL) @@ -1785,12 +1768,12 @@ class SwitchControlCommand(ControlCommand): control_subdomain = "switch" - def __init__(self, handler_mapping: Dict[str, Sequence[ResponseHandler]]): + def __init__(self, handler_mapping: dict[str, Sequence[ResponseHandler]]): self._handler_mapping = handler_mapping def handle( - self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext - ) -> Optional[str]: + self, args: list[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> str | None: if len(args) != 1 or args[0] not in self._handler_mapping: logging.error("Invalid %s query %s", self, qctx.qname) qctx.response.set_rcode(dns.rcode.SERVFAIL) diff --git a/bin/tests/system/isctest/check.py b/bin/tests/system/isctest/check.py index d6a222aded..6dbf6bca26 100644 --- a/bin/tests/system/isctest/check.py +++ b/bin/tests/system/isctest/check.py @@ -9,15 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from typing import cast + import difflib import shutil -from typing import cast, List, Optional + +from dns.edns import EDECode, EDEOption import dns.edns -from dns.edns import EDECode, EDEOption import dns.flags import dns.message import dns.rcode +import dns.rrset import dns.zone import isctest.log @@ -69,10 +72,10 @@ def noraflag(message: dns.message.Message) -> None: def _extract_ede_options( message: dns.message.Message, -) -> List[EDEOption]: +) -> list[EDEOption]: """Extract EDE options from the DNS message.""" return cast( - List[EDEOption], + list[EDEOption], [ option for option in message.options @@ -87,9 +90,7 @@ def noede(message: dns.message.Message) -> None: assert not ede_options, f"unexpected EDE options {ede_options} in {message}" -def ede( - message: dns.message.Message, code: EDECode, text: Optional[str] = None -) -> None: +def ede(message: dns.message.Message, code: EDECode, text: str | None = None) -> None: """Check if message contains expected EDE code (and its text).""" msg_opts = _extract_ede_options(message) matching_opts = [opt for opt in msg_opts if opt.code == code] @@ -135,7 +136,7 @@ def same_answer(res1: dns.message.Message, res2: dns.message.Message): def rrsets_equal( first_rrset: dns.rrset.RRset, second_rrset: dns.rrset.RRset, - compare_ttl: Optional[bool] = False, + compare_ttl: bool | None = False, ) -> None: """Compare two RRset (optionally including TTL)""" @@ -164,7 +165,7 @@ def rrsets_equal( def zones_equal( first_zone: dns.zone.Zone, second_zone: dns.zone.Zone, - compare_ttl: Optional[bool] = False, + compare_ttl: bool | None = False, ) -> None: """Compare two zones (optionally including TTL)""" diff --git a/bin/tests/system/isctest/hypothesis/__init__.py b/bin/tests/system/isctest/hypothesis/__init__.py index 6c2cc00210..7123496b53 100644 --- a/bin/tests/system/isctest/hypothesis/__init__.py +++ b/bin/tests/system/isctest/hypothesis/__init__.py @@ -9,8 +9,9 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# This ensures we're using a suitable hypothesis version. A newer version is -# required for FIPS-enabled platforms. +from . import settings, strategies -from . import settings -from . import strategies +__all__ = [ + "settings", + "strategies", +] diff --git a/bin/tests/system/isctest/hypothesis/strategies.py b/bin/tests/system/isctest/hypothesis/strategies.py index e8badc6802..e5355eb3e0 100644 --- a/bin/tests/system/isctest/hypothesis/strategies.py +++ b/bin/tests/system/isctest/hypothesis/strategies.py @@ -11,10 +11,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import collections.abc -from typing import List, Union from warnings import warn +import collections.abc + from hypothesis.strategies import ( binary, builds, @@ -27,7 +27,6 @@ from hypothesis.strategies import ( ) import dns.name -import dns.message import dns.rdataclass import dns.rdatatype @@ -39,9 +38,7 @@ def dns_names( draw, *, prefix: dns.name.Name = dns.name.empty, - suffix: Union[ - dns.name.Name, collections.abc.Iterable[dns.name.Name] - ] = dns.name.root, + suffix: dns.name.Name | collections.abc.Iterable[dns.name.Name] = dns.name.root, min_labels: int = 1, max_labels: int = 128, ) -> dns.name.Name: @@ -155,7 +152,7 @@ dns_rdatatypes_without_meta = integers(0, dns.rdatatype.OPT - 1) | integers(dns. @composite def _partition_bytes_to_labels( draw, remaining_bytes: int, number_of_labels: int -) -> List[int]: +) -> list[int]: two_bytes_reserved_for_label = 2 # Reserve two bytes for each label diff --git a/bin/tests/system/isctest/instance.py b/bin/tests/system/isctest/instance.py index 129a2a907a..2786f66e5d 100644 --- a/bin/tests/system/isctest/instance.py +++ b/bin/tests/system/isctest/instance.py @@ -11,18 +11,19 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import List, NamedTuple, Optional +from pathlib import Path +from typing import NamedTuple import os -from pathlib import Path import re -import dns.update +import dns.exception import dns.rcode +import dns.update -from .log import debug, WatchLogFromStart, WatchLogFromHere -from .run import CmdResult, EnvCmd, perl +from .log import WatchLogFromHere, WatchLogFromStart, debug from .query import udp +from .run import CmdResult, EnvCmd, perl from .text import TextFile @@ -53,8 +54,8 @@ class NamedInstance: def __init__( self, identifier: str, - num: Optional[int] = None, - ports: Optional[NamedPorts] = None, + num: int | None = None, + ports: NamedPorts | None = None, ) -> None: """ `identifier` is the name of the instance's directory @@ -94,7 +95,7 @@ class NamedInstance: return f"10.53.0.{self.num}" @staticmethod - def _identifier_to_num(identifier: str, num: Optional[int] = None) -> int: + def _identifier_to_num(identifier: str, num: int | None = None) -> int: regex_match = re.match(r"^ns(?P[0-9]{1,2})$", identifier) if not regex_match: if num is None: @@ -175,7 +176,7 @@ class NamedInstance: watcher.wait_for_line("all zones loaded") return cmd - def stop(self, args: Optional[List[str]] = None) -> None: + def stop(self, args: list[str] | None = None) -> None: """Stop the instance.""" args = args or [] perl( @@ -183,7 +184,7 @@ class NamedInstance: [self.system_test_name, self.identifier] + args, ) - def start(self, args: Optional[List[str]] = None) -> None: + def start(self, args: list[str] | None = None) -> None: """Start the instance.""" args = args or [] perl( diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 950a8d994f..e1f8bc5120 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -11,26 +11,33 @@ from datetime import datetime, timedelta, timezone from functools import total_ordering +from pathlib import Path +from re import compile as Re + import glob import os -from pathlib import Path import re -from re import compile as Re import time -from typing import Dict, List, Optional, Tuple, Union -import dns import dns.dnssec +import dns.exception +import dns.message +import dns.name +import dns.rcode +import dns.rdataclass import dns.rdatatype import dns.rrset import dns.tsig +import dns.zone +import dns.zonefile + +from isctest.instance import NamedInstance +from isctest.template import TrustAnchor +from isctest.vars.algorithms import ALL_ALGORITHMS_BY_NUM, Algorithm import isctest.log import isctest.query import isctest.util -from isctest.instance import NamedInstance -from isctest.template import TrustAnchor -from isctest.vars.algorithms import Algorithm, ALL_ALGORITHMS_BY_NUM DEFAULT_TTL = 300 @@ -84,24 +91,24 @@ def Iret(config, zsk=True, ksk=False, rollover=True, smooth=True): sign_delay = config["signatures-validity"] - config["signatures-refresh"] safety_interval = config["retire-safety"] - iretKSK = timedelta(0) + iret_ksk = timedelta(0) if ksk: # KSK: Double-KSK Method: Iret = DprpP + TTLds - iretKSK = ( + iret_ksk = ( config["parent-propagation-delay"] + config["ds-ttl"] + safety_interval ) - iretZSK = timedelta(0) + iret_zsk = timedelta(0) if zsk: # ZSK: Pre-Publication Method: Iret = Dsgn + Dprp + TTLsig - iretZSK = ( + iret_zsk = ( sign_delay + config["zone-propagation-delay"] + config["max-zone-ttl"] + safety_interval ) - return max(iretKSK, iretZSK) + return max(iret_ksk, iret_zsk) @total_ordering @@ -130,26 +137,26 @@ class KeyTimingMetadata: def __str__(self) -> str: return self.value.strftime(self.FORMAT) - def __add__(self, other: Union[timedelta, int]): + def __add__(self, other: timedelta | int): if isinstance(other, int): other = timedelta(seconds=other) result = KeyTimingMetadata.__new__(KeyTimingMetadata) result.value = self.value + other return result - def __sub__(self, other: Union[timedelta, int]): + def __sub__(self, other: timedelta | int): if isinstance(other, int): other = timedelta(seconds=other) result = KeyTimingMetadata.__new__(KeyTimingMetadata) result.value = self.value - other return result - def __iadd__(self, other: Union[timedelta, int]): + def __iadd__(self, other: timedelta | int): if isinstance(other, int): other = timedelta(seconds=other) self.value += other - def __isub__(self, other: Union[timedelta, int]): + def __isub__(self, other: timedelta | int): if isinstance(other, int): other = timedelta(seconds=other) self.value -= other @@ -176,7 +183,7 @@ class KeyProperties: self, name: str, metadata: dict, - timing: Dict[str, KeyTimingMetadata], + timing: dict[str, KeyTimingMetadata], private: bool = True, legacy: bool = False, role: str = "csk", @@ -184,7 +191,7 @@ class KeyProperties: flags: int = 257, keytag_min: int = 0, keytag_max: int = 65535, - offset: Union[timedelta, int] = 0, + offset: timedelta | int = 0, ): self.name = name self.key = None @@ -215,7 +222,7 @@ class KeyProperties: "KSK": "yes", "ZSK": "yes", } - timing: Dict[str, KeyTimingMetadata] = {} + timing: dict[str, KeyTimingMetadata] = {} result = KeyProperties(name="DEFAULT", metadata=metadata, timing=timing) result.name = "DEFAULT" @@ -322,7 +329,7 @@ class Key: operations for KASP tests. """ - def __init__(self, name: str, keydir: Optional[Union[str, Path]] = None): + def __init__(self, name: str, keydir: str | Path | None = None): self.name = name if keydir is None: self.keydir = Path() @@ -337,7 +344,7 @@ class Key: def get_timing( self, metadata: str, must_exist: bool = True - ) -> Optional[KeyTimingMetadata]: + ) -> KeyTimingMetadata | None: regex = rf";\s+{metadata}:\s+(\d+).*" with open(self.keyfile, "r", encoding="utf-8") as file: for line in file: @@ -377,7 +384,7 @@ class Key: def get_signing_state( self, offline_ksk=False, zsk_missing=False, smooth=False - ) -> Tuple[bool, bool]: + ) -> tuple[bool, bool]: """ This returns the signing state derived from the key states, KRRSIGState and ZRRSIGState. @@ -575,14 +582,10 @@ class Key: isctest.log.debug(f"{self.name} {key} TIMING UNEXPECTED: {value}") return value == "undefined" - def match_properties(self, zone, properties): + def _check_public_key_file(self, zone, properties): """ - Check the key with given properties. + Check the public key file. """ - # Check file existence. - # Noop. If file is missing then the get_metadata calls will fail. - - # Check the public key file. role = properties.role_full() comment = f"This is a {role} key, keyid {self.tag}, for {zone}." if not isctest.util.file_contents_contain(self.keyfile, comment): @@ -597,31 +600,45 @@ class Key: isctest.log.debug(f"{self.name} DNSKEY MISMATCH: expected '{dnskey}'") return False - # Now check the private key file. - if properties.private: - # Retrieve creation date. - created = self.get_metadata("Generated") + return True - pval = self.get_metadata("Created", file=self.privatefile) - if pval != created: - isctest.log.debug( - f"{self.name} Created METADATA MISMATCH: {pval} - {created}" - ) - return False - pval = self.get_metadata("Private-key-format", file=self.privatefile) - if pval != "v1.3": - isctest.log.debug( - f"{self.name} Private-key-format METADATA MISMATCH: {pval} - v1.3" - ) - return False - pval = self.get_metadata("Algorithm", file=self.privatefile) - if pval != f"{alg}": - isctest.log.debug( - f"{self.name} Algorithm METADATA MISMATCH: {pval} - {alg}" - ) - return False + def _check_private_key_file(self, properties): + """ + Check the private key file. + """ + if not properties.private: + return True - # Now check the key state file. + alg = properties.metadata["Algorithm"] + + # Retrieve creation date. + created = self.get_metadata("Generated") + + pval = self.get_metadata("Created", file=self.privatefile) + if pval != created: + isctest.log.debug( + f"{self.name} Created METADATA MISMATCH: {pval} - {created}" + ) + return False + pval = self.get_metadata("Private-key-format", file=self.privatefile) + if pval != "v1.3": + isctest.log.debug( + f"{self.name} Private-key-format METADATA MISMATCH: {pval} - v1.3" + ) + return False + pval = self.get_metadata("Algorithm", file=self.privatefile) + if pval != f"{alg}": + isctest.log.debug( + f"{self.name} Algorithm METADATA MISMATCH: {pval} - {alg}" + ) + return False + + return True + + def _check_key_state_file(self, zone, properties): + """ + Check the key state file. + """ if properties.legacy: return True @@ -652,7 +669,24 @@ class Key: if self.tag > properties.keytag_max: return False - # A match is found. + return True + + def match_properties(self, zone, properties): + """ + Check the key with given properties. + """ + # Check file existence. + # Noop. If file is missing then the get_metadata calls will fail. + + if not self._check_public_key_file(zone, properties): + return False + + if not self._check_private_key_file(properties): + return False + + if not self._check_key_state_file(zone, properties): + return False + return True def match_timingmetadata(self, timings, file=None, comment=False): @@ -1474,8 +1508,8 @@ def next_key_event_equals(server, zone, next_event): def keydir_to_keylist( - zone: Optional[str], keydir: Optional[str] = None, in_use: bool = False -) -> List[Key]: + zone: str | None, keydir: str | None = None, in_use: bool = False +) -> list[Key]: """ Retrieve all keys from the key files in a directory. If 'zone' is None, retrieve all keys in the directory, otherwise only those matching the @@ -1515,11 +1549,11 @@ def keydir_to_keylist( return [k for k in all_keys if used(k)] -def keystr_to_keylist(keystr: str, keydir: Optional[str] = None) -> List[Key]: +def keystr_to_keylist(keystr: str, keydir: str | None = None) -> list[Key]: return [Key(name, keydir) for name in keystr.split()] -def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]: +def policy_to_properties(ttl, keys: list[str]) -> list[KeyProperties]: """ Get the policies from a list of specially formatted strings. The splitted line should result in the following items: @@ -1541,8 +1575,8 @@ def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]: line = key.split() # defaults - metadata: Dict[str, Union[str, int]] = {} - timing: Dict[str, KeyTimingMetadata] = {} + metadata: dict[str, str | int] = {} + timing: dict[str, KeyTimingMetadata] = {} private = True legacy = False keytag_min = 0 diff --git a/bin/tests/system/isctest/log/__init__.py b/bin/tests/system/isctest/log/__init__.py index 228f69e5bf..ea801b5bd6 100644 --- a/bin/tests/system/isctest/log/__init__.py +++ b/bin/tests/system/isctest/log/__init__.py @@ -11,16 +11,31 @@ from .basic import ( avoid_duplicated_logs, + critical, + debug, deinit_module_logger, deinit_test_logger, + error, + info, init_conftest_logger, init_module_logger, init_test_logger, - debug, - info, warning, - error, - critical, ) +from .watchlog import WatchLogFromHere, WatchLogFromStart -from .watchlog import WatchLogFromStart, WatchLogFromHere +__all__ = [ + "WatchLogFromHere", + "WatchLogFromStart", + "avoid_duplicated_logs", + "critical", + "debug", + "deinit_module_logger", + "deinit_test_logger", + "error", + "info", + "init_conftest_logger", + "init_module_logger", + "init_test_logger", + "warning", +] diff --git a/bin/tests/system/isctest/log/basic.py b/bin/tests/system/isctest/log/basic.py index 812e83e254..981049b626 100644 --- a/bin/tests/system/isctest/log/basic.py +++ b/bin/tests/system/isctest/log/basic.py @@ -9,19 +9,19 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import logging from pathlib import Path + +import logging import textwrap -from typing import Dict, Optional LOG_FORMAT = "%(asctime)s %(levelname)7s:%(name)s %(message)s" LOG_INDENT = 4 -LOGGERS = { +LOGGERS: dict[str, logging.Logger | None] = { "conftest": None, "module": None, "test": None, -} # type: Dict[str, Optional[logging.Logger]] +} def init_conftest_logger(): diff --git a/bin/tests/system/isctest/log/watchlog.py b/bin/tests/system/isctest/log/watchlog.py index d7154995b7..22f81b94fa 100644 --- a/bin/tests/system/isctest/log/watchlog.py +++ b/bin/tests/system/isctest/log/watchlog.py @@ -9,16 +9,17 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import Any, List, Match, Optional, Pattern, TextIO, TypeVar, Union +from re import Match, Pattern +from typing import Any, TextIO, TypeAlias, TypeVar import abc import os import time -from isctest.text import compile_pattern, FlexPattern, LineReader +from isctest.text import FlexPattern, LineReader, compile_pattern T = TypeVar("T") -OneOrMore = Union[T, List[T]] +OneOrMore: TypeAlias = T | list[T] class WatchLogException(Exception): @@ -62,8 +63,8 @@ class WatchLog(abc.ABC): ... isctest.log.watchlog.WatchLogException: timeout must be greater than 0 """ - self._fd: Optional[TextIO] = None - self._reader: Optional[LineReader] = None + self._fd: TextIO | None = None + self._reader: LineReader | None = None self._path = path self._wait_function_called = False if timeout <= 0.0: @@ -71,12 +72,12 @@ class WatchLog(abc.ABC): self._timeout = timeout self._deadline = 0.0 - def _setup_wait(self, patterns: OneOrMore[FlexPattern]) -> List[Pattern]: + def _setup_wait(self, patterns: OneOrMore[FlexPattern]) -> list[Pattern]: self._wait_function_called = True self._deadline = time.monotonic() + self._timeout return self._prepare_patterns(patterns) - def _prepare_patterns(self, strings: OneOrMore[FlexPattern]) -> List[Pattern]: + def _prepare_patterns(self, strings: OneOrMore[FlexPattern]) -> list[Pattern]: """ Convert a mix of string(s) and/or pattern(s) into a list of patterns. @@ -90,7 +91,7 @@ class WatchLog(abc.ABC): patterns.append(compile_pattern(string)) return patterns - def _wait_for_match(self, regexes: List[Pattern]) -> Match: + def _wait_for_match(self, regexes: list[Pattern]) -> Match: if not self._reader: raise WatchLogException( "use WatchLog as context manager before calling wait_for_*() functions" @@ -209,7 +210,7 @@ class WatchLog(abc.ABC): return self._wait_for_match(regexes) - def wait_for_sequence(self, patterns: List[FlexPattern]) -> List[Match]: + def wait_for_sequence(self, patterns: list[FlexPattern]) -> list[Match]: """ Block execution until the specified pattern sequence is found in the log file. @@ -285,7 +286,7 @@ class WatchLog(abc.ABC): return matches - def wait_for_all(self, patterns: List[FlexPattern]) -> List[Match]: + def wait_for_all(self, patterns: list[FlexPattern]) -> list[Match]: """ Block execution until all the specified patterns are found in the log file in any order. diff --git a/bin/tests/system/isctest/mark.py b/bin/tests/system/isctest/mark.py index 4d7fcce147..81f3774972 100644 --- a/bin/tests/system/isctest/mark.py +++ b/bin/tests/system/isctest/mark.py @@ -11,11 +11,12 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import os from pathlib import Path + +import os import platform -import socket import shutil +import socket import subprocess import pytest diff --git a/bin/tests/system/isctest/name.py b/bin/tests/system/isctest/name.py index cc836f85db..02b43059a7 100644 --- a/bin/tests/system/isctest/name.py +++ b/bin/tests/system/isctest/name.py @@ -9,14 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import Iterable, FrozenSet - -import dns.name -import dns.zone -import dns.rdatatype +from collections.abc import Iterable from dns.name import Name +import dns.name +import dns.rdatatype +import dns.zone + def prepend_label(label: str, name: Name) -> Name: return Name((label,) + name.labels) @@ -26,7 +26,7 @@ def len_wire_uncompressed(name: Name) -> int: return len(name) + sum(map(len, name.labels)) -def get_wildcard_names(names: Iterable[Name]) -> FrozenSet[Name]: +def get_wildcard_names(names: Iterable[Name]) -> frozenset[Name]: return frozenset(name for name in names if name.is_wild()) @@ -84,7 +84,7 @@ class ZoneAnalyzer: .union(self.reachable_dnames) ) - def get_names_with_type(self, rdtype) -> FrozenSet[Name]: + def get_names_with_type(self, rdtype) -> frozenset[Name]: return frozenset( name for name in self.zone if self.zone.get_rdataset(name, rdtype) ) @@ -148,7 +148,7 @@ class ZoneAnalyzer: self.reachable_delegations = frozenset(reachable_delegations) self.occluded = frozenset(occluded) - def generate_ents(self) -> FrozenSet[Name]: + def generate_ents(self) -> frozenset[Name]: """ Generate reachable names of empty nodes "between" all reachable names with a RR and the origin. diff --git a/bin/tests/system/isctest/query.py b/bin/tests/system/isctest/query.py index daa8ade014..57af8254c9 100644 --- a/bin/tests/system/isctest/query.py +++ b/bin/tests/system/isctest/query.py @@ -9,12 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from collections.abc import Callable +from typing import Any + import os import time -from typing import Any, Callable, Optional -import dns.query +import dns.exception +import dns.flags import dns.message +import dns.query +import dns.rcode +import dns.rdataclass import isctest.log @@ -25,11 +31,11 @@ def generic_query( query_func: Callable[..., Any], message: dns.message.Message, ip: str, - port: Optional[int] = None, - source: Optional[str] = None, + port: int | None = None, + source: str | None = None, timeout: int = QUERY_TIMEOUT, attempts: int = 10, - expected_rcode: Optional[dns.rcode.Rcode] = None, + expected_rcode: dns.rcode.Rcode | None = None, verify: bool = False, log_query: bool = True, log_response: bool = True, diff --git a/bin/tests/system/isctest/run.py b/bin/tests/system/isctest/run.py index 65fd5ec8df..4e11c71ba0 100644 --- a/bin/tests/system/isctest/run.py +++ b/bin/tests/system/isctest/run.py @@ -9,11 +9,11 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import os from pathlib import Path + +import os import subprocess import time -from typing import List, Optional import isctest.log import isctest.text @@ -39,9 +39,9 @@ def cmd( stderr=subprocess.PIPE, log_stdout=True, log_stderr=True, - input_text: Optional[bytes] = None, + input_text: bytes | None = None, raise_on_exception=True, - env: Optional[dict] = None, + env: dict | None = None, ) -> CmdResult: """Execute a command with given args as subprocess.""" isctest.log.debug(f"isctest.run.cmd(): {' '.join(args)}") @@ -97,7 +97,7 @@ class EnvCmd: def _run_script( interpreter: str, script: str, - args: Optional[List[str]] = None, + args: list[str] | None = None, ): if args is None: args = [] @@ -129,12 +129,12 @@ def _run_script( isctest.log.debug(" exited with %d", returncode) -def shell(script: str, args: Optional[List[str]] = None) -> None: +def shell(script: str, args: list[str] | None = None) -> None: """Run a given script with system's shell interpreter.""" _run_script(os.environ["SHELL"], script, args) -def perl(script: str, args: Optional[List[str]] = None) -> None: +def perl(script: str, args: list[str] | None = None) -> None: """Run a given script with system's perl interpreter.""" _run_script(os.environ["PERL"], script, args) diff --git a/bin/tests/system/isctest/template.py b/bin/tests/system/isctest/template.py index f454dca7d0..118565e3f7 100644 --- a/bin/tests/system/isctest/template.py +++ b/bin/tests/system/isctest/template.py @@ -13,7 +13,7 @@ from dataclasses import dataclass from pathlib import Path -from typing import Any, Dict, Optional, Union +from typing import Any import jinja2 @@ -26,7 +26,7 @@ class TemplateEngine: Engine for rendering jinja2 templates in system test directories. """ - def __init__(self, directory: Union[str, Path], env_vars=ALL): + def __init__(self, directory: str | Path, env_vars=ALL): """ Initialize the template engine for `directory`, optionally overriding the `env_vars` that will be used when rendering the templates (defaults @@ -44,8 +44,8 @@ class TemplateEngine: def render( self, output: str, - data: Optional[Dict[str, Any]] = None, - template: Optional[str] = None, + data: dict[str, Any] | None = None, + template: str | None = None, ) -> None: """ Render `output` file from jinja `template` and fill in the `data`. The @@ -69,7 +69,7 @@ class TemplateEngine: stream = self.j2env.get_template(template).stream(data) stream.dump(output, encoding="utf-8") - def render_auto(self, data: Optional[Dict[str, Any]] = None): + def render_auto(self, data: dict[str, Any] | None = None): """ Render all *.j2 templates with default (and optionally the provided) values and write the output to files without the .j2 extensions. diff --git a/bin/tests/system/isctest/text.py b/bin/tests/system/isctest/text.py index 33798c3703..a60c1bbae3 100644 --- a/bin/tests/system/isctest/text.py +++ b/bin/tests/system/isctest/text.py @@ -11,12 +11,15 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from collections.abc import Iterator +from re import Match, Pattern +from re import compile as Re +from typing import TextIO + import abc import re -from re import compile as Re -from typing import Iterator, List, Match, Optional, Pattern, TextIO, Union -FlexPattern = Union[str, Pattern] +FlexPattern = str | Pattern def compile_pattern(string: FlexPattern) -> Pattern: @@ -47,7 +50,7 @@ class Grep(abc.ABC): if match: yield match - def grep(self, pattern: FlexPattern) -> List[Match]: + def grep(self, pattern: FlexPattern) -> list[Match]: """ Get list of lines matching the pattern. """ @@ -149,7 +152,7 @@ class LineReader(Grep): self._stream = stream self._linebuf = "" - def readline(self) -> Optional[str]: + def readline(self) -> str | None: """ Wrapper around io.readline() function to handle unfinished lines. diff --git a/bin/tests/system/isctest/util.py b/bin/tests/system/isctest/util.py index eec03ae724..7ffce13b8e 100644 --- a/bin/tests/system/isctest/util.py +++ b/bin/tests/system/isctest/util.py @@ -9,6 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +import dns.rrset import dns.zone import pytest diff --git a/bin/tests/system/isctest/vars/__init__.py b/bin/tests/system/isctest/vars/__init__.py index 3ebaf3df5e..f1bdc21d72 100644 --- a/bin/tests/system/isctest/vars/__init__.py +++ b/bin/tests/system/isctest/vars/__init__.py @@ -11,19 +11,29 @@ import os -from .all import ALL -from .algorithms import init_crypto_supported, set_algorithm_set -from .features import init_features -from .openssl import parse_openssl_config from .. import log +from . import algorithms, autoconf, basic, dirs, features, openssl, ports +from .all import ALL + +__all__ = [ + "ALL", + "algorithms", + "autoconf", + "basic", + "dirs", + "features", + "init_vars", + "openssl", + "ports", +] def init_vars(): """Initializes the environment variables.""" - init_features() - init_crypto_supported() - set_algorithm_set(os.getenv("ALGORITHM_SET")) - parse_openssl_config(ALL["OPENSSL_CONF"]) + features.init_features() + algorithms.init_crypto_supported() + algorithms.set_algorithm_set(os.getenv("ALGORITHM_SET")) + openssl.parse_openssl_config(ALL["OPENSSL_CONF"]) os.environ.update(ALL) log.debug("setting following env vars: %s", ", ".join([str(key) for key in ALL])) diff --git a/bin/tests/system/isctest/vars/algorithms.py b/bin/tests/system/isctest/vars/algorithms.py index 446ab09d69..ac8605896a 100644 --- a/bin/tests/system/isctest/vars/algorithms.py +++ b/bin/tests/system/isctest/vars/algorithms.py @@ -9,16 +9,17 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from typing import NamedTuple + import os import platform import random import subprocess import tempfile import time -from typing import Dict, List, NamedTuple, Optional, Union -from .basic import BASIC_VARS from .. import log +from .basic import BASIC_VARS # Algorithms are selected randomly at runtime from a list of supported # algorithms. The randomization is deterministic and remains stable for a @@ -56,18 +57,26 @@ class Algorithm(NamedTuple): number: int bits: int + @classmethod + def default(cls): + return cls( + os.environ["DEFAULT_ALGORITHM"], + int(os.environ["DEFAULT_ALGORITHM_NUMBER"]), + int(os.environ["DEFAULT_BITS"]), + ) + class AlgorithmSet(NamedTuple): """Collection of DEFAULT, ALTERNATIVE and DISABLED algorithms""" - default: Union[Algorithm, List[Algorithm]] + default: Algorithm | list[Algorithm] """DEFAULT is the algorithm for testing.""" - alternative: Union[Algorithm, List[Algorithm]] + alternative: Algorithm | list[Algorithm] """ALTERNATIVE is an alternative algorithm for test cases that require more than one algorithm (for example algorithm rollover).""" - disabled: Union[Algorithm, List[Algorithm]] + disabled: Algorithm | list[Algorithm] """DISABLED is an algorithm that is used for tests against the "disable-algorithms" configuration option.""" @@ -151,7 +160,7 @@ CRYPTO_SUPPORTED_VARS = { "ED448_SUPPORTED": "0", } -SUPPORTED_ALGORITHMS: List[Algorithm] = [] +SUPPORTED_ALGORITHMS: list[Algorithm] = [] def init_crypto_supported(): @@ -241,7 +250,7 @@ def _select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> Algorithm return AlgorithmSet(default, alternative, disabled) -def _algorithms_env(algs: AlgorithmSet, name: str) -> Dict[str, str]: +def _algorithms_env(algs: AlgorithmSet, name: str) -> dict[str, str]: """Return environment variables with selected algorithms as a dict.""" algs_env = { "ALGORITHM_SET": name, @@ -264,7 +273,7 @@ def _algorithms_env(algs: AlgorithmSet, name: str) -> Dict[str, str]: return algs_env -def set_algorithm_set(name: Optional[str]): +def set_algorithm_set(name: str | None): if name is None: name = "stable" assert name in ALGORITHM_SETS, f'ALGORITHM_SET "{name}" unknown' diff --git a/bin/tests/system/isctest/vars/all.py b/bin/tests/system/isctest/vars/all.py index 828341aa4c..d295aef0b1 100644 --- a/bin/tests/system/isctest/vars/all.py +++ b/bin/tests/system/isctest/vars/all.py @@ -11,11 +11,8 @@ from collections import ChainMap -# pylint: disable=import-error -from .autoconf import AC_VARS # type: ignore - -# pylint: enable=import-error from .algorithms import ALG_VARS, CRYPTO_SUPPORTED_VARS +from .autoconf import AC_VARS # type: ignore from .basic import BASIC_VARS from .dirs import DIR_VARS from .features import FEATURE_VARS diff --git a/bin/tests/system/isctest/vars/autoconf.py b/bin/tests/system/isctest/vars/autoconf.py index 7000ef2d72..4153bf3680 100644 --- a/bin/tests/system/isctest/vars/autoconf.py +++ b/bin/tests/system/isctest/vars/autoconf.py @@ -10,10 +10,9 @@ # information regarding copyright ownership. from pathlib import Path -from typing import Dict -def load_ac_vars_from_files() -> Dict[str, str]: +def load_ac_vars_from_files() -> dict[str, str]: ac_vars = {} ac_vars_dir = Path(__file__).resolve().parent / ".ac_vars" var_paths = [ diff --git a/bin/tests/system/isctest/vars/basic.py b/bin/tests/system/isctest/vars/basic.py index 9096df4886..b8e97787ee 100644 --- a/bin/tests/system/isctest/vars/basic.py +++ b/bin/tests/system/isctest/vars/basic.py @@ -11,12 +11,8 @@ import os -# pylint: disable=import-error from .autoconf import AC_VARS # type: ignore -# pylint: enable=import-error - - BASIC_VARS = { "ARPANAME": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/arpaname", "CDS": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-cds", diff --git a/bin/tests/system/isctest/vars/dirs.py b/bin/tests/system/isctest/vars/dirs.py index d99a30cca9..f04f478483 100644 --- a/bin/tests/system/isctest/vars/dirs.py +++ b/bin/tests/system/isctest/vars/dirs.py @@ -11,12 +11,8 @@ import os -# pylint: disable=import-error from .autoconf import AC_VARS # type: ignore -# pylint: enable=import-error - - SYSTEM_TEST_DIR_GIT_PATH = "bin/tests/system" DIR_VARS = { diff --git a/bin/tests/system/isctest/vars/openssl.py b/bin/tests/system/isctest/vars/openssl.py index b84f526dd8..44fbec4805 100644 --- a/bin/tests/system/isctest/vars/openssl.py +++ b/bin/tests/system/isctest/vars/openssl.py @@ -9,9 +9,9 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import os from re import compile as Re -from typing import Optional + +import os from .. import log @@ -23,7 +23,7 @@ OPENSSL_VARS = { } -def parse_openssl_config(path: Optional[str]): +def parse_openssl_config(path: str | None): if path is None or not os.path.exists(path): OPENSSL_VARS["ENGINE_ARG"] = None OPENSSL_VARS["SOFTHSM2_MODULE"] = None diff --git a/bin/tests/system/ixfr-nonminimal/ans2/ans.py b/bin/tests/system/ixfr-nonminimal/ans2/ans.py index 207b5e49ff..3d2b190c65 100644 --- a/bin/tests/system/ixfr-nonminimal/ans2/ans.py +++ b/bin/tests/system/ixfr-nonminimal/ans2/ans.py @@ -11,6 +11,8 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator, Collection, Iterable + import abc import dns.rcode @@ -18,8 +20,6 @@ import dns.rdataclass import dns.rdatatype import dns.rrset -from typing import AsyncGenerator, Collection, Iterable - from isctest.asyncserver import ( ControllableAsyncDnsServer, DnsResponseSend, diff --git a/bin/tests/system/ixfr-nonminimal/ans4/ans.py b/bin/tests/system/ixfr-nonminimal/ans4/ans.py index 769600ec94..c6bde4cd83 100644 --- a/bin/tests/system/ixfr-nonminimal/ans4/ans.py +++ b/bin/tests/system/ixfr-nonminimal/ans4/ans.py @@ -11,6 +11,8 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator, Collection, Iterable + import abc import dns.rcode @@ -18,8 +20,6 @@ import dns.rdataclass import dns.rdatatype import dns.rrset -from typing import AsyncGenerator, Collection, Iterable - from isctest.asyncserver import ( ControllableAsyncDnsServer, DnsResponseSend, diff --git a/bin/tests/system/ixfr/ans2/ans.py b/bin/tests/system/ixfr/ans2/ans.py index 8659244426..5c9268a193 100644 --- a/bin/tests/system/ixfr/ans2/ans.py +++ b/bin/tests/system/ixfr/ans2/ans.py @@ -11,6 +11,8 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator, Collection, Iterable + import abc import dns.rcode @@ -18,8 +20,6 @@ import dns.rdataclass import dns.rdatatype import dns.rrset -from typing import AsyncGenerator, Collection, Iterable - from isctest.asyncserver import ( ControllableAsyncDnsServer, DnsResponseSend, diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py index 89f2696e56..fdc80adc01 100644 --- a/bin/tests/system/kasp/tests_kasp.py +++ b/bin/tests/system/kasp/tests_kasp.py @@ -9,25 +9,28 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from datetime import timedelta + import os import shutil import subprocess import time -from datetime import timedelta - -import dns +import dns.exception +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.tsig import dns.update import pytest +from isctest.kasp import KeyProperties, KeyTimingMetadata +from isctest.util import param +from isctest.vars.algorithms import ECDSAP256SHA256, ECDSAP384SHA384, Algorithm + import isctest import isctest.mark -from isctest.kasp import ( - KeyProperties, - KeyTimingMetadata, -) -from isctest.util import param -from isctest.vars.algorithms import ECDSAP256SHA256, ECDSAP384SHA384 pytestmark = pytest.mark.extra_artifacts( [ @@ -131,10 +134,10 @@ KASP_INHERIT_TSIG_SECRET = { } -def autosign_properties(alg, size): +def autosign_properties(algorithm: Algorithm): return [ - f"ksk {lifetime['P2Y']} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk {lifetime['P1Y']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk {lifetime['P2Y']} {algorithm.number} {algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk {lifetime['P1Y']} {algorithm.number} {algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] @@ -355,9 +358,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "autosign", "config": autosign_config, "offset": -timedelta(days=30 * 6), - "key-properties": autosign_properties( - os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] - ), + "key-properties": autosign_properties(Algorithm.default()), }, id="dnskey-ttl-mismatch.autosign", ), @@ -367,9 +368,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "autosign", "config": autosign_config, "offset": -timedelta(days=30 * 6), - "key-properties": autosign_properties( - os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] - ), + "key-properties": autosign_properties(Algorithm.default()), "additional-tests": [ { "callback": cb_rrsig_refresh, @@ -385,9 +384,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "autosign", "config": autosign_config, "offset": -timedelta(days=30 * 6), - "key-properties": autosign_properties( - os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] - ), + "key-properties": autosign_properties(Algorithm.default()), "additional-tests": [ { "callback": cb_rrsig_reuse, @@ -403,9 +400,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "autosign", "config": autosign_config, "offset": -timedelta(days=30 * 6), - "key-properties": autosign_properties( - os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] - ), + "key-properties": autosign_properties(Algorithm.default()), "additional-tests": [ { "callback": cb_rrsig_refresh, @@ -421,9 +416,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "autosign", "config": autosign_config, "offset": -timedelta(days=30 * 6), - "key-properties": autosign_properties( - os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] - ), + "key-properties": autosign_properties(Algorithm.default()), "additional-tests": [ { "callback": cb_remove_keyfiles, @@ -440,8 +433,8 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "config": autosign_config, "offset": -timedelta(days=30 * 6), "key-properties": [ - f"ksk 63072000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent missing", - f"zsk 31536000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk 63072000 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent missing", + f"zsk 31536000 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ], }, id="ksk-missing.autosign", @@ -453,8 +446,8 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "config": autosign_config, "offset": -timedelta(days=30 * 6), "key-properties": [ - f"ksk 63072000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk 31536000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent missing", + f"ksk 63072000 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk 31536000 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent missing", ], }, id="zsk-missing.autosign", @@ -513,8 +506,8 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): }, "key-directories": ["{keydir}/ksk", "{keydir}/zsk"], "key-properties": [ - f"ksk unlimited {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk unlimited {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk unlimited {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ], }, id="keystore.kasp", @@ -615,7 +608,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None): "policy": "unlimited", "config": kasp_config, "key-properties": [ - f"csk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="unlimited.kasp", @@ -912,7 +905,7 @@ def test_kasp_default(ns3): ns3.rndc(f"loadkeys {zone}") watcher.wait_for_line(f"zone {zone}/IN (signed): {expectmsg}") # Nothing has changed. - expected[0].private = False # noqa + expected[0].private = False isctest.kasp.check_dnssec_verify(ns3, zone) isctest.kasp.check_keys(zone, keys, expected) isctest.kasp.check_keytimes(keys, expected) @@ -1061,18 +1054,16 @@ def test_kasp_dynamic(ns3): assert f"zone_resigninc: zone {zone}/IN (unsigned): enter" not in "ns3/named.run" -def test_kasp_checkds(ns3): +def test_kasp_checkds(ns3, default_algorithm): def wait_for_metadata(): return isctest.util.file_contents_contain(ksk.statefile, metadata) # Zone: checkds-ksk.kasp. zone = "checkds-ksk.kasp" policy = "checkds-ksk" - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] policy_keys = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ] isctest.kasp.wait_keymgr_done(ns3, zone) @@ -1105,19 +1096,17 @@ def test_kasp_checkds(ns3): isctest.kasp.check_keys(zone, keys, expected) -def test_kasp_checkds_doubleksk(ns3): +def test_kasp_checkds_doubleksk(ns3, default_algorithm): def wait_for_metadata(): return isctest.util.file_contents_contain(ksk.statefile, metadata) # Zone: checkds-doubleksk.kasp. zone = "checkds-doubleksk.kasp" policy = "checkds-doubleksk" - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] policy_keys = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ] isctest.kasp.wait_keymgr_done(ns3, zone) @@ -1179,17 +1168,15 @@ def test_kasp_checkds_doubleksk(ns3): isctest.kasp.check_keys(zone, keys, expected) -def test_kasp_checkds_csk(ns3): +def test_kasp_checkds_csk(ns3, default_algorithm): def wait_for_metadata(): return isctest.util.file_contents_contain(ksk.statefile, metadata) # Zone: checkds-csk.kasp. zone = "checkds-csk.kasp" policy = "checkds-csk" - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] policy_keys = [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ] isctest.kasp.wait_keymgr_done(ns3, zone) @@ -1467,7 +1454,7 @@ def test_kasp_dnssec_keygen(): isctest.kasp.check_keytimes(keys, expected) -def test_kasp_zsk_retired(ns3): +def test_kasp_zsk_retired(ns3, default_algorithm): config = { "dnskey-ttl": timedelta(seconds=300), "ds-ttl": timedelta(days=1), @@ -1482,14 +1469,12 @@ def test_kasp_zsk_retired(ns3): zone = "zsk-retired.autosign" policy = "autosign" - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] key_properties = [ - f"ksk 63072000 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"ksk 63072000 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", # zsk predecessor - f"zsk 31536000 {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + f"zsk 31536000 {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent", # zsk successor - f"zsk 31536000 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden", + f"zsk 31536000 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden", ] isctest.kasp.wait_keymgr_done(ns3, zone) @@ -1688,18 +1673,16 @@ def test_kasp_reload_restart(ns6): isctest.run.retry_with_timeout(check_soa_ttl, timeout=10) -def test_kasp_manual_mode(ns3): +def test_kasp_manual_mode(ns3, default_algorithm): keydir = ns3.identifier zone = "keyfiles-missing.manual" policy = "manual" ttl = int(autosign_config["dnskey-ttl"].total_seconds()) offset = -timedelta(days=30 * 6) - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] keyprops = [ - f"ksk {lifetime['P2Y']} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk {lifetime['P2M']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk {lifetime['P2Y']} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk {lifetime['P2M']} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] isctest.kasp.wait_keymgr_done(ns3, zone) @@ -1774,9 +1757,9 @@ def test_kasp_manual_mode(ns3): # Check keys again, make sure the rollover has started. keyprops = [ - f"ksk {lifetime['P2Y']} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk {lifetime['P2M']} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent", - f"zsk {lifetime['P2M']} {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden", + f"ksk {lifetime['P2Y']} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk {lifetime['P2M']} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + f"zsk {lifetime['P2M']} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden", ] expected = isctest.kasp.policy_to_properties(ttl=ttl, keys=keyprops) keys = isctest.kasp.keydir_to_keylist(zone, keydir) diff --git a/bin/tests/system/keepalive/tests_keepalive.py b/bin/tests/system/keepalive/tests_keepalive.py index 7a90c7cb43..92657515a9 100644 --- a/bin/tests/system/keepalive/tests_keepalive.py +++ b/bin/tests/system/keepalive/tests_keepalive.py @@ -9,9 +9,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import isctest import pytest +import isctest + pytestmark = pytest.mark.extra_artifacts( ["ns2/named.stats"], ) diff --git a/bin/tests/system/keyfromlabel/tests_keyfromlabel.py b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py index 44f14077ed..e2f76c63df 100644 --- a/bin/tests/system/keyfromlabel/tests_keyfromlabel.py +++ b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py @@ -9,9 +9,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from re import compile as Re + import hashlib import os -from re import compile as Re import shutil import pytest @@ -85,7 +86,6 @@ def token_init_and_cleanup(): assert Re("Found token (.*) with matching token label") in cmd.out -# pylint: disable-msg=too-many-locals @pytest.mark.parametrize( "alg_name,alg_type,alg_bits", [ diff --git a/bin/tests/system/ksr/tests_ksr.py b/bin/tests/system/ksr/tests_ksr.py index fd5f17ae4c..b9a21eac5b 100644 --- a/bin/tests/system/ksr/tests_ksr.py +++ b/bin/tests/system/ksr/tests_ksr.py @@ -10,6 +10,7 @@ # information regarding copyright ownership. from datetime import timedelta + import os import re import shutil @@ -17,8 +18,10 @@ import time import pytest -import isctest from isctest.kasp import KeyTimingMetadata +from isctest.vars.algorithms import Algorithm + +import isctest pytestmark = pytest.mark.extra_artifacts( [ @@ -116,12 +119,17 @@ def ksr(zone, policy, action, options="", raise_on_exception=True, to_file=""): def check_keys( keys, lifetime, - alg=os.environ["DEFAULT_ALGORITHM_NUMBER"], - size=os.environ["DEFAULT_BITS"], + alg=None, + size=None, offset=0, with_state=False, ): # Check keys that were created. + if alg is None: + alg = Algorithm.default().number + if size is None: + size = Algorithm.default().bits + num = 0 now = KeyTimingMetadata.now() @@ -507,7 +515,6 @@ def check_signedkeyresponse( # collect keys that should be in this bundle # collect lines that should be in this bundle bundle_keys.append(key) - # pylint: disable=unused-variable for _arg in expected_cds: bundle_lines.append(lines[line_no]) line_no += 1 diff --git a/bin/tests/system/limits/tests_limits.py b/bin/tests/system/limits/tests_limits.py index 6949838ec7..c7498a22ec 100644 --- a/bin/tests/system/limits/tests_limits.py +++ b/bin/tests/system/limits/tests_limits.py @@ -11,10 +11,11 @@ import itertools -import isctest +import dns.flags +import dns.rrset import pytest -import dns.rrset +import isctest @pytest.mark.parametrize( diff --git a/bin/tests/system/migrate2kasp/tests_migrate2kasp.py b/bin/tests/system/migrate2kasp/tests_migrate2kasp.py index cb5f6e2051..3e4150ee7f 100644 --- a/bin/tests/system/migrate2kasp/tests_migrate2kasp.py +++ b/bin/tests/system/migrate2kasp/tests_migrate2kasp.py @@ -9,13 +9,15 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import os from datetime import timedelta +import os + import pytest +from isctest.vars.algorithms import Algorithm + import isctest -import isctest.mark pytestmark = pytest.mark.extra_artifacts( [ @@ -133,8 +135,8 @@ lifetime = { "config": standard_config, "offset": 0, "key-properties": [ - f"ksk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:rumoured", - f"zsk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:rumoured", + f"zsk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ], }, id="migrate.kasp", @@ -148,7 +150,7 @@ lifetime = { "config": default_config, "offset": 0, "key-properties": [ - f"csk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:rumoured", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:rumoured", ], }, id="csk.kasp", @@ -162,7 +164,7 @@ lifetime = { "config": default_config, "offset": 0, "key-properties": [ - f"csk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:rumoured", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:rumoured", ], }, id="csk-nosep.kasp", @@ -176,8 +178,8 @@ lifetime = { "config": timing_config, "offset": -timedelta(seconds=300), "key-properties": [ - f"ksk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:rumoured", - f"zsk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:rumoured", + f"zsk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ], }, id="rumoured.kasp", @@ -191,8 +193,8 @@ lifetime = { "config": timing_config, "offset": -timedelta(seconds=3900), "key-properties": [ - f"ksk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ], }, id="omnipresent.kasp", @@ -206,8 +208,8 @@ lifetime = { "config": timing_config, "offset": -timedelta(hours=12), "key-properties": [ - f"ksk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured", - f"zsk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured", + f"zsk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ], }, id="no-syncpublish.kasp", @@ -223,8 +225,8 @@ lifetime = { "key-properties": [ "ksk - 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", "zsk - 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent", - f"ksk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk {lifetime['P60D']} {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk {lifetime['P60D']} {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ], }, id="migrate-nomatch-algnum.kasp", @@ -256,10 +258,10 @@ lifetime = { "config": migrate_config, "offset": -timedelta(seconds=3900), "key-properties": [ - f"ksk - {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk - {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + f"ksk - {Algorithm.default().number} {Algorithm.default().bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk - {Algorithm.default().number} {Algorithm.default().bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent", # This key is considered to be prepublished, so it is not yet signing, nor is the DS introduced. - f"csk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden", ], }, id="migrate-nomatch-kzc.kasp", diff --git a/bin/tests/system/multisigner/tests_multisigner.py b/bin/tests/system/multisigner/tests_multisigner.py index da9a3e5a56..81209009f1 100644 --- a/bin/tests/system/multisigner/tests_multisigner.py +++ b/bin/tests/system/multisigner/tests_multisigner.py @@ -10,13 +10,16 @@ # information regarding copyright ownership. from datetime import timedelta -import os from re import compile as Re -import pytest +import os -import dns +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype import dns.update +import pytest import isctest @@ -45,8 +48,6 @@ pytestmark = pytest.mark.extra_artifacts( ] ) -ALGORITHM = os.environ["DEFAULT_ALGORITHM_NUMBER"] -SIZE = os.environ["DEFAULT_BITS"] CONFIG = { "dnskey-ttl": timedelta(hours=1), "ds-ttl": timedelta(days=1), @@ -502,11 +503,11 @@ def check_remove_cds( check_dnssec(server, zone, keys, expected) -def test_multisigner(ns3, ns4): +def test_multisigner(ns3, ns4, default_algorithm): zone = "model2.multisigner" keyprops = [ - f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] # First make sure the zone is properly signed. @@ -529,10 +530,10 @@ def test_multisigner(ns3, ns4): check_dnssec(ns4, zone, keys4, expected4) # Add DNSKEY to RRset. - newprops = [f"zsk unlimited {ALGORITHM} {SIZE}"] + newprops = [f"zsk unlimited {default_algorithm.number} {default_algorithm.bits}"] extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops) - extra[0].private = False # noqa - extra[0].legacy = True # noqa + extra[0].private = False + extra[0].legacy = True check_add_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra) check_add_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra) @@ -544,10 +545,10 @@ def test_multisigner(ns3, ns4): check_no_dnssec_in_journal(ns4, zone) # Add CDNSKEY RRset. - newprops = [f"ksk unlimited {ALGORITHM} {SIZE}"] + newprops = [f"ksk unlimited {default_algorithm.number} {default_algorithm.bits}"] extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops) - extra[0].private = False # noqa - extra[0].legacy = True # noqa + extra[0].private = False + extra[0].legacy = True check_add_cdnskey(ns3, zone, keys3, expected3, [ksks4[0]], extra) check_add_cdnskey(ns4, zone, keys4, expected4, [ksks3[0]], extra) @@ -573,11 +574,11 @@ def test_multisigner(ns3, ns4): check_no_dnssec_in_journal(ns4, zone) -def test_multisigner_secondary(ns3, ns4, ns5): +def test_multisigner_secondary(ns3, ns4, ns5, default_algorithm): zone = "model2.secondary" keyprops = [ - f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] # First make sure the zone is properly signed. @@ -600,10 +601,10 @@ def test_multisigner_secondary(ns3, ns4, ns5): check_dnssec(ns4, zone, keys4, expected4) # Add DNSKEY to RRset. - newprops = [f"zsk unlimited {ALGORITHM} {SIZE}"] + newprops = [f"zsk unlimited {default_algorithm.number} {default_algorithm.bits}"] extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops) - extra[0].private = False # noqa - extra[0].legacy = True # noqa + extra[0].private = False + extra[0].legacy = True check_add_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra, primary=ns5) check_add_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra, primary=ns5) @@ -617,10 +618,10 @@ def test_multisigner_secondary(ns3, ns4, ns5): check_no_dnssec_in_journal(ns4, zone) # Add CDNSKEY RRset. - newprops = [f"ksk unlimited {ALGORITHM} {SIZE}"] + newprops = [f"ksk unlimited {default_algorithm.number} {default_algorithm.bits}"] extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops) - extra[0].private = False # noqa - extra[0].legacy = True # noqa + extra[0].private = False + extra[0].legacy = True check_add_cdnskey(ns3, zone, keys3, expected3, [ksks4[0]], extra, primary=ns5) check_add_cdnskey(ns4, zone, keys4, expected4, [ksks3[0]], extra, primary=ns5) diff --git a/bin/tests/system/nsec3-answer/tests_nsec3.py b/bin/tests/system/nsec3-answer/tests_nsec3.py index ebd0ea6623..f339813ced 100755 --- a/bin/tests/system/nsec3-answer/tests_nsec3.py +++ b/bin/tests/system/nsec3-answer/tests_nsec3.py @@ -15,30 +15,30 @@ # https://github.com/pylint-dev/pylint/issues/10785#issuecomment-3677224217 # pylint: disable=unreachable +from collections.abc import Container, Iterable from dataclasses import dataclass -import os from pathlib import Path -from typing import Container, Iterable, Optional, Set, Tuple -import pytest +import os + +from hypothesis import assume, given import dns.dnssec import dns.message import dns.name -import dns.query import dns.rcode import dns.rdataclass import dns.rdatatype -import dns.rdtypes.ANY.RRSIG import dns.rdtypes.ANY.NSEC3 +import dns.rdtypes.ANY.RRSIG import dns.rrset +import pytest from isctest.hypothesis.strategies import dns_names, sampled_from + import isctest import isctest.name -from hypothesis import assume, given - SUFFIX = dns.name.from_text(".") AUTH = "10.53.0.1" RESOLVER = "10.53.0.2" @@ -62,7 +62,7 @@ def is_related_to_any( def do_test_query( qname: dns.name.Name, qtype: dns.rdatatype.RdataType, server: str, named_port: int -) -> Tuple[dns.message.QueryMessage, "NSEC3Checker"]: +) -> tuple[dns.message.QueryMessage, "NSEC3Checker"]: query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) response = isctest.query.tcp(query, server, named_port, timeout=TIMEOUT) isctest.check.is_response_to(response, query) @@ -290,7 +290,7 @@ class NSEC3Params: algorithm: int flags: int iterations: int - salt: Optional[bytes] + salt: bytes | None class NSEC3Checker: @@ -348,8 +348,8 @@ class NSEC3Checker: assert attrs_seen["algorithm"] is not None, f"no NSEC3 found\n{response}" self.params: NSEC3Params = NSEC3Params(**attrs_seen) self.response: dns.message.Message = response - self.owners_present: Set[dns.name.Name] = owners_seen - self.owners_used: Set[dns.name.Name] = set() + self.owners_present: set[dns.name.Name] = owners_seen + self.owners_used: set[dns.name.Name] = set() @staticmethod def nsec3_covers(rrset: dns.rrset.RRset, hashed_name: dns.name.Name) -> bool: diff --git a/bin/tests/system/nsec3/common.py b/bin/tests/system/nsec3/common.py index be0925e3b3..13a8f13464 100644 --- a/bin/tests/system/nsec3/common.py +++ b/bin/tests/system/nsec3/common.py @@ -9,16 +9,16 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import os - from datetime import timedelta -import dns +import dns.rcode +import dns.rdataclass +import dns.rdatatype import pytest import isctest -pytestmark = pytest.mark.extra_artifacts( +NSEC3_MARK = pytest.mark.extra_artifacts( [ "*.axfr", "*.created", @@ -40,9 +40,6 @@ pytestmark = pytest.mark.extra_artifacts( ] ) -ALGORITHM = os.environ["DEFAULT_ALGORITHM_NUMBER"] -SIZE = os.environ["DEFAULT_BITS"] - default_config = { "dnskey-ttl": timedelta(hours=1), "ds-ttl": timedelta(days=1), @@ -124,8 +121,8 @@ def check_nsec3_case(server, params, nsec3=True): if "external-keys" in params: expected2 = isctest.kasp.policy_to_properties(ttl, keys=params["external-keys"]) for ek in expected2: - ek.private = False # noqa - ek.legacy = True # noqa + ek.private = False + ek.legacy = True expected = expected + expected2 assert "external-keydir" in params extkeys = isctest.kasp.keydir_to_keylist(zone, params["external-keydir"]) diff --git a/bin/tests/system/nsec3/tests_nsec3_change.py b/bin/tests/system/nsec3/tests_nsec3_change.py index d5ec16f5b4..b8a8b066e3 100644 --- a/bin/tests/system/nsec3/tests_nsec3_change.py +++ b/bin/tests/system/nsec3/tests_nsec3_change.py @@ -9,26 +9,20 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - -import os import shutil import time -import dns -import dns.update +import dns.name +import dns.rdataclass +import dns.rdatatype import pytest +from isctest.vars.algorithms import Algorithm +from nsec3.common import NSEC3_MARK, check_nsec3_case + import isctest -import isctest.mark -from isctest.vars.algorithms import RSASHA1 -from nsec3.common import ( - ALGORITHM, - SIZE, - default_config, - pytestmark, - check_nsec3_case, -) + +pytestmark = NSEC3_MARK # include the following zones when rendering named configs ZONES = { @@ -100,7 +94,7 @@ def test_nsec3_case(ns3): "salt-length": 8, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], } zone = params["zone"] diff --git a/bin/tests/system/nsec3/tests_nsec3_initial.py b/bin/tests/system/nsec3/tests_nsec3_initial.py index 42c0f2b2ae..0cc53c81aa 100644 --- a/bin/tests/system/nsec3/tests_nsec3_initial.py +++ b/bin/tests/system/nsec3/tests_nsec3_initial.py @@ -9,24 +9,19 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import,unspecified-encoding,multiple-statements,use-maxsplit-arg,broad-exception-caught,f-string-without-interpolation - import os -import dns +import dns.rcode import dns.update import pytest +from isctest.vars.algorithms import RSASHA1, Algorithm +from nsec3.common import NSEC3_MARK, check_nsec3_case + import isctest import isctest.mark -from isctest.vars.algorithms import RSASHA1 -from nsec3.common import ( - ALGORITHM, - SIZE, - default_config, - pytestmark, - check_nsec3_case, -) + +pytestmark = NSEC3_MARK # include the following zones when rendering named configs ZONES = { @@ -70,7 +65,7 @@ def bootstrap(): "zone": "nsec-to-nsec3.kasp", "policy": "nsec", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec-to-nsec3.kasp", @@ -104,10 +99,10 @@ def bootstrap(): "zone": "nsec3-xfr-inline.kasp", "policy": "nsec", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], "external-keys": [ - f"csk 0 {ALGORITHM} {SIZE}", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits}", ], "external-keydir": "ns2", }, @@ -118,7 +113,7 @@ def bootstrap(): "zone": "nsec3-dynamic-update-inline.kasp", "policy": "nsec", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic-update-inline.kasp", @@ -161,7 +156,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-to-rsasha1.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", ], }, id="nsec3-to-rsasha1.kasp", @@ -172,7 +167,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-to-rsasha1-ds.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", ], }, id="nsec3-to-rsasha1-ds.kasp", @@ -183,7 +178,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3.kasp", @@ -193,7 +188,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-dynamic.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic.kasp", @@ -203,7 +198,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-change.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-change.kasp", @@ -213,7 +208,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-dynamic-change.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic-change.kasp", @@ -223,7 +218,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-dynamic-to-inline.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic-to-inline.kasp", @@ -233,7 +228,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-inline-to-dynamic.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-inline-to-dynamic.kasp", @@ -243,7 +238,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-to-nsec.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-to-nsec.kasp", @@ -253,7 +248,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-to-optout.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-to-optout.kasp", @@ -267,7 +262,7 @@ def test_nsec_case(ns3, params): "salt-length": 0, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-from-optout.kasp", @@ -281,7 +276,7 @@ def test_nsec_case(ns3, params): "salt-length": 8, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-other.kasp", diff --git a/bin/tests/system/nsec3/tests_nsec3_reconfig.py b/bin/tests/system/nsec3/tests_nsec3_reconfig.py index cb75f1caa4..9efc486791 100644 --- a/bin/tests/system/nsec3/tests_nsec3_reconfig.py +++ b/bin/tests/system/nsec3/tests_nsec3_reconfig.py @@ -9,26 +9,22 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import os -import shutil import time -import dns -import dns.update +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype import pytest +from isctest.vars.algorithms import RSASHA1, Algorithm +from nsec3.common import NSEC3_MARK, check_nsec3_case + import isctest import isctest.mark -from isctest.vars.algorithms import RSASHA1 -from nsec3.common import ( - ALGORITHM, - SIZE, - default_config, - pytestmark, - check_nsec3_case, -) + +pytestmark = NSEC3_MARK # include the following zones when rendering named configs ZONES = { @@ -97,7 +93,7 @@ def after_servers_start(ns3, templates): "policy": "nsec3", "key-properties": [ f"csk 0 {RSASHA1.number} 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="rsasha1-to-nsec3.kasp", @@ -109,7 +105,7 @@ def after_servers_start(ns3, templates): "policy": "nsec3", "key-properties": [ f"csk 0 {RSASHA1.number} 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="rsasha1-to-nsec3-wait.kasp", @@ -120,7 +116,7 @@ def after_servers_start(ns3, templates): "zone": "nsec3-to-rsasha1.kasp", "policy": "rsasha1", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", f"csk 0 {RSASHA1.number} 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, @@ -132,7 +128,7 @@ def after_servers_start(ns3, templates): "zone": "nsec3-to-rsasha1-ds.kasp", "policy": "rsasha1", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", f"csk 0 {RSASHA1.number} 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, @@ -144,7 +140,7 @@ def after_servers_start(ns3, templates): "zone": "nsec3-to-nsec.kasp", "policy": "nsec", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-to-nsec.kasp", @@ -169,7 +165,7 @@ def test_nsec_case(ns3, params): "zone": "nsec-to-nsec3.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec-to-nsec3.kasp", @@ -179,7 +175,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3.kasp", @@ -189,7 +185,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-dynamic.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic.kasp", @@ -203,7 +199,7 @@ def test_nsec_case(ns3, params): "salt-length": 8, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic-change.kasp", @@ -213,7 +209,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-dynamic-to-inline.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-dynamic-to-inline.kasp", @@ -223,7 +219,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-inline-to-dynamic.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-inline-to-dynamic.kasp", @@ -240,7 +236,7 @@ def test_nsec_case(ns3, params): # "salt-length": 0, # }, # "key-properties": [ - # f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + # f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", # ], # }, # id="nsec3-to-optout.kasp", @@ -253,7 +249,7 @@ def test_nsec_case(ns3, params): # "zone": "nsec3-from-optout.kasp", # "policy": "optout", # "key-properties": [ - # f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + # f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", # ], # }, # id="nsec3-from-optout.kasp", @@ -267,7 +263,7 @@ def test_nsec_case(ns3, params): "salt-length": 8, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-other.kasp", @@ -291,7 +287,7 @@ def test_nsec3_ent(ns3, templates): "zone": "nsec3-ent.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], } diff --git a/bin/tests/system/nsec3/tests_nsec3_reload.py b/bin/tests/system/nsec3/tests_nsec3_reload.py index 33171932bd..fb11f5fc27 100644 --- a/bin/tests/system/nsec3/tests_nsec3_reload.py +++ b/bin/tests/system/nsec3/tests_nsec3_reload.py @@ -9,21 +9,13 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - -import os import shutil -import time -import dns -import pytest +from nsec3.common import NSEC3_MARK, check_nsec3_case import isctest -from nsec3.common import ( - ALGORITHM, - SIZE, - check_nsec3_case, -) + +pytestmark = NSEC3_MARK # include the following zones when rendering named configs ZONES = { @@ -37,13 +29,13 @@ def bootstrap(): } -def test_nsec3_case(ns3): +def test_nsec3_case(ns3, default_algorithm): # Get test parameters. params = { "zone": "nsec3-fails-to-load.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], } zone = params["zone"] diff --git a/bin/tests/system/nsec3/tests_nsec3_restart.py b/bin/tests/system/nsec3/tests_nsec3_restart.py index 9771fd5812..ca6ebef811 100644 --- a/bin/tests/system/nsec3/tests_nsec3_restart.py +++ b/bin/tests/system/nsec3/tests_nsec3_restart.py @@ -9,24 +9,17 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import os -import dns -import dns.update +import dns.rdatatype import pytest +from isctest.vars.algorithms import Algorithm +from nsec3.common import NSEC3_MARK, check_nsec3_case, check_nsec3param + import isctest -import isctest.mark -from nsec3.common import ( - ALGORITHM, - SIZE, - default_config, - pytestmark, - check_nsec3_case, - check_nsec3param, -) + +pytestmark = NSEC3_MARK # include the following zones when rendering named configs ZONES = { @@ -74,7 +67,7 @@ def perform_nsec3_tests(server, params): "zone": "nsec3.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3.kasp", @@ -88,7 +81,7 @@ def perform_nsec3_tests(server, params): "salt-length": 8, }, "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, id="nsec3-other.kasp", diff --git a/bin/tests/system/nsec3/tests_nsec3_retransfer.py b/bin/tests/system/nsec3/tests_nsec3_retransfer.py index c4b9b3284c..6fd2e86080 100644 --- a/bin/tests/system/nsec3/tests_nsec3_retransfer.py +++ b/bin/tests/system/nsec3/tests_nsec3_retransfer.py @@ -9,24 +9,19 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta -import os -import shutil -import dns -import dns.update -import pytest +import os + +import dns.rcode +import dns.rdatatype + +from isctest.vars.algorithms import RSASHA256 +from nsec3.common import NSEC3_MARK, check_auth_nsec3, check_nsec3param import isctest -import isctest.mark -from isctest.vars.algorithms import RSASHA256 -from nsec3.common import ( - pytestmark, - check_auth_nsec3, - check_nsec3param, -) + +pytestmark = NSEC3_MARK DNSKEY_TTL = int(timedelta(hours=1).total_seconds()) ZSK_LIFETIME = int(timedelta(days=90).total_seconds()) diff --git a/bin/tests/system/nsupdate/ans4/ans.py b/bin/tests/system/nsupdate/ans4/ans.py index ab066c4bee..da1f43886b 100644 --- a/bin/tests/system/nsupdate/ans4/ans.py +++ b/bin/tests/system/nsupdate/ans4/ans.py @@ -9,11 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from isctest.asyncserver import ( - AsyncDnsServer, - IgnoreAllConnections, - IgnoreAllQueries, -) +from isctest.asyncserver import AsyncDnsServer, IgnoreAllConnections, IgnoreAllQueries def main() -> None: diff --git a/bin/tests/system/nzd2nzf/tests_nzd2nzf.py b/bin/tests/system/nzd2nzf/tests_nzd2nzf.py index 790e937556..54e5a2c95b 100644 --- a/bin/tests/system/nzd2nzf/tests_nzd2nzf.py +++ b/bin/tests/system/nzd2nzf/tests_nzd2nzf.py @@ -11,6 +11,7 @@ import os + import pytest import isctest diff --git a/bin/tests/system/optout/tests_optout.py b/bin/tests/system/optout/tests_optout.py index 1cc0132e3e..ef157b3e9e 100755 --- a/bin/tests/system/optout/tests_optout.py +++ b/bin/tests/system/optout/tests_optout.py @@ -16,17 +16,12 @@ import os import re import sys -import isctest -import pytest - -import dns -import dns.exception -import dns.message -import dns.name import dns.query import dns.rcode -import dns.rdataclass -import dns.rdatatype +import dns.zone +import pytest + +import isctest pytestmark = [ pytest.mark.skipif( diff --git a/bin/tests/system/pytest.ini b/bin/tests/system/pytest.ini index 5574b3e611..fce4abff24 100644 --- a/bin/tests/system/pytest.ini +++ b/bin/tests/system/pytest.ini @@ -10,7 +10,7 @@ # information regarding copyright ownership. [pytest] -addopts = --tb=short -rA -vv +addopts = --tb=short -rA -vv --dist=loadscope log_format = %(asctime)s %(levelname)s:%(name)s %(message)s log_date_format = %Y-%m-%d %H:%M:%S log_cli = 1 diff --git a/bin/tests/system/qmin/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py index 4708dc6cf1..a8e7d7cd97 100644 --- a/bin/tests/system/qmin/ans2/ans.py +++ b/bin/tests/system/qmin/ans2/ans.py @@ -11,9 +11,8 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator -import dns.message import dns.name import dns.rcode import dns.rdatatype @@ -27,7 +26,7 @@ from isctest.asyncserver import ( ResponseAction, ) -from qmin_ans import ( +from ..qmin_ans import ( DelayedResponseHandler, EntRcodeChanger, QueryLogHandler, diff --git a/bin/tests/system/qmin/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py index ec720fd228..5d4e7edca4 100644 --- a/bin/tests/system/qmin/ans3/ans.py +++ b/bin/tests/system/qmin/ans3/ans.py @@ -15,7 +15,7 @@ import dns.rcode from isctest.asyncserver import AsyncDnsServer -from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler +from ..qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler class QueryLogger(QueryLogHandler): diff --git a/bin/tests/system/qmin/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py index b766017de0..c3c5547258 100644 --- a/bin/tests/system/qmin/ans4/ans.py +++ b/bin/tests/system/qmin/ans4/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype @@ -24,7 +24,12 @@ from isctest.asyncserver import ( ResponseAction, ) -from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler, log_query +from ..qmin_ans import ( + DelayedResponseHandler, + EntRcodeChanger, + QueryLogHandler, + log_query, +) class QueryLogger(QueryLogHandler): diff --git a/bin/tests/system/qmin/qmin_ans.py b/bin/tests/system/qmin/qmin_ans.py index 6185e15a10..74c4891b6e 100644 --- a/bin/tests/system/qmin/qmin_ans.py +++ b/bin/tests/system/qmin/qmin_ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import abc diff --git a/bin/tests/system/re_compile_checker.py b/bin/tests/system/re_compile_checker.py index efa0e9a038..447f88e17e 100644 --- a/bin/tests/system/re_compile_checker.py +++ b/bin/tests/system/re_compile_checker.py @@ -14,7 +14,6 @@ import re from astroid import nodes - from pylint.checkers import BaseRawFileChecker from pylint.lint import PyLinter @@ -36,10 +35,19 @@ class ReCompileChecker(BaseRawFileChecker): def process_module(self, node: nodes.Module) -> None: pattern = re.compile(r"re\.compile\(") + import_pattern = re.compile(r"^\s*(import|from)\s+isctest\b") with node.stream() as stream: - for lineno, line in enumerate(stream): - if pattern.search(line.decode("utf-8")): - self.add_message("re-compile-alias", line=lineno) + lines = [line.decode("utf-8", errors="replace") for line in stream] + + if not any( + import_pattern.search(line) and not line.lstrip().startswith("#") + for line in lines + ): + return + + for lineno, line in enumerate(lines): + if pattern.search(line): + self.add_message("re-compile-alias", line=lineno) def register(linter: PyLinter) -> None: diff --git a/bin/tests/system/resolver/ans10/ans.py b/bin/tests/system/resolver/ans10/ans.py index 1edb75db9e..0abb52c54c 100644 --- a/bin/tests/system/resolver/ans10/ans.py +++ b/bin/tests/system/resolver/ans10/ans.py @@ -9,7 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype @@ -21,7 +21,7 @@ from isctest.asyncserver import ( ResponseHandler, ) -from resolver_ans import rrset, soa_rrset +from ..resolver_ans import rrset, soa_rrset class EdnsWithOptionsFormerrHandler(ResponseHandler): diff --git a/bin/tests/system/resolver/ans2/ans.py b/bin/tests/system/resolver/ans2/ans.py index 30c8d4230c..112bf8ac85 100644 --- a/bin/tests/system/resolver/ans2/ans.py +++ b/bin/tests/system/resolver/ans2/ans.py @@ -11,12 +11,12 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator, Tuple, Union +from collections.abc import AsyncGenerator import dns.name import dns.rcode -import dns.rrset import dns.rdatatype +import dns.rrset from isctest.asyncserver import ( AsyncDnsServer, @@ -26,11 +26,11 @@ from isctest.asyncserver import ( QnameHandler, QnameQtypeHandler, QueryContext, - StaticResponseHandler, ResponseHandler, + StaticResponseHandler, ) -from resolver_ans import ( +from ..resolver_ans import ( DelegationHandler, Gl6412AHandler, Gl6412Handler, @@ -52,8 +52,8 @@ class BadGoodDnameNsHandler(QnameQtypeHandler, StaticResponseHandler): def _cname_rrsets( - qname: Union[dns.name.Name, str], -) -> Tuple[dns.rrset.RRset, dns.rrset.RRset]: + qname: dns.name.Name | str, +) -> tuple[dns.rrset.RRset, dns.rrset.RRset]: return ( rrset(qname, dns.rdatatype.CNAME, f"{qname}"), rrset(qname, dns.rdatatype.A, "1.2.3.4"), diff --git a/bin/tests/system/resolver/ans3/ans.py b/bin/tests/system/resolver/ans3/ans.py index bd21c9d4f7..8913186a70 100644 --- a/bin/tests/system/resolver/ans3/ans.py +++ b/bin/tests/system/resolver/ans3/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.name import dns.rcode @@ -25,11 +25,11 @@ from isctest.asyncserver import ( QnameHandler, QnameQtypeHandler, QueryContext, - StaticResponseHandler, ResponseHandler, + StaticResponseHandler, ) -from resolver_ans import ( +from ..resolver_ans import ( DelegationHandler, Gl6412AHandler, Gl6412Handler, diff --git a/bin/tests/system/resolver/ans8/ans.py b/bin/tests/system/resolver/ans8/ans.py index 25eac4247f..98929085bc 100644 --- a/bin/tests/system/resolver/ans8/ans.py +++ b/bin/tests/system/resolver/ans8/ans.py @@ -11,9 +11,9 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -import abc +from collections.abc import AsyncGenerator -from typing import AsyncGenerator +import abc import dns.flags import dns.message @@ -22,8 +22,8 @@ import dns.rdatatype from isctest.asyncserver import ( AsyncDnsServer, - DnsResponseSend, DnsProtocol, + DnsResponseSend, DomainHandler, QnameHandler, QnameQtypeHandler, @@ -32,7 +32,7 @@ from isctest.asyncserver import ( StaticResponseHandler, ) -from resolver_ans import rrset +from ..resolver_ans import rrset class HeaderOnlyHandler(ResponseHandler): diff --git a/bin/tests/system/resolver/resolver_ans.py b/bin/tests/system/resolver/resolver_ans.py index e5d7854fd9..e2bf2dc30b 100644 --- a/bin/tests/system/resolver/resolver_ans.py +++ b/bin/tests/system/resolver/resolver_ans.py @@ -11,7 +11,8 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator, List, NamedTuple, Union +from collections.abc import AsyncGenerator +from typing import NamedTuple import abc @@ -29,7 +30,7 @@ from isctest.asyncserver import ( def rrset( - qname: Union[dns.name.Name, str], + qname: dns.name.Name | str, rtype: dns.rdatatype.RdataType, rdata: str, ttl: int = 300, @@ -38,15 +39,15 @@ def rrset( def rrset_from_list( - qname: Union[dns.name.Name, str], + qname: dns.name.Name | str, rtype: dns.rdatatype.RdataType, - rdata_list: List[str], + rdata_list: list[str], ttl: int = 300, ) -> dns.rrset.RRset: return dns.rrset.from_text_list(qname, ttl, dns.rdataclass.IN, rtype, rdata_list) -def soa_rrset(qname: Union[dns.name.Name, str]) -> dns.rrset.RRset: +def soa_rrset(qname: dns.name.Name | str) -> dns.rrset.RRset: return rrset(qname, dns.rdatatype.SOA, ". . 0 0 0 0 0") @@ -56,9 +57,9 @@ class DelegationRRsets(NamedTuple): def delegation_rrsets( - owner: Union[dns.name.Name, str], + owner: dns.name.Name | str, server_number: int, - ns_name: Union[dns.name.Name, str, None] = None, + ns_name: dns.name.Name | str | None = None, ) -> DelegationRRsets: if ns_name is None: ns_name = f"ns.{owner}" @@ -68,7 +69,7 @@ def delegation_rrsets( def setup_delegation( - qctx: QueryContext, owner: Union[dns.name.Name, str], server_number: int + qctx: QueryContext, owner: dns.name.Name | str, server_number: int ) -> None: delegation = delegation_rrsets(owner, server_number) qctx.response.authority.append(delegation.ns_rrset) diff --git a/bin/tests/system/rfc5011/tests_rfc5011.py b/bin/tests/system/rfc5011/tests_rfc5011.py index 652293792b..35a73f14cd 100644 --- a/bin/tests/system/rfc5011/tests_rfc5011.py +++ b/bin/tests/system/rfc5011/tests_rfc5011.py @@ -10,6 +10,7 @@ # information regarding copyright ownership. import pytest + from isctest.mark import live_internet_test pytestmark = pytest.mark.extra_artifacts( diff --git a/bin/tests/system/rndc/tests_cve-2023-3341.py b/bin/tests/system/rndc/tests_cve_2023_3341.py similarity index 100% rename from bin/tests/system/rndc/tests_cve-2023-3341.py rename to bin/tests/system/rndc/tests_cve_2023_3341.py diff --git a/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_initial.py b/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_initial.py index 131933f40f..be4856710a 100644 --- a/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_initial.py +++ b/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_initial.py @@ -9,24 +9,15 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.util import param -from rollover.common import ( - pytestmark, - CDSS, - DURATION, - TIMEDELTA, - ALGOROLL_CONFIG, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_algo_csk, -) +from rollover.common import ALGOROLL_CONFIG, CDSS, DURATION, ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_algo_csk, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK POLICY = "csk-algoroll" diff --git a/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_reconfig.py b/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_reconfig.py index 8c7c2badba..abb1e257a4 100644 --- a/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_reconfig.py +++ b/bin/tests/system/rollover-algo-csk/tests_rollover_algo_csk_reconfig.py @@ -9,18 +9,11 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.kasp import KeyTimingMetadata from isctest.util import param from rollover.common import ( - pytestmark, - alg, - size, - CDSS, ALGOROLL_CONFIG, ALGOROLL_IPUB, ALGOROLL_IPUBC, @@ -29,14 +22,16 @@ from rollover.common import ( ALGOROLL_KEYTTLPROP, ALGOROLL_OFFSETS, ALGOROLL_OFFVAL, + CDSS, DURATION, + ROLLOVER_MARK, TIMEDELTA, ) -from rollover.setup import ( - configure_root, - configure_tld, - configure_algo_csk, -) +from rollover.setup import configure_algo_csk, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CONFIG = ALGOROLL_CONFIG POLICY = "csk-algoroll" @@ -90,7 +85,7 @@ def after_servers_start(ns3, templates): param("manual"), ], ) -def test_algoroll_csk_reconfig_step1(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step1(tld, ns3, default_algorithm): zone = f"step1.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -131,7 +126,7 @@ def test_algoroll_csk_reconfig_step1(tld, ns3, alg, size): # The RSASHA keys are outroducing. f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFVAL}", # The ECDSAP256SHA256 keys are introducing. - f"csk 0 {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], # Next key event is when the ecdsa256 keys have been propagated. "nextev": ALGOROLL_IPUB, @@ -146,7 +141,7 @@ def test_algoroll_csk_reconfig_step1(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_csk_reconfig_step2(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step2(tld, ns3, default_algorithm): zone = f"step2.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -164,7 +159,7 @@ def test_algoroll_csk_reconfig_step2(tld, ns3, alg, size): f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFVAL}", # The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is # omnipresent, but the zone signatures are not. - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{ALGOROLL_OFFSETS['step2']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{ALGOROLL_OFFSETS['step2']}", ], # Next key event is when all zone signatures are signed with the # new algorithm. This is the child publication interval, minus @@ -183,7 +178,7 @@ def test_algoroll_csk_reconfig_step2(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_csk_reconfig_step3(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step3(tld, ns3, default_algorithm): zone = f"step3.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -196,7 +191,7 @@ def test_algoroll_csk_reconfig_step3(tld, ns3, alg, size): "cdss": CDSS, "keyprops": [ f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step3']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step3']}", ], "manual-mode": True, "nextev": None, @@ -236,7 +231,7 @@ def test_algoroll_csk_reconfig_step3(tld, ns3, alg, size): "keyprops": [ # The DS can be swapped. f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:unretentive offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{ALGOROLL_OFFSETS['step3']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{ALGOROLL_OFFSETS['step3']}", ], # Next key event is when the DS becomes OMNIPRESENT. This happens # after the publication interval of the parent side. @@ -252,7 +247,7 @@ def test_algoroll_csk_reconfig_step3(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_csk_reconfig_step4(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step4(tld, ns3, default_algorithm): zone = f"step4.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -265,7 +260,7 @@ def test_algoroll_csk_reconfig_step4(tld, ns3, alg, size): "cdss": CDSS, "keyprops": [ f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", ], "manual-mode": True, "nextev": None, @@ -291,7 +286,7 @@ def test_algoroll_csk_reconfig_step4(tld, ns3, alg, size): "keyprops": [ # The old DS is HIDDEN, we can remove the old algorithm records. f"csk 0 8 2048 goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:unretentive ds:hidden offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", ], # Next key event is when the old DNSKEY becomes HIDDEN. # This happens after the DNSKEY TTL plus zone propagation delay. @@ -307,7 +302,7 @@ def test_algoroll_csk_reconfig_step4(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_csk_reconfig_step5(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step5(tld, ns3, default_algorithm): zone = f"step5.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -321,7 +316,7 @@ def test_algoroll_csk_reconfig_step5(tld, ns3, alg, size): "keyprops": [ # The DNSKEY becomes HIDDEN. f"csk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden zrrsig:unretentive ds:hidden offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", ], # Next key event is when the RSASHA signatures become HIDDEN. # This happens after the max-zone-ttl plus zone propagation delay @@ -341,7 +336,7 @@ def test_algoroll_csk_reconfig_step5(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_csk_reconfig_step6(tld, ns3, alg, size): +def test_algoroll_csk_reconfig_step6(tld, ns3, default_algorithm): zone = f"step6.csk-algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -355,7 +350,7 @@ def test_algoroll_csk_reconfig_step6(tld, ns3, alg, size): "keyprops": [ # The zone signatures are now HIDDEN. f"csk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{ALGOROLL_OFFVAL}", - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", ], # Next key event is never since we established the policy and the # keys have an unlimited lifetime. Fallback to the default diff --git a/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_initial.py b/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_initial.py index 2f74cd0fa4..ec3d880fe5 100644 --- a/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_initial.py +++ b/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_initial.py @@ -9,24 +9,15 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=unused-import - import pytest -import isctest from isctest.util import param -from rollover.common import ( - pytestmark, - CDSS, - DURATION, - TIMEDELTA, - ALGOROLL_CONFIG, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_algo_ksk_zsk, -) +from rollover.common import ALGOROLL_CONFIG, CDSS, DURATION, ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_algo_ksk_zsk, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK def bootstrap(): diff --git a/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_reconfig.py b/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_reconfig.py index cfac1739f8..9f472053dd 100644 --- a/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_reconfig.py +++ b/bin/tests/system/rollover-algo-ksk-zsk/tests_rollover_algo_ksk_zsk_reconfig.py @@ -9,18 +9,11 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.kasp import KeyTimingMetadata from isctest.util import param from rollover.common import ( - pytestmark, - alg, - size, - CDSS, ALGOROLL_CONFIG, ALGOROLL_IPUB, ALGOROLL_IPUBC, @@ -29,14 +22,16 @@ from rollover.common import ( ALGOROLL_KEYTTLPROP, ALGOROLL_OFFSETS, ALGOROLL_OFFVAL, + CDSS, DURATION, + ROLLOVER_MARK, TIMEDELTA, ) -from rollover.setup import ( - configure_root, - configure_tld, - configure_algo_ksk_zsk, -) +from rollover.setup import configure_algo_ksk_zsk, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CONFIG = ALGOROLL_CONFIG POLICY = "ecdsa256" @@ -88,7 +83,7 @@ def after_servers_start(ns3, templates): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step1(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step1(tld, ns3, default_algorithm): zone = f"step1.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -133,8 +128,8 @@ def test_algoroll_ksk_zsk_reconfig_step1(tld, ns3, alg, size): f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFVAL}", # The ECDSAP256SHA256 keys are introducing. - f"ksk 0 {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured", ], # Next key event is when the ecdsa256 keys have been propagated. "nextev": ALGOROLL_IPUB, @@ -149,7 +144,7 @@ def test_algoroll_ksk_zsk_reconfig_step1(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step2(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step2(tld, ns3, default_algorithm): zone = f"step2.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -168,8 +163,8 @@ def test_algoroll_ksk_zsk_reconfig_step2(tld, ns3, alg, size): f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFVAL}", # The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is # omnipresent, but the zone signatures are not. - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step2']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{ALGOROLL_OFFSETS['step2']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step2']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{ALGOROLL_OFFSETS['step2']}", ], # Next key event is when all zone signatures are signed with the new # algorithm. This is the max-zone-ttl plus zone propagation delay. But @@ -188,7 +183,7 @@ def test_algoroll_ksk_zsk_reconfig_step2(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, default_algorithm): zone = f"step3.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -202,8 +197,8 @@ def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, alg, size): "keyprops": [ f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step3']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step3']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFSETS['step3']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step3']}", ], "manual-mode": True, "nextev": None, @@ -244,8 +239,8 @@ def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, alg, size): # The DS can be swapped. f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{ALGOROLL_OFFSETS['step3']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step3']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{ALGOROLL_OFFSETS['step3']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step3']}", ], # Next key event is when the DS becomes OMNIPRESENT. This happens # after the retire interval. @@ -261,7 +256,7 @@ def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, default_algorithm): zone = f"step4.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -275,8 +270,8 @@ def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, alg, size): "keyprops": [ f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", ], "manual-mode": True, "nextev": None, @@ -306,8 +301,8 @@ def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, alg, size): # The old DS is HIDDEN, we can remove the old algorithm records. f"ksk 0 8 2048 goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:unretentive zrrsig:unretentive offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step4']}", ], # Next key event is when the old DNSKEY becomes HIDDEN. # This happens after the DNSKEY TTL plus zone propagation delay. @@ -323,7 +318,7 @@ def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step5(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step5(tld, ns3, default_algorithm): zone = f"step5.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -338,8 +333,8 @@ def test_algoroll_ksk_zsk_reconfig_step5(tld, ns3, alg, size): # The DNSKEY becomes HIDDEN. f"ksk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:hidden zrrsig:unretentive offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step5']}", ], # Next key event is when the RSASHA signatures become HIDDEN. # This happens after the max-zone-ttl plus zone propagation delay @@ -359,7 +354,7 @@ def test_algoroll_ksk_zsk_reconfig_step5(tld, ns3, alg, size): param("manual"), ], ) -def test_algoroll_ksk_zsk_reconfig_step6(tld, ns3, alg, size): +def test_algoroll_ksk_zsk_reconfig_step6(tld, ns3, default_algorithm): zone = f"step6.algorithm-roll.{tld}" policy = f"{POLICY}-{tld}" @@ -374,8 +369,8 @@ def test_algoroll_ksk_zsk_reconfig_step6(tld, ns3, alg, size): # The zone signatures are now HIDDEN. f"ksk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{ALGOROLL_OFFVAL}", f"zsk 0 8 2048 goal:hidden dnskey:hidden zrrsig:hidden offset:{ALGOROLL_OFFVAL}", - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", - f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", + f"zsk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{ALGOROLL_OFFSETS['step6']}", ], # Next key event is never since we established the policy and the # keys have an unlimited lifetime. Fallback to the default diff --git a/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py b/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py index b598cd6888..3ec2c18c75 100644 --- a/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py +++ b/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py @@ -9,26 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta import pytest -import isctest from isctest.kasp import Ipub, Iret from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - TIMEDELTA, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_cskroll1, -) +from rollover.common import ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_cskroll1, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CDSS = ["CDNSKEY", "CDS (SHA-384)"] CONFIG = { @@ -100,7 +92,7 @@ def bootstrap(): param("manual"), ], ) -def test_csk_roll1_step1(tld, ns3, alg, size): +def test_csk_roll1_step1(tld, ns3, default_algorithm): zone = f"step1.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -114,7 +106,7 @@ def test_csk_roll1_step1(tld, ns3, alg, size): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", ], # Next key event is when the successor CSK needs to be published # minus time already elapsed. This is Lcsk - Ipub + Dreg (we ignore @@ -131,7 +123,7 @@ def test_csk_roll1_step1(tld, ns3, alg, size): param("manual"), ], ) -def test_csk_roll1_step2(tld, alg, size, ns3): +def test_csk_roll1_step2(tld, ns3, default_algorithm): zone = f"step2.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -143,7 +135,7 @@ def test_csk_roll1_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", ], "manual-mode": True, "nextev": None, @@ -172,8 +164,8 @@ def test_csk_roll1_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{OFFSETS['step2-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{OFFSETS['step2-s']}", ], "keyrelationships": [0, 1], # Next key event is when the successor CSK becomes OMNIPRESENT. @@ -189,7 +181,7 @@ def test_csk_roll1_step2(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step3(tld, alg, size, ns3): +def test_csk_roll1_step3(tld, ns3, default_algorithm): zone = f"step3.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -201,8 +193,8 @@ def test_csk_roll1_step3(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step3-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step3-s']}", ], "keyrelationships": [0, 1], "manual-mode": True, @@ -253,8 +245,8 @@ def test_csk_roll1_step3(tld, alg, size, ns3): # CSK1 ds: omnipresent -> unretentive # CSK2 ds: hidden -> rumoured "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{OFFSETS['step3-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{OFFSETS['step3-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{OFFSETS['step3-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{OFFSETS['step3-s']}", ], "keyrelationships": [0, 1], # Next key event is when the predecessor DS has been replaced with @@ -276,7 +268,7 @@ def test_csk_roll1_step3(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step4(tld, alg, size, ns3): +def test_csk_roll1_step4(tld, ns3, default_algorithm): zone = f"step4.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -288,8 +280,8 @@ def test_csk_roll1_step4(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step4-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [0, 1], "manual-mode": True, @@ -321,8 +313,8 @@ def test_csk_roll1_step4(tld, alg, size, ns3): # CSK1 ds: unretentive -> hidden # CSK2 ds: rumoured -> omnipresent "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:unretentive zrrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step4-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:unretentive zrrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [0, 1], # Next key event is when the KRRSIG enters the HIDDEN state. @@ -341,7 +333,7 @@ def test_csk_roll1_step4(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step5(tld, alg, size, ns3): +def test_csk_roll1_step5(tld, ns3, default_algorithm): zone = f"step5.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -355,8 +347,8 @@ def test_csk_roll1_step5(tld, alg, size, ns3): # The predecessor KRRSIG records are now all hidden. # CSK1 krrsig: unretentive -> hidden "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:hidden zrrsig:unretentive ds:hidden offset:{OFFSETS['step5-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step5-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:hidden zrrsig:unretentive ds:hidden offset:{OFFSETS['step5-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step5-s']}", ], "keyrelationships": [0, 1], # Next key event is when the DNSKEY can be removed. This is when @@ -374,7 +366,7 @@ def test_csk_roll1_step5(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step6(tld, alg, size, ns3): +def test_csk_roll1_step6(tld, ns3, default_algorithm): zone = f"step6.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -392,8 +384,8 @@ def test_csk_roll1_step6(tld, alg, size, ns3): # CSK1 zrrsig: unretentive -> hidden # CSK2 zrrsig: rumoured -> omnipresent "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step6-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step6-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", ], "keyrelationships": [0, 1], # Next key event is when the DNSKEY enters the HIDDEN state. @@ -410,7 +402,7 @@ def test_csk_roll1_step6(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step7(tld, alg, size, ns3): +def test_csk_roll1_step7(tld, ns3, default_algorithm): zone = f"step7.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -423,8 +415,8 @@ def test_csk_roll1_step7(tld, alg, size, ns3): "cdss": CDSS, # The predecessor CSK is now completely HIDDEN. "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step7-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step7-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step7-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step7-s']}", ], "keyrelationships": [0, 1], # Next key event is when the new successor needs to be published. @@ -442,7 +434,7 @@ def test_csk_roll1_step7(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll1_step8(tld, alg, size, ns3): +def test_csk_roll1_step8(tld, ns3, default_algorithm): zone = f"step8.csk-roll1.{tld}" policy = f"{POLICY}-{tld}" @@ -454,7 +446,7 @@ def test_csk_roll1_step8(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step8-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step8-s']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover-csk-roll2/tests_rollover_csk_roll2.py b/bin/tests/system/rollover-csk-roll2/tests_rollover_csk_roll2.py index 983d382236..e0c9b119e3 100644 --- a/bin/tests/system/rollover-csk-roll2/tests_rollover_csk_roll2.py +++ b/bin/tests/system/rollover-csk-roll2/tests_rollover_csk_roll2.py @@ -9,26 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta import pytest -import isctest from isctest.kasp import Ipub, Iret from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - TIMEDELTA, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_cskroll2, -) +from rollover.common import ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_cskroll2, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CDSS = ["CDNSKEY", "CDS (SHA-256)", "CDS (SHA-384)"] CONFIG = { @@ -103,7 +95,7 @@ def bootstrap(): param("manual"), ], ) -def test_csk_roll2_step1(tld, alg, size, ns3): +def test_csk_roll2_step1(tld, ns3, default_algorithm): zone = f"step1.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -117,7 +109,7 @@ def test_csk_roll2_step1(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", ], # Next key event is when the successor CSK needs to be published # minus time already elapsed. This is Lcsk - Ipub + Dreg (we ignore @@ -134,7 +126,7 @@ def test_csk_roll2_step1(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step2(tld, alg, size, ns3): +def test_csk_roll2_step2(tld, ns3, default_algorithm): zone = f"step2.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -146,7 +138,7 @@ def test_csk_roll2_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", ], "manual-mode": True, "nextev": None, @@ -175,8 +167,8 @@ def test_csk_roll2_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{OFFSETS['step2-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{OFFSETS['step2-s']}", ], "keyrelationships": [0, 1], # Next key event is when the successor CSK becomes OMNIPRESENT. @@ -192,7 +184,7 @@ def test_csk_roll2_step2(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step3(tld, alg, size, ns3): +def test_csk_roll2_step3(tld, ns3, default_algorithm): zone = f"step3.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -204,8 +196,8 @@ def test_csk_roll2_step3(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step3-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step3-s']}", ], "keyrelationships": [0, 1], "manual-mode": True, @@ -256,8 +248,8 @@ def test_csk_roll2_step3(tld, alg, size, ns3): # CSK1 ds: omnipresent -> unretentive # CSK2 ds: hidden -> rumoured "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{OFFSETS['step3-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{OFFSETS['step3-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{OFFSETS['step3-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{OFFSETS['step3-s']}", ], "keyrelationships": [0, 1], # Next key event is when the predecessor DS has been replaced with @@ -279,7 +271,7 @@ def test_csk_roll2_step3(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step4(tld, alg, size, ns3): +def test_csk_roll2_step4(tld, ns3, default_algorithm): zone = f"step4.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -295,8 +287,8 @@ def test_csk_roll2_step4(tld, alg, size, ns3): # CSK1 zrrsig: unretentive -> hidden # CSK2 zrrsig: rumoured -> omnipresent "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:unretentive offset:{OFFSETS['step4-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step4-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:unretentive offset:{OFFSETS['step4-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step4-s']}", ], "keyrelationships": [0, 1], # Next key event is when the predecessor DS has been replaced with @@ -318,7 +310,7 @@ def test_csk_roll2_step4(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step5(tld, alg, size, ns3): +def test_csk_roll2_step5(tld, ns3, default_algorithm): zone = f"step5.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -330,8 +322,8 @@ def test_csk_roll2_step5(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", ], "keyrelationships": [0, 1], "manual-mode": True, @@ -364,8 +356,8 @@ def test_csk_roll2_step5(tld, alg, size, ns3): # The successor key is now fully OMNIPRESENT. # CSK2 ds: rumoured -> omnipresent "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", ], "keyrelationships": [0, 1], # Next key event is when the DNSKEY enters the HIDDEN state. @@ -382,7 +374,7 @@ def test_csk_roll2_step5(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step6(tld, alg, size, ns3): +def test_csk_roll2_step6(tld, ns3, default_algorithm): zone = f"step6.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -397,8 +389,8 @@ def test_csk_roll2_step6(tld, alg, size, ns3): # CSK1 dnskey: unretentive -> hidden # CSK1 krrsig: unretentive -> hidden "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step6-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step6-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", ], "keyrelationships": [0, 1], # Next key event is when the new successor needs to be published. @@ -415,7 +407,7 @@ def test_csk_roll2_step6(tld, alg, size, ns3): param("manual"), ], ) -def test_csk_roll2_step7(tld, alg, size, ns3): +def test_csk_roll2_step7(tld, ns3, default_algorithm): zone = f"step7.csk-roll2.{tld}" policy = f"{POLICY}-{tld}" @@ -428,8 +420,8 @@ def test_csk_roll2_step7(tld, alg, size, ns3): "cdss": CDSS, # The predecessor CSK is now completely HIDDEN. "keyprops": [ - f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step7-p']}", - f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step7-s']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step7-p']}", + f"csk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step7-s']}", ], "keyrelationships": [0, 1], "nextev": None, diff --git a/bin/tests/system/rollover-dynamic2inline/tests_rollover_dynamic2inline.py b/bin/tests/system/rollover-dynamic2inline/tests_rollover_dynamic2inline.py index 7ec8591195..eff0fedc99 100644 --- a/bin/tests/system/rollover-dynamic2inline/tests_rollover_dynamic2inline.py +++ b/bin/tests/system/rollover-dynamic2inline/tests_rollover_dynamic2inline.py @@ -9,19 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import +from rollover.common import CDSS, DEFAULT_CONFIG, ROLLOVER_MARK import isctest -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DEFAULT_CONFIG, -) + +pytestmark = ROLLOVER_MARK -def test_dynamic2inline(alg, size, ns3, templates): +def test_dynamic2inline(ns3, default_algorithm, templates): config = DEFAULT_CONFIG policy = "default" zone = "dynamic2inline.kasp" @@ -32,7 +27,7 @@ def test_dynamic2inline(alg, size, ns3, templates): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], "nextev": None, } diff --git a/bin/tests/system/rollover-enable-dnssec/tests_rollover_enable_dnssec.py b/bin/tests/system/rollover-enable-dnssec/tests_rollover_enable_dnssec.py index 23d47bdbb6..db9f018cc3 100644 --- a/bin/tests/system/rollover-enable-dnssec/tests_rollover_enable_dnssec.py +++ b/bin/tests/system/rollover-enable-dnssec/tests_rollover_enable_dnssec.py @@ -9,25 +9,16 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.kasp import Ipub, IpubC, Iret from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - TIMEDELTA, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_enable_dnssec, -) +from rollover.common import CDSS, ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_enable_dnssec, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CONFIG = { "dnskey-ttl": TIMEDELTA["PT5M"], @@ -83,7 +74,7 @@ def bootstrap(): param("manual"), ], ) -def test_rollover_enable_dnssec_step1(tld, alg, size, ns3): +def test_rollover_enable_dnssec_step1(tld, default_algorithm, ns3): zone = f"step1.enable-dnssec.{tld}" policy = f"{POLICY}-{tld}" @@ -114,7 +105,7 @@ def test_rollover_enable_dnssec_step1(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{OFFSETS['step1']}", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{OFFSETS['step1']}", ], # Next key event is when the DNSKEY RRset becomes OMNIPRESENT, # after the publication interval. @@ -130,7 +121,7 @@ def test_rollover_enable_dnssec_step1(tld, alg, size, ns3): param("manual"), ], ) -def test_rollover_enable_dnssec_step2(tld, alg, size, ns3): +def test_rollover_enable_dnssec_step2(tld, default_algorithm, ns3): zone = f"step2.enable-dnssec.{tld}" policy = f"{POLICY}-{tld}" @@ -146,7 +137,7 @@ def test_rollover_enable_dnssec_step2(tld, alg, size, ns3): # dnskey: rumoured -> omnipresent # krrsig: rumoured -> omnipresent "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{OFFSETS['step2']}", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{OFFSETS['step2']}", ], # Next key event is when the zone signatures become OMNIPRESENT, # Minus the time already elapsed. @@ -162,7 +153,7 @@ def test_rollover_enable_dnssec_step2(tld, alg, size, ns3): param("manual"), ], ) -def test_rollover_enable_dnssec_step3(tld, alg, size, ns3): +def test_rollover_enable_dnssec_step3(tld, default_algorithm, ns3): zone = f"step3.enable-dnssec.{tld}" policy = f"{POLICY}-{tld}" @@ -174,7 +165,7 @@ def test_rollover_enable_dnssec_step3(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{OFFSETS['step3']}", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{OFFSETS['step3']}", ], "manual-mode": True, "nextev": None, @@ -200,7 +191,7 @@ def test_rollover_enable_dnssec_step3(tld, alg, size, ns3): # zrrsig: rumoured -> omnipresent # ds: hidden -> rumoured "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step3']}", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step3']}", ], # Next key event is when the DS can move to the OMNIPRESENT state. # This is after the retire interval. @@ -216,7 +207,7 @@ def test_rollover_enable_dnssec_step3(tld, alg, size, ns3): param("manual"), ], ) -def test_rollover_enable_dnssec_step4(tld, alg, size, ns3): +def test_rollover_enable_dnssec_step4(tld, default_algorithm, ns3): zone = f"step4.enable-dnssec.{tld}" policy = f"{POLICY}-{tld}" @@ -230,7 +221,7 @@ def test_rollover_enable_dnssec_step4(tld, alg, size, ns3): # DS has been published long enough. # ds: rumoured -> omnipresent "keyprops": [ - f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4']}", + f"csk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4']}", ], # Next key event is never, the zone dnssec-policy has been # established. So we fall back to the default loadkeys interval. diff --git a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py index 92950124ed..599254d556 100644 --- a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py +++ b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py @@ -9,24 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest +from rollover.common import CDSS, DURATION, ROLLOVER_MARK, UNSIGNING_CONFIG +from rollover.setup import configure_going_insecure, configure_root, configure_tld + import isctest -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DURATION, - UNSIGNING_CONFIG, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_going_insecure, -) + +pytestmark = ROLLOVER_MARK def bootstrap(): @@ -53,7 +43,7 @@ def bootstrap(): "going-insecure-dynamic.kasp", ], ) -def test_going_insecure_initial(zone, ns3, alg, size): +def test_going_insecure_initial(zone, ns3, default_algorithm): config = UNSIGNING_CONFIG policy = "unsigning" zone = f"step1.{zone}" @@ -64,8 +54,8 @@ def test_going_insecure_initial(zone, ns3, alg, size): "zone": zone, "cdss": CDSS, "keyprops": [ - f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", - f"zsk {DURATION['P60D']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", + f"zsk {DURATION['P60D']} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py index 5cd8d65816..a5c05e1c13 100644 --- a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py +++ b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py @@ -9,25 +9,20 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from rollover.common import ( - pytestmark, - alg, - size, CDSS, DEFAULT_CONFIG, DURATION, + ROLLOVER_MARK, UNSIGNING_CONFIG, ) -from rollover.setup import ( - configure_root, - configure_tld, - configure_going_insecure, -) +from rollover.setup import configure_going_insecure, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK def bootstrap(): @@ -60,7 +55,7 @@ def after_servers_start(ns3, templates): "going-insecure-dynamic.kasp", ], ) -def test_going_insecure_reconfig_step1(zone, alg, size, ns3): +def test_going_insecure_reconfig_step1(zone, ns3, default_algorithm): config = DEFAULT_CONFIG policy = "insecure" zone = f"step1.{zone}" @@ -73,8 +68,8 @@ def test_going_insecure_reconfig_step1(zone, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"ksk 0 {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{-DURATION['P10D']}", - f"zsk {DURATION['P60D']} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{-DURATION['P10D']}", + f"zsk {DURATION['P60D']} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}", ], # Next key event is when the DS becomes HIDDEN. This # happens after the# parent propagation delay plus DS TTL. @@ -93,7 +88,7 @@ def test_going_insecure_reconfig_step1(zone, alg, size, ns3): "going-insecure-dynamic.kasp", ], ) -def test_going_insecure_reconfig_step2(zone, alg, size, ns3): +def test_going_insecure_reconfig_step2(zone, ns3, default_algorithm): config = DEFAULT_CONFIG policy = "insecure" zone = f"step2.{zone}" @@ -107,8 +102,8 @@ def test_going_insecure_reconfig_step2(zone, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"ksk 0 {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{-DURATION['P10D']}", - f"zsk {DURATION['P60D']} {alg} {size} goal:hidden dnskey:unretentive zrrsig:unretentive offset:{-DURATION['P10D']}", + f"ksk 0 {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{-DURATION['P10D']}", + f"zsk {DURATION['P60D']} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive zrrsig:unretentive offset:{-DURATION['P10D']}", ], # Next key event is when the DNSKEY becomes HIDDEN. # This happens after the propagation delay, plus DNSKEY TTL. diff --git a/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py b/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py index dbbf136149..f4c72f6bcd 100644 --- a/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py +++ b/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py @@ -9,26 +9,21 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta -import isctest from isctest.kasp import KeyTimingMetadata from rollover.common import ( - pytestmark, - alg, - size, KSK_CONFIG, - KSK_LIFETIME_POLICY, KSK_IPUB, KSK_IRET, + KSK_LIFETIME_POLICY, + ROLLOVER_MARK, ) -from rollover.setup import ( - configure_root, - configure_tld, - configure_ksk_3crowd, -) +from rollover.setup import configure_ksk_3crowd, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CDSS = ["CDS (SHA-256)"] POLICY = "ksk-doubleksk-autosign" @@ -54,7 +49,7 @@ def bootstrap(): return data -def test_rollover_ksk_three_is_a_crowd(alg, size, ns3): +def test_rollover_ksk_three_is_a_crowd(ns3, default_algorithm): """Test #2375: Scheduled rollovers are happening faster than they can finish.""" zone = "three-is-a-crowd.kasp" @@ -64,9 +59,9 @@ def test_rollover_ksk_three_is_a_crowd(alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}", ], "keyrelationships": [0, 1], } @@ -87,10 +82,10 @@ def test_rollover_ksk_three_is_a_crowd(alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:0", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:0", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}", ], "check-keytimes": False, # checked manually with modified values } diff --git a/bin/tests/system/rollover-ksk-doubleksk/tests_rollover_ksk_doubleksk.py b/bin/tests/system/rollover-ksk-doubleksk/tests_rollover_ksk_doubleksk.py index 46e8524295..eb73298bca 100644 --- a/bin/tests/system/rollover-ksk-doubleksk/tests_rollover_ksk_doubleksk.py +++ b/bin/tests/system/rollover-ksk-doubleksk/tests_rollover_ksk_doubleksk.py @@ -9,32 +9,27 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta import pytest -import isctest from isctest.util import param from rollover.common import ( - pytestmark, - alg, - size, KSK_CONFIG, - KSK_LIFETIME, - KSK_LIFETIME_POLICY, KSK_IPUB, KSK_IPUBC, KSK_IRET, KSK_KEYTTLPROP, + KSK_LIFETIME, + KSK_LIFETIME_POLICY, + ROLLOVER_MARK, TIMEDELTA, ) -from rollover.setup import ( - configure_root, - configure_tld, - configure_ksk_doubleksk, -) +from rollover.setup import configure_ksk_doubleksk, configure_root, configure_tld + +import isctest + +pytestmark = ROLLOVER_MARK CDSS = ["CDS (SHA-256)"] POLICY = "ksk-doubleksk" @@ -83,7 +78,7 @@ def bootstrap(): param("manual"), ], ) -def test_ksk_doubleksk_step1(tld, alg, size, ns3): +def test_ksk_doubleksk_step1(tld, ns3, default_algorithm): zone = f"step1.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -97,8 +92,8 @@ def test_ksk_doubleksk_step1(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step1-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step1-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", ], # Next key event is when the successor KSK needs to be published. # That is the KSK lifetime - prepublication time (minus time @@ -115,7 +110,7 @@ def test_ksk_doubleksk_step1(tld, alg, size, ns3): param("manual"), ], ) -def test_ksk_doubleksk_step2(tld, alg, size, ns3): +def test_ksk_doubleksk_step2(tld, ns3, default_algorithm): zone = f"step2.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -127,8 +122,8 @@ def test_ksk_doubleksk_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", ], "manual-mode": True, "nextev": None, @@ -156,9 +151,9 @@ def test_ksk_doubleksk_step2(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{OFFSETS['step2-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{OFFSETS['step2-s']}", ], "keyrelationships": [1, 2], # Next key event is when the successor KSK becomes OMNIPRESENT. @@ -174,7 +169,7 @@ def test_ksk_doubleksk_step2(tld, alg, size, ns3): param("manual"), ], ) -def test_ksk_doubleksk_step3(tld, alg, size, ns3): +def test_ksk_doubleksk_step3(tld, ns3, default_algorithm): zone = f"step3.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -186,9 +181,9 @@ def test_ksk_doubleksk_step3(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{OFFSETS['step3-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{OFFSETS['step3-s']}", ], "keyrelationships": [1, 2], "manual-mode": True, @@ -233,9 +228,9 @@ def test_ksk_doubleksk_step3(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSETS['step3-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSETS['step3-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSETS['step3-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSETS['step3-s']}", ], "keyrelationships": [1, 2], # Next key event is when the predecessor DS has been replaced with @@ -254,7 +249,7 @@ def test_ksk_doubleksk_step3(tld, alg, size, ns3): param("manual"), ], ) -def test_ksk_doubleksk_step4(tld, alg, size, ns3): +def test_ksk_doubleksk_step4(tld, ns3, default_algorithm): zone = f"step4.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -266,9 +261,9 @@ def test_ksk_doubleksk_step4(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{OFFSETS['step4-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{OFFSETS['step4-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [1, 2], "manual-mode": True, @@ -301,9 +296,9 @@ def test_ksk_doubleksk_step4(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [1, 2], # Next key event is when the DNSKEY enters the HIDDEN state. @@ -320,7 +315,7 @@ def test_ksk_doubleksk_step4(tld, alg, size, ns3): param("manual"), ], ) -def test_ksk_doubleksk_step5(tld, alg, size, ns3): +def test_ksk_doubleksk_step5(tld, ns3, default_algorithm): zone = f"step5.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -336,9 +331,9 @@ def test_ksk_doubleksk_step5(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step5-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step5-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}", ], "keyrelationships": [1, 2], # Next key event is when the new successor needs to be published. @@ -355,7 +350,7 @@ def test_ksk_doubleksk_step5(tld, alg, size, ns3): param("manual"), ], ) -def test_ksk_doubleksk_step6(tld, alg, size, ns3): +def test_ksk_doubleksk_step6(tld, ns3, default_algorithm): zone = f"step6.ksk-doubleksk.{tld}" policy = f"{POLICY}-{tld}" @@ -368,8 +363,8 @@ def test_ksk_doubleksk_step6(tld, alg, size, ns3): "zone": zone, "cdss": CDSS, "keyprops": [ - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step6-p']}", - f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step6-p']}", + f"ksk {KSK_LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_initial.py b/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_initial.py index a7f5ead0fa..5c63d85283 100644 --- a/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_initial.py +++ b/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_initial.py @@ -9,20 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DEFAULT_CONFIG, - DURATION, -) +from rollover.common import CDSS, DEFAULT_CONFIG, DURATION, ROLLOVER_MARK + +import isctest + +pytestmark = ROLLOVER_MARK @pytest.mark.parametrize( @@ -34,7 +28,7 @@ from rollover.common import ( param("unlimit-lifetime", "short-lifetime", "P6M"), ], ) -def test_lifetime_initial(zone, policy, lifetime, alg, size, ns3): +def test_lifetime_initial(zone, policy, lifetime, ns3, default_algorithm): config = DEFAULT_CONFIG isctest.kasp.wait_keymgr_done(ns3, f"{zone}.kasp") @@ -43,7 +37,7 @@ def test_lifetime_initial(zone, policy, lifetime, alg, size, ns3): "zone": f"{zone}.kasp", "cdss": CDSS, "keyprops": [ - f"csk {DURATION[lifetime]} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk {DURATION[lifetime]} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], "nextev": None, } diff --git a/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_reconfig.py b/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_reconfig.py index d28a7e4cd5..894980f8ac 100644 --- a/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_reconfig.py +++ b/bin/tests/system/rollover-lifetime/tests_rollover_lifetime_reconfig.py @@ -9,20 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest -import isctest from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DEFAULT_CONFIG, - DURATION, -) +from rollover.common import CDSS, DEFAULT_CONFIG, DURATION, ROLLOVER_MARK + +import isctest + +pytestmark = ROLLOVER_MARK @pytest.fixture(scope="module", autouse=True) @@ -49,7 +43,7 @@ def after_servers_start(ns3, templates): param("unlimit-lifetime", "unlimited-lifetime", 0), ], ) -def test_lifetime_reconfig(zone, policy, lifetime, alg, size, ns3): +def test_lifetime_reconfig(zone, policy, lifetime, ns3, default_algorithm): config = DEFAULT_CONFIG isctest.kasp.wait_keymgr_done(ns3, f"{zone}.kasp", reconfig=True) @@ -58,7 +52,7 @@ def test_lifetime_reconfig(zone, policy, lifetime, alg, size, ns3): "zone": f"{zone}.kasp", "cdss": CDSS, "keyprops": [ - f"csk {DURATION[lifetime]} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk {DURATION[lifetime]} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], "nextev": None, } diff --git a/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py b/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py index 02c43ab459..f104a2aa3a 100644 --- a/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py +++ b/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py @@ -9,26 +9,21 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta + import os -import pytest - -import dns import dns.update -import isctest from isctest.kasp import Iret from isctest.run import EnvCmd -from rollover.common import ( - pytestmark, - alg, - size, -) +from rollover.common import ROLLOVER_MARK from rollover.setup import fake_lifetime, render_and_sign_zone +import isctest + +pytestmark = ROLLOVER_MARK + def bootstrap(): templates = isctest.template.TemplateEngine(".") @@ -93,7 +88,7 @@ def bootstrap(): return {} -def test_rollover_multisigner(ns3, alg, size): +def test_rollover_multisigner(ns3, default_algorithm): policy = "multisigner-model2" config = { "dnskey-ttl": timedelta(hours=1), @@ -115,7 +110,7 @@ def test_rollover_multisigner(ns3, alg, size): keygen_command = [ os.environ.get("KEYGEN"), "-a", - alg, + default_algorithm.name, "-L", "3600", "-M", @@ -132,15 +127,17 @@ def test_rollover_multisigner(ns3, alg, size): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured tag-range:32768-65535", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:rumoured tag-range:32768-65535", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) - newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"] + newprops = [ + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} tag-range:0-32767" + ] expected2 = isctest.kasp.policy_to_properties(ttl, newprops) - expected2[0].private = False # noqa - expected2[0].legacy = True # noqa + expected2[0].private = False + expected2[0].legacy = True expected = expected + expected2 ownkeys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) @@ -161,10 +158,12 @@ def test_rollover_multisigner(ns3, alg, size): # Update zone with ZSK from another provider for zone. out = keygen(zone) newkeys = isctest.kasp.keystr_to_keylist(out) - newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"] + newprops = [ + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} tag-range:0-32767" + ] expected2 = isctest.kasp.policy_to_properties(ttl, newprops) - expected2[0].private = False # noqa - expected2[0].legacy = True # noqa + expected2[0].private = False + expected2[0].legacy = True expected = expected + expected2 dnskey = newkeys[0].dnskey @@ -208,10 +207,10 @@ def test_rollover_multisigner(ns3, alg, size): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden tag-range:32768-65535", - f"ksk unlimited {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent tag-range:0-32767 offset:{offval}", - f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent tag-range:0-32767 offset:{offval}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden tag-range:32768-65535", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent tag-range:0-32767 offset:{offval}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent tag-range:0-32767 offset:{offval}", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) diff --git a/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_initial.py b/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_initial.py index c38e5ddd49..f25700281c 100644 --- a/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_initial.py +++ b/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_initial.py @@ -9,24 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest +from rollover.common import CDSS, DEFAULT_CONFIG, DURATION, ROLLOVER_MARK +from rollover.setup import configure_root, configure_straight2none, configure_tld + import isctest -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DURATION, - DEFAULT_CONFIG, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_straight2none, -) + +pytestmark = ROLLOVER_MARK def bootstrap(): @@ -53,7 +43,7 @@ def bootstrap(): "going-straight-to-none-dynamic.kasp", ], ) -def test_straight2none_initial(zone, ns3, alg, size): +def test_straight2none_initial(zone, ns3, default_algorithm): config = DEFAULT_CONFIG policy = "default" @@ -63,7 +53,7 @@ def test_straight2none_initial(zone, ns3, alg, size): "zone": zone, "cdss": CDSS, "keyprops": [ - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_reconfig.py b/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_reconfig.py index 5cfb49653b..6738ee8bd2 100644 --- a/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_reconfig.py +++ b/bin/tests/system/rollover-straight2none/tests_rollover_straight2none_reconfig.py @@ -9,24 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - import pytest +from rollover.common import CDSS, DEFAULT_CONFIG, DURATION, ROLLOVER_MARK +from rollover.setup import configure_root, configure_straight2none, configure_tld + import isctest -from rollover.common import ( - pytestmark, - alg, - size, - CDSS, - DURATION, - DEFAULT_CONFIG, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_straight2none, -) + +pytestmark = ROLLOVER_MARK def bootstrap(): @@ -62,7 +52,7 @@ def after_servers_start(ns3, templates): "going-straight-to-none-dynamic.kasp", ], ) -def test_straight2none_reconfig(zone, ns3, alg, size): +def test_straight2none_reconfig(zone, ns3, default_algorithm): config = DEFAULT_CONFIG policy = None @@ -72,7 +62,7 @@ def test_straight2none_reconfig(zone, ns3, alg, size): # These zones will go bogus after signatures expire, but # remain validly signed for now. "keyprops": [ - f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", + f"csk 0 {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py b/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py index 31e0b99e43..b5070e8647 100644 --- a/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py +++ b/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py @@ -9,26 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=redefined-outer-name,unused-import - from datetime import timedelta import pytest -import isctest from isctest.kasp import Ipub, Iret from isctest.util import param -from rollover.common import ( - pytestmark, - alg, - size, - TIMEDELTA, -) -from rollover.setup import ( - configure_root, - configure_tld, - configure_zsk_prepub, -) +from rollover.common import ROLLOVER_MARK, TIMEDELTA +from rollover.setup import configure_root, configure_tld, configure_zsk_prepub + +import isctest + +pytestmark = ROLLOVER_MARK CONFIG = { "dnskey-ttl": TIMEDELTA["PT1H"], @@ -93,7 +85,7 @@ def bootstrap(): param("manual"), ], ) -def test_zsk_prepub_step1(tld, alg, size, ns3): +def test_zsk_prepub_step1(tld, ns3, default_algorithm): zone = f"step1.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -106,8 +98,8 @@ def test_zsk_prepub_step1(tld, alg, size, ns3): # Introduce the first key. This will immediately be active. "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step1-p']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step1-p']}", ], # Next key event is when the successor ZSK needs to be published. # That is the ZSK lifetime - prepublication time (minus time @@ -124,7 +116,7 @@ def test_zsk_prepub_step1(tld, alg, size, ns3): param("manual"), ], ) -def test_zsk_prepub_step2(tld, alg, size, ns3): +def test_zsk_prepub_step2(tld, ns3, default_algorithm): zone = f"step2.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -135,8 +127,8 @@ def test_zsk_prepub_step2(tld, alg, size, ns3): step = { "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", ], "manual-mode": True, "nextev": None, @@ -162,9 +154,9 @@ def test_zsk_prepub_step2(tld, alg, size, ns3): # zsk2 dnskey: hidden -> rumoured "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:{OFFSETS['step2-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:{OFFSETS['step2-s']}", ], "keyrelationships": [1, 2], # next key event is when the successor zsk becomes omnipresent. @@ -181,7 +173,7 @@ def test_zsk_prepub_step2(tld, alg, size, ns3): param("manual"), ], ) -def test_zsk_prepub_step3(tld, alg, size, ns3): +def test_zsk_prepub_step3(tld, ns3, default_algorithm): zone = f"step3.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -192,9 +184,9 @@ def test_zsk_prepub_step3(tld, alg, size, ns3): step = { "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step3-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step3-s']}", ], "keyrelationships": [1, 2], "manual-mode": True, @@ -236,9 +228,9 @@ def test_zsk_prepub_step3(tld, alg, size, ns3): # zsk2 zrrsig: hidden -> rumoured "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:unretentive offset:{OFFSETS['step3-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{OFFSETS['step3-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:unretentive offset:{OFFSETS['step3-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{OFFSETS['step3-s']}", ], "keyrelationships": [1, 2], # next key event is when all the rrsig records have been replaced @@ -268,7 +260,7 @@ def test_zsk_prepub_step3(tld, alg, size, ns3): param("manual"), ], ) -def test_zsk_prepub_step4(tld, alg, size, ns3): +def test_zsk_prepub_step4(tld, ns3, default_algorithm): zone = f"step4.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -279,9 +271,9 @@ def test_zsk_prepub_step4(tld, alg, size, ns3): step = { "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step4-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step4-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [1, 2], "manual-mode": True, @@ -310,9 +302,9 @@ def test_zsk_prepub_step4(tld, alg, size, ns3): # zsk2 zrrsig: rumoured -> omnipresent "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive zrrsig:hidden offset:{OFFSETS['step4-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:unretentive zrrsig:hidden offset:{OFFSETS['step4-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-s']}", ], "keyrelationships": [1, 2], # next key event is when the dnskey enters the hidden state. @@ -329,7 +321,7 @@ def test_zsk_prepub_step4(tld, alg, size, ns3): param("manual"), ], ) -def test_zsk_prepub_step5(tld, alg, size, ns3): +def test_zsk_prepub_step5(tld, ns3, default_algorithm): zone = f"step5.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -342,9 +334,9 @@ def test_zsk_prepub_step5(tld, alg, size, ns3): # zsk1 dnskey: unretentive -> hidden "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden zrrsig:hidden offset:{OFFSETS['step5-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step5-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:hidden zrrsig:hidden offset:{OFFSETS['step5-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step5-s']}", ], "keyrelationships": [1, 2], # next key event is when the new successor needs to be published. @@ -362,7 +354,7 @@ def test_zsk_prepub_step5(tld, alg, size, ns3): param("manual"), ], ) -def test_zsk_prepub_step6(tld, alg, size, ns3): +def test_zsk_prepub_step6(tld, ns3, default_algorithm): zone = f"step6.zsk-prepub.{tld}" policy = f"{POLICY}-{tld}" @@ -374,8 +366,8 @@ def test_zsk_prepub_step6(tld, alg, size, ns3): # predecessor zsk is now purged. "zone": zone, "keyprops": [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-p']}", - f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step6-s']}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-p']}", + f"zsk {LIFETIME_POLICY} {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step6-s']}", ], "nextev": None, } diff --git a/bin/tests/system/rollover/common.py b/bin/tests/system/rollover/common.py index 6fa054a1d7..0b0eedf0eb 100644 --- a/bin/tests/system/rollover/common.py +++ b/bin/tests/system/rollover/common.py @@ -10,14 +10,12 @@ # information regarding copyright ownership. from datetime import timedelta -import os import pytest from isctest.kasp import Ipub, IpubC, Iret -from isctest.vars.algorithms import Algorithm -pytestmark = pytest.mark.extra_artifacts( +ROLLOVER_MARK = pytest.mark.extra_artifacts( [ "*.axfr*", "dig.out*", @@ -130,21 +128,3 @@ KSK_IPUB = Ipub(KSK_CONFIG) KSK_IPUBC = IpubC(KSK_CONFIG) KSK_IRET = Iret(KSK_CONFIG, zsk=False, ksk=True) KSK_KEYTTLPROP = KSK_CONFIG["dnskey-ttl"] + KSK_CONFIG["zone-propagation-delay"] - - -@pytest.fixture -def alg(): - return os.environ["DEFAULT_ALGORITHM_NUMBER"] - - -@pytest.fixture -def size(): - return os.environ["DEFAULT_BITS"] - - -def default_algorithm(): - return Algorithm( - os.environ["DEFAULT_ALGORITHM"], - int(os.environ["DEFAULT_ALGORITHM_NUMBER"]), - int(os.environ["DEFAULT_BITS"]), - ) diff --git a/bin/tests/system/rollover/setup.py b/bin/tests/system/rollover/setup.py index ed4b0d1289..840e7aa937 100644 --- a/bin/tests/system/rollover/setup.py +++ b/bin/tests/system/rollover/setup.py @@ -10,18 +10,18 @@ # information regarding copyright ownership. import shutil -from typing import List + +from isctest.kasp import private_type_record +from isctest.run import EnvCmd +from isctest.template import Nameserver, TrustAnchor, Zone +from isctest.vars.algorithms import Algorithm import isctest -from isctest.kasp import private_type_record -from isctest.template import Nameserver, TrustAnchor, Zone -from isctest.run import EnvCmd -from rollover.common import default_algorithm -def configure_tld(zonename: str, delegations: List[Zone]) -> Zone: +def configure_tld(zonename: str, delegations: list[Zone]) -> Zone: templates = isctest.template.TemplateEngine(".") - alg = default_algorithm() + alg = Algorithm.default() keygen = EnvCmd("KEYGEN", f"-q -a {alg.number} -b {alg.bits} -L 3600") signer = EnvCmd("SIGNER", "-S -g") @@ -53,9 +53,9 @@ def configure_tld(zonename: str, delegations: List[Zone]) -> Zone: return Zone(zonename, f"{outfile}.signed", Nameserver("ns2", "10.53.0.2")) -def configure_root(delegations: List[Zone]) -> TrustAnchor: +def configure_root(delegations: list[Zone]) -> TrustAnchor: templates = isctest.template.TemplateEngine(".") - alg = default_algorithm() + alg = Algorithm.default() keygen = EnvCmd("KEYGEN", f"-q -a {alg.number} -b {alg.bits} -L 3600") signer = EnvCmd("SIGNER", "-S -g") @@ -108,7 +108,7 @@ def set_key_relationship(key1: str, key2: str): def render_and_sign_zone( - zonename: str, keys: List[str], signing: bool = True, extra_options: str = "" + zonename: str, keys: list[str], signing: bool = True, extra_options: str = "" ): dnskeys = [] privaterrs = [] @@ -135,7 +135,7 @@ def render_and_sign_zone( ) -def configure_algo_csk(tld: str, policy: str, reconfig: bool = False) -> List[Zone]: +def configure_algo_csk(tld: str, policy: str, reconfig: bool = False) -> list[Zone]: # The zones at csk-algorithm-roll.$tld represent the various steps # of a CSK algorithm rollover. zones = [] @@ -283,7 +283,7 @@ def configure_algo_csk(tld: str, policy: str, reconfig: bool = False) -> List[Zo return zones -def configure_algo_ksk_zsk(tld: str, reconfig: bool = False) -> List[Zone]: +def configure_algo_ksk_zsk(tld: str, reconfig: bool = False) -> list[Zone]: # The zones at algorithm-roll.$tld represent the various steps of a ZSK/KSK # algorithm rollover. zones = [] @@ -539,7 +539,7 @@ def configure_algo_ksk_zsk(tld: str, reconfig: bool = False) -> List[Zone]: return zones -def configure_cskroll1(tld: str, policy: str) -> List[Zone]: +def configure_cskroll1(tld: str, policy: str) -> list[Zone]: # The zones at csk-roll1.$tld represent the various steps of a CSK rollover # (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). zones = [] @@ -868,7 +868,7 @@ def configure_cskroll1(tld: str, policy: str) -> List[Zone]: return zones -def configure_cskroll2(tld: str, policy: str) -> List[Zone]: +def configure_cskroll2(tld: str, policy: str) -> list[Zone]: # The zones at csk-roll2.$tld represent the various steps of a CSK rollover # (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). # This scenario differs from the csk-roll1 one because the zone signatures (ZRRSIG) @@ -1212,7 +1212,7 @@ def configure_cskroll2(tld: str, policy: str) -> List[Zone]: return zones -def configure_enable_dnssec(tld: str, policy: str) -> List[Zone]: +def configure_enable_dnssec(tld: str, policy: str) -> list[Zone]: # The zones at enable-dnssec.$tld represent the various steps of the # initial signing of a zone. zones = [] @@ -1292,7 +1292,7 @@ def configure_enable_dnssec(tld: str, policy: str) -> List[Zone]: return zones -def configure_going_insecure(tld: str, reconfig: bool = False) -> List[Zone]: +def configure_going_insecure(tld: str, reconfig: bool = False) -> list[Zone]: zones = [] keygen = EnvCmd("KEYGEN", "-a ECDSA256 -L 7200") settime = EnvCmd("SETTIME", "-s") @@ -1360,7 +1360,7 @@ def configure_going_insecure(tld: str, reconfig: bool = False) -> List[Zone]: return zones -def configure_straight2none(tld: str) -> List[Zone]: +def configure_straight2none(tld: str) -> list[Zone]: # These zones are going straight to "none" policy. This is undefined behavior. zones = [] keygen = EnvCmd("KEYGEN", "-k default") @@ -1399,7 +1399,7 @@ def configure_straight2none(tld: str) -> List[Zone]: return zones -def configure_ksk_doubleksk(tld: str) -> List[Zone]: +def configure_ksk_doubleksk(tld: str) -> list[Zone]: # The zones at ksk-doubleksk.$tld represent the various steps of a KSK # Double-KSK rollover. zones = [] @@ -1666,7 +1666,7 @@ def configure_ksk_doubleksk(tld: str) -> List[Zone]: return zones -def configure_ksk_3crowd(tld: str) -> List[Zone]: +def configure_ksk_3crowd(tld: str) -> list[Zone]: # Test #2375, the "three is a crowd" bug, where a new key is introduced but the # previous rollover has not finished yet. In other words, we have a key KEY2 # that is the successor of key KEY1, and we introduce a new key KEY3 that is @@ -1727,7 +1727,7 @@ def configure_ksk_3crowd(tld: str) -> List[Zone]: return zones -def configure_zsk_prepub(tld: str) -> List[Zone]: +def configure_zsk_prepub(tld: str) -> list[Zone]: # The zones at zsk-prepub.$tld represent the various steps of a ZSK # Pre-Publication rollover. zones = [] diff --git a/bin/tests/system/rollover/tests_rollover_manual.py b/bin/tests/system/rollover/tests_rollover_manual.py index f2c9871f4d..80a00ada30 100644 --- a/bin/tests/system/rollover/tests_rollover_manual.py +++ b/bin/tests/system/rollover/tests_rollover_manual.py @@ -10,24 +10,23 @@ # information regarding copyright ownership. from datetime import timedelta -import os + +from isctest.kasp import Ipub, Iret, KeyTimingMetadata, private_type_record +from isctest.run import EnvCmd +from isctest.template import Nameserver, Zone +from isctest.vars.algorithms import Algorithm +from rollover.setup import configure_root, configure_tld import isctest -from isctest.kasp import KeyTimingMetadata, Ipub, Iret, private_type_record -from isctest.template import Nameserver, Zone -from isctest.run import EnvCmd - -from rollover.common import default_algorithm -from rollover.setup import ( - configure_root, - configure_tld, -) def setup_zone(zone, ksk_time, ksk_settime, zsk_time, zsk_settime) -> Zone: templates = isctest.template.TemplateEngine(".") - alg = default_algorithm() - keygen = EnvCmd("KEYGEN", f"-q -a {alg.number} -b {alg.bits} -L 3600") + default_algorithm = Algorithm.default() + keygen = EnvCmd( + "KEYGEN", + f"-q -a {default_algorithm.number} -b {default_algorithm.bits} -L 3600", + ) signer = EnvCmd("SIGNER", "-S -g") settime = EnvCmd("SETTIME", "-s") @@ -109,10 +108,8 @@ CONFIG = { POLICY = "manual-rollover" -def test_rollover_manual(ns3): +def test_rollover_manual(ns3, default_algorithm): ttl = int(CONFIG["dnskey-ttl"].total_seconds()) - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] zone = "manual-rollover.kasp" isctest.kasp.wait_keymgr_done(ns3, zone) @@ -120,8 +117,8 @@ def test_rollover_manual(ns3): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) @@ -168,9 +165,9 @@ def test_rollover_manual(ns3): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) @@ -210,10 +207,10 @@ def test_rollover_manual(ns3): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", - f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) @@ -234,10 +231,8 @@ def test_rollover_manual(ns3): assert "key is not actively signing" in response.out -def test_rollover_manual_zrrsig_rumoured(ns3): +def test_rollover_manual_zrrsig_rumoured(ns3, default_algorithm): ttl = int(CONFIG["dnskey-ttl"].total_seconds()) - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] zone = "manual-rollover-zrrsig-rumoured.kasp" isctest.kasp.wait_keymgr_done(ns3, zone) @@ -247,8 +242,8 @@ def test_rollover_manual_zrrsig_rumoured(ns3): koffset = -int(timedelta(days=7).total_seconds()) zoffset = -int(timedelta(hours=2).total_seconds()) key_properties = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) @@ -276,10 +271,10 @@ def test_rollover_manual_zrrsig_rumoured(ns3): isctest.kasp.check_dnssec_verify(ns3, zone) key_properties = [ - f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", + f"ksk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", # Predecessor DNSKEY must stay until successor ZSK is fully omnipresent. - f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", - f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:0", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:hidden dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", + f"zsk unlimited {default_algorithm.number} {default_algorithm.bits} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:0", ] expected = isctest.kasp.policy_to_properties(ttl, key_properties) keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) diff --git a/bin/tests/system/rpzextra/tests_rpzextra.py b/bin/tests/system/rpzextra/tests_rpzextra.py index dc2353d039..904c6f03ac 100644 --- a/bin/tests/system/rpzextra/tests_rpzextra.py +++ b/bin/tests/system/rpzextra/tests_rpzextra.py @@ -13,11 +13,9 @@ import os -import pytest - -import dns import dns.rcode import dns.rrset +import pytest import isctest diff --git a/bin/tests/system/rpzrecurse/ans5/ans.py b/bin/tests/system/rpzrecurse/ans5/ans.py index 6eed86d7f4..576f9d0f06 100644 --- a/bin/tests/system/rpzrecurse/ans5/ans.py +++ b/bin/tests/system/rpzrecurse/ans5/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype diff --git a/bin/tests/system/selftest/tests_zone_analyzer.py b/bin/tests/system/selftest/tests_zone_analyzer.py index 90f76b8416..6114134428 100755 --- a/bin/tests/system/selftest/tests_zone_analyzer.py +++ b/bin/tests/system/selftest/tests_zone_analyzer.py @@ -14,16 +14,16 @@ isctest.name.ZoneAnalyzer self-test Generate insane test zone and check expected output of ZoneAnalyzer utility class """ -import collections -import itertools from pathlib import Path -import dns -import dns.name +import collections +import itertools + from dns.name import Name + +import dns.name import pytest -import isctest import isctest.name # set of properies present in the tested zone - read by tests_zone_analyzer.py diff --git a/bin/tests/system/shutdown/tests_shutdown.py b/bin/tests/system/shutdown/tests_shutdown.py index 2b5b9d5220..aaa7cbad77 100755 --- a/bin/tests/system/shutdown/tests_shutdown.py +++ b/bin/tests/system/shutdown/tests_shutdown.py @@ -12,17 +12,16 @@ # information regarding copyright ownership. from concurrent.futures import ThreadPoolExecutor, as_completed +from string import ascii_lowercase as letters + import os import random import signal import subprocess -from string import ascii_lowercase as letters import time -import pytest - -import dns import dns.exception +import pytest import isctest diff --git a/bin/tests/system/sortlist/tests_sortlist.py b/bin/tests/system/sortlist/tests_sortlist.py index f5c68c86af..a9ce201c33 100644 --- a/bin/tests/system/sortlist/tests_sortlist.py +++ b/bin/tests/system/sortlist/tests_sortlist.py @@ -10,7 +10,7 @@ # information regarding copyright ownership. import dns.message - +import dns.rrset import pytest import isctest diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl index d4a0b40b5b..3eafa7d058 100755 --- a/bin/tests/system/start.pl +++ b/bin/tests/system/start.pl @@ -325,7 +325,7 @@ sub construct_ans_command { if (-e "$testdir/$server/ans.py") { $ENV{'PYTHONPATH'} = $testdir . ":" . $builddir; - $command = "$PYTHON -u ans.py 10.53.0.$n $queryport"; + $command = "$PYTHON -u -m $test.$server.ans 10.53.0.$n $queryport"; } elsif (-e "$testdir/$server/ans.pl") { $command = "$PERL ans.pl"; } else { diff --git a/bin/tests/system/statistics/ans4/ans.py b/bin/tests/system/statistics/ans4/ans.py index 52e0a00d50..dd16e4c471 100644 --- a/bin/tests/system/statistics/ans4/ans.py +++ b/bin/tests/system/statistics/ans4/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype diff --git a/util/get-running-system-tests.py b/bin/tests/system/statschannel/__init__.py old mode 100755 new mode 100644 similarity index 50% rename from util/get-running-system-tests.py rename to bin/tests/system/statschannel/__init__.py index 1653e0a66d..6ba22b927a --- a/util/get-running-system-tests.py +++ b/bin/tests/system/statschannel/__init__.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # SPDX-License-Identifier: MPL-2.0 @@ -11,15 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -import psutil -for pid in psutil.pids(): - try: - environ = psutil.Process(pid).environ() - if "PYTEST_CURRENT_TEST" in environ: - name = psutil.Process(pid).name() - print( - f'pytest process {name}/{pid} running: {environ["PYTEST_CURRENT_TEST"]}' - ) - except (psutil.AccessDenied, psutil.NoSuchProcess): - pass +import pytest + +pytest.register_assert_rewrite("generic") diff --git a/bin/tests/system/statschannel/generic.py b/bin/tests/system/statschannel/generic.py index fa64f5c483..0b0ee82de0 100644 --- a/bin/tests/system/statschannel/generic.py +++ b/bin/tests/system/statschannel/generic.py @@ -9,19 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from datetime import datetime, timedelta from collections import defaultdict +from datetime import datetime, timedelta from time import sleep + import os import dns.message -import dns.query -import dns.rcode import isctest # ISO datetime format without msec -fmt = "%Y-%m-%dT%H:%M:%SZ" +FMT = "%Y-%m-%dT%H:%M:%SZ" # The constants were taken from BIND 9 source code (lib/dns/zone.c) max_refresh = timedelta(seconds=2419200) # 4 weeks @@ -29,7 +28,7 @@ max_expires = timedelta(seconds=14515200) # 24 weeks dayzero = datetime.utcfromtimestamp(0).replace(microsecond=0) # Wait for the secondary zone files to appear to extract their mtime -max_secondary_zone_waittime_sec = 5 +MAX_SECONDARY_ZONE_WAITTIME_SEC = 5 # Generic helper functions @@ -45,7 +44,7 @@ def check_refresh(refresh, min_time, max_time): def check_loaded(loaded, expected, now): # Sanity check the zone timers values - assert (loaded - expected).total_seconds() < max_secondary_zone_waittime_sec + assert (loaded - expected).total_seconds() < MAX_SECONDARY_ZONE_WAITTIME_SEC assert loaded <= now @@ -69,7 +68,7 @@ def check_manykeys(name, zone=None): def zone_mtime(zonedir, name): try: - si = os.stat(os.path.join(zonedir, "{}.db".format(name))) + si = os.stat(os.path.join(zonedir, f"{name}.db")) except FileNotFoundError: return dayzero @@ -97,7 +96,7 @@ def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs): zonedir = kwargs["zonedir"] # If any one of the zone files isn't ready, then retry until timeout. - tries = max_secondary_zone_waittime_sec + tries = MAX_SECONDARY_ZONE_WAITTIME_SEC while tries >= 0: zones = fetch_zones(statsip, statsport) again = False @@ -160,7 +159,7 @@ def create_expected(data): def update_expected(expected, key, msg): msg_len = len(msg.to_wire()) bucket_num = (msg_len // 16) * 16 - bucket = "{}-{}".format(bucket_num, bucket_num + 15) + bucket = f"{bucket_num}-{bucket_num + 15}" expected[key][bucket] += 1 diff --git a/bin/tests/system/statschannel/tests_json.py b/bin/tests/system/statschannel/tests_json.py index c495a94a83..30348f4e69 100755 --- a/bin/tests/system/statschannel/tests_json.py +++ b/bin/tests/system/statschannel/tests_json.py @@ -18,8 +18,7 @@ import requests import isctest.mark -pytest.register_assert_rewrite("generic") -import generic +from . import generic pytestmark = [ isctest.mark.with_json_c, @@ -47,9 +46,7 @@ pytestmark = [ # JSON helper functions def fetch_zones_json(statsip, statsport): - r = requests.get( - "http://{}:{}/json/v1/zones".format(statsip, statsport), timeout=600 - ) + r = requests.get(f"http://{statsip}:{statsport}/json/v1/zones", timeout=600) assert r.status_code == 200 data = r.json() @@ -57,9 +54,7 @@ def fetch_zones_json(statsip, statsport): def fetch_traffic_json(statsip, statsport): - r = requests.get( - "http://{}:{}/json/v1/traffic".format(statsip, statsport), timeout=600 - ) + r = requests.get(f"http://{statsip}:{statsport}/json/v1/traffic", timeout=600) assert r.status_code == 200 data = r.json() @@ -72,7 +67,7 @@ def load_timers_json(zone, primary=True): # Check if the primary zone timer exists assert "loaded" in zone - loaded = datetime.strptime(zone["loaded"], generic.fmt) + loaded = datetime.strptime(zone["loaded"], generic.FMT) if primary: # Check if the secondary zone timers does not exist @@ -83,8 +78,8 @@ def load_timers_json(zone, primary=True): else: assert "expires" in zone assert "refresh" in zone - expires = datetime.strptime(zone["expires"], generic.fmt) - refresh = datetime.strptime(zone["refresh"], generic.fmt) + expires = datetime.strptime(zone["expires"], generic.FMT) + refresh = datetime.strptime(zone["refresh"], generic.FMT) return (name, loaded, expires, refresh) diff --git a/bin/tests/system/statschannel/tests_xml.py b/bin/tests/system/statschannel/tests_xml.py index 97ca7c1365..0707681de7 100755 --- a/bin/tests/system/statschannel/tests_xml.py +++ b/bin/tests/system/statschannel/tests_xml.py @@ -12,6 +12,7 @@ # information regarding copyright ownership. from datetime import datetime + import xml.etree.ElementTree as ET import pytest @@ -19,8 +20,7 @@ import requests import isctest.mark -pytest.register_assert_rewrite("generic") -import generic +from . import generic pytestmark = [ isctest.mark.with_libxml2, @@ -47,9 +47,7 @@ pytestmark = [ # XML helper functions def fetch_zones_xml(statsip, statsport): - r = requests.get( - "http://{}:{}/xml/v3/zones".format(statsip, statsport), timeout=600 - ) + r = requests.get(f"http://{statsip}:{statsport}/xml/v3/zones", timeout=600) assert r.status_code == 200 root = ET.fromstring(r.text) @@ -72,9 +70,7 @@ def fetch_traffic_xml(statsip, statsport): return out - r = requests.get( - "http://{}:{}/xml/v3/traffic".format(statsip, statsport), timeout=600 - ) + r = requests.get(f"http://{statsip}:{statsport}/xml/v3/traffic", timeout=600) assert r.status_code == 200 root = ET.fromstring(r.text) @@ -85,9 +81,9 @@ def fetch_traffic_xml(statsip, statsport): proto_root = root.find("traffic").find(ip).find(proto) for counters in proto_root.findall("counters"): if counters.attrib["type"] == "request-size": - key = "dns-{}-requests-sizes-received-{}".format(proto, ip) + key = f"dns-{proto}-requests-sizes-received-{ip}" else: - key = "dns-{}-responses-sizes-sent-{}".format(proto, ip) + key = f"dns-{proto}-responses-sizes-sent-{ip}" values = load_counters(counters) traffic[key] = values @@ -100,7 +96,7 @@ def load_timers_xml(zone, primary=True): loaded_el = zone.find("loaded") assert loaded_el is not None - loaded = datetime.strptime(loaded_el.text, generic.fmt) + loaded = datetime.strptime(loaded_el.text, generic.FMT) expires_el = zone.find("expires") refresh_el = zone.find("refresh") @@ -112,8 +108,8 @@ def load_timers_xml(zone, primary=True): else: assert expires_el is not None assert refresh_el is not None - expires = datetime.strptime(expires_el.text, generic.fmt) - refresh = datetime.strptime(refresh_el.text, generic.fmt) + expires = datetime.strptime(expires_el.text, generic.FMT) + refresh = datetime.strptime(refresh_el.text, generic.FMT) return (name, loaded, expires, refresh) diff --git a/bin/tests/system/stress/tests_stress_update.py b/bin/tests/system/stress/tests_stress_update.py index ef98b41137..5864335c46 100644 --- a/bin/tests/system/stress/tests_stress_update.py +++ b/bin/tests/system/stress/tests_stress_update.py @@ -12,6 +12,8 @@ import concurrent.futures import time +import dns.exception +import dns.rcode import dns.update import pytest diff --git a/bin/tests/system/stub/tests_stub.py b/bin/tests/system/stub/tests_stub.py index 2c9bd00cd6..8cf87c7ad8 100644 --- a/bin/tests/system/stub/tests_stub.py +++ b/bin/tests/system/stub/tests_stub.py @@ -12,7 +12,7 @@ import os -import dns.message +import dns.rrset import pytest import isctest diff --git a/bin/tests/system/tcp/ans6/ans.py b/bin/tests/system/tcp/ans6/ans.py index a9df8b7df7..210ae16c98 100644 --- a/bin/tests/system/tcp/ans6/ans.py +++ b/bin/tests/system/tcp/ans6/ans.py @@ -58,14 +58,14 @@ def open_connections(active_conns, count, host, port): except socket.error: family = socket.AF_INET6 - log("Opening %d connections..." % count) + log(f"Opening {count} connections...") for _ in range(count): sock = socket.socket(family, socket.SOCK_STREAM) sock.setblocking(0) err = sock.connect_ex((host, port)) if err not in (0, errno.EINPROGRESS): - log("%s on connect for socket %s" % (errno.errorcode[err], sock)) + log(f"{errno.errorcode[err]} on connect for socket {sock}") errors.append(sock) else: queued.append(sock) @@ -81,30 +81,30 @@ def open_connections(active_conns, count, host, port): queued.remove(sock) err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) if err: - log("%s for socket %s" % (errno.errorcode[err], sock)) + log(f"{errno.errorcode[err]} for socket {sock}") errors.append(sock) else: sock.send(VERSION_QUERY) active_conns.append(sock) if errors: - log("result=FAIL: %d connection(s) failed" % len(errors)) + log(f"result=FAIL: {len(errors)} connection(s) failed") elif queued: - log("result=FAIL: Timed out, aborting %d pending connections" % len(queued)) + log(f"result=FAIL: Timed out, aborting {len(queued)} pending connections") for sock in queued: sock.close() else: - log("result=OK: Successfully opened %d connections" % count) + log(f"result=OK: Successfully opened {count} connections") def close_connections(active_conns, count): - log("Closing %s connections..." % "all" if count == 0 else str(count)) + log(f"Closing {'all' if count == 0 else count} connections...") if count == 0: count = len(active_conns) for _ in range(count): sock = active_conns.pop(0) sock.close() - log("result=OK: Successfully closed %d connections" % count) + log(f"result=OK: Successfully closed {count} connections") def sigterm(*_): @@ -118,7 +118,7 @@ def main(): signal.signal(signal.SIGTERM, sigterm) - with open("ans.pid", "w") as pidfile: + with open("ans.pid", "w", encoding="utf-8") as pidfile: print(os.getpid(), file=pidfile) listenip = "10.53.0.6" @@ -127,7 +127,7 @@ def main(): except KeyError: port = 5309 - log("Listening on %s:%d" % (listenip, port)) + log(f"Listening on {listenip}:{port}") ctlsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ctlsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -136,10 +136,10 @@ def main(): while True: clientsock, _ = ctlsock.accept() - log("Accepted control connection from %s" % clientsock) + log(f"Accepted control connection from {clientsock}") cmdline = clientsock.recv(512).decode("ascii").strip() if cmdline: - log("Received command: %s" % cmdline) + log(f"Received command: {cmdline}") cmd = cmdline.split() if cmd[0] == "open": count, host, port = cmd[1:] diff --git a/bin/tests/system/tcp/tests_tcp.py b/bin/tests/system/tcp/tests_tcp.py index 25ee0d0e1b..46c391c245 100644 --- a/bin/tests/system/tcp/tests_tcp.py +++ b/bin/tests/system/tcp/tests_tcp.py @@ -11,17 +11,16 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=unused-variable - import socket import struct import time -import pytest - -import dns +import dns.flags import dns.message +import dns.name import dns.query +import dns.rrset +import pytest pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/timeouts/tests_tcp_timeouts.py b/bin/tests/system/timeouts/tests_tcp_timeouts.py index ca982ef6c9..0d0660bd81 100644 --- a/bin/tests/system/timeouts/tests_tcp_timeouts.py +++ b/bin/tests/system/timeouts/tests_tcp_timeouts.py @@ -11,22 +11,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=unused-variable - import socket import time -import pytest - -import dns import dns.edns import dns.message import dns.name import dns.query import dns.rdataclass import dns.rdatatype +import pytest -import isctest.mark # pylint: disable=import-error +import isctest.mark pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/tools/tests_tools_nsec3hash.py b/bin/tests/system/tools/tests_tools_nsec3hash.py index 93670bc48c..d1dd1de053 100644 --- a/bin/tests/system/tools/tests_tools_nsec3hash.py +++ b/bin/tests/system/tools/tests_tools_nsec3hash.py @@ -12,15 +12,15 @@ import os import subprocess +from dns.dnssectypes import NSEC3Hash +from hypothesis import given, settings, strategies + +import dns.dnssec import pytest -import isctest from isctest.hypothesis.strategies import dns_names -from hypothesis import strategies, given, settings - -from dns.dnssectypes import NSEC3Hash -import dns.dnssec +import isctest NSEC3HASH = os.environ.get("NSEC3HASH") diff --git a/bin/tests/system/tsig/ans2/ans.py b/bin/tests/system/tsig/ans2/ans.py index 677a57cf8f..fe91046d51 100644 --- a/bin/tests/system/tsig/ans2/ans.py +++ b/bin/tests/system/tsig/ans2/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.flags diff --git a/bin/tests/system/tsig/tests_badtime.py b/bin/tests/system/tsig/tests_badtime.py index 4c3a62c9d8..7da1ef7357 100644 --- a/bin/tests/system/tsig/tests_badtime.py +++ b/bin/tests/system/tsig/tests_badtime.py @@ -11,16 +11,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -# pylint: disable=unused-variable - import socket import time -import pytest - import dns.message import dns.query +import dns.tsig import dns.tsigkeyring +import pytest pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/tsig/tests_tsig_hypothesis.py b/bin/tests/system/tsig/tests_tsig_hypothesis.py index 5d31b58339..a7107c87fc 100644 --- a/bin/tests/system/tsig/tests_tsig_hypothesis.py +++ b/bin/tests/system/tsig/tests_tsig_hypothesis.py @@ -17,7 +17,8 @@ import time -import pytest +from hypothesis import assume, example, given +from hypothesis.strategies import binary, booleans, composite, just, sampled_from import dns.exception import dns.message @@ -27,12 +28,11 @@ import dns.rdatatype import dns.rdtypes.ANY.TSIG import dns.rrset import dns.tsig +import pytest -import isctest from isctest.hypothesis.strategies import dns_names, uint -from hypothesis import assume, example, given -from hypothesis.strategies import binary, booleans, composite, just, sampled_from +import isctest pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py index 7e960ba6e1..3193ea6c3f 100755 --- a/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py +++ b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py @@ -20,17 +20,14 @@ import argparse import struct import time -import pytest - -import isctest - -import dns -import dns.message import dns.name import dns.rdata import dns.rdataclass import dns.rdatatype import dns.rrset +import pytest + +import isctest pytestmark = pytest.mark.extra_artifacts( [ diff --git a/bin/tests/system/verify/tests_verify.py b/bin/tests/system/verify/tests_verify.py index e5e780a532..2fe4d30b2f 100644 --- a/bin/tests/system/verify/tests_verify.py +++ b/bin/tests/system/verify/tests_verify.py @@ -9,9 +9,10 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from re import compile as Re + import os import re -from re import compile as Re import pytest diff --git a/bin/tests/system/vulture_ignore_list.py b/bin/tests/system/vulture_ignore_list.py index 2080fe1d3d..2d8d69e57e 100644 --- a/bin/tests/system/vulture_ignore_list.py +++ b/bin/tests/system/vulture_ignore_list.py @@ -9,6 +9,4 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -transfers_complete # unused function (cipher-suites/tests_cipher_suites.py:31) -transfers_complete # unused variable (cipher-suites/tests_cipher_suites.py:86) -token_init_and_cleanup # unused function (keyfromlabel/tests_keyfromlabel.py:43) +transfers_complete # unused function (cipher-suites/tests_cipher_suites.py:82) diff --git a/bin/tests/system/wildcard/tests_wildcard.py b/bin/tests/system/wildcard/tests_wildcard.py index 60d75384f0..3ea3fdc7d3 100755 --- a/bin/tests/system/wildcard/tests_wildcard.py +++ b/bin/tests/system/wildcard/tests_wildcard.py @@ -31,19 +31,15 @@ Limitations - untested properties: # https://github.com/pylint-dev/pylint/issues/10785#issuecomment-3677224217 # pylint: disable=unreachable -import pytest +from hypothesis import assume, example, given, settings -import dns -import dns.message import dns.name -import dns.query -import dns.rcode import dns.rdataclass import dns.rdatatype import dns.rrset +import pytest from isctest.hypothesis.strategies import dns_names, dns_rdatatypes_without_meta -from hypothesis import assume, example, given, settings import isctest.check import isctest.name diff --git a/bin/tests/system/xfer/ans10/ans.py b/bin/tests/system/xfer/ans10/ans.py index 6f5346ff86..d162070c76 100644 --- a/bin/tests/system/xfer/ans10/ans.py +++ b/bin/tests/system/xfer/ans10/ans.py @@ -9,10 +9,7 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -from isctest.asyncserver import ( - AsyncDnsServer, - IgnoreAllQueries, -) +from isctest.asyncserver import AsyncDnsServer, IgnoreAllQueries def main() -> None: diff --git a/bin/tests/system/xfer/ans9/ans.py b/bin/tests/system/xfer/ans9/ans.py index 2e3a1f8be2..25da6b7d43 100644 --- a/bin/tests/system/xfer/ans9/ans.py +++ b/bin/tests/system/xfer/ans9/ans.py @@ -11,7 +11,7 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ -from typing import AsyncGenerator +from collections.abc import AsyncGenerator import dns.rcode import dns.rdatatype @@ -19,10 +19,10 @@ import dns.rrset from isctest.asyncserver import ( ControllableAsyncDnsServer, + DnsResponseSend, DomainHandler, QueryContext, ResponseAction, - DnsResponseSend, ToggleResponsesCommand, ) diff --git a/bin/tests/system/xfer/tests_xfer.py b/bin/tests/system/xfer/tests_xfer.py index 591e2ffab0..b57fc80626 100644 --- a/bin/tests/system/xfer/tests_xfer.py +++ b/bin/tests/system/xfer/tests_xfer.py @@ -10,18 +10,24 @@ # information regarding copyright ownership. +from re import compile as Re + import fileinput import os -from re import compile as Re import socket import time +import dns.message +import dns.query +import dns.rdataclass +import dns.rdatatype +import dns.tsig +import dns.zone import pytest -import isctest from isctest.util import param -import dns.message +import isctest NEW_SOA_SERIAL = 1397051953 OLD_SOA_SERIAL = 1397051952 diff --git a/bin/tests/system/xferquota/setup.py b/bin/tests/system/xferquota/setup.py index ec457bf171..bd8f96bc0c 100644 --- a/bin/tests/system/xferquota/setup.py +++ b/bin/tests/system/xferquota/setup.py @@ -15,9 +15,9 @@ # Set up test data for zone transfer quota tests. # -zones = 300 +ZONES = 300 -for z in range(zones): +for z in range(ZONES): zn = f"zone{z:06d}.example" with open(f"ns1/{zn}.db", "w", encoding="utf-8") as f: f.write("""$TTL 300 @@ -35,7 +35,7 @@ xyzzy A 10.0.0.2 with open("ns1/zones.conf", "w", encoding="utf-8") as priconf, open( "ns2/zones.conf", "w", encoding="utf-8" ) as secconf: - for z in range(zones): + for z in range(ZONES): zn = f"zone{z:06d}.example" priconf.write(f'zone "{zn}" {{ type primary; file "{zn}.db"; }};\n') secconf.write( diff --git a/bin/tests/system/xferquota/tests_xferquota.py b/bin/tests/system/xferquota/tests_xferquota.py index a0d042d135..6d255085cb 100644 --- a/bin/tests/system/xferquota/tests_xferquota.py +++ b/bin/tests/system/xferquota/tests_xferquota.py @@ -9,15 +9,16 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +from re import compile as Re + import glob import os import re -from re import compile as Re import shutil import signal import time -import dns.message +import dns.zone import pytest import isctest diff --git a/bin/tests/system/zero/ans5/ans.py b/bin/tests/system/zero/ans5/ans.py index a7f63913cf..5ff475d801 100644 --- a/bin/tests/system/zero/ans5/ans.py +++ b/bin/tests/system/zero/ans5/ans.py @@ -11,8 +11,9 @@ See the COPYRIGHT file distributed with this work for additional information regarding copyright ownership. """ +from collections.abc import AsyncGenerator + import ipaddress -from typing import AsyncGenerator import dns.rcode import dns.rdatatype diff --git a/dangerfile.py b/dangerfile.py index b6851be7a5..27e2d31c1c 100644 --- a/dangerfile.py +++ b/dangerfile.py @@ -42,7 +42,6 @@ def lines_containing(lines, string): return [l for l in lines if bytes(string, "utf-8") in l] -changes_issue_or_mr_id_regex = re.compile(rb"\[(GL [#!]|RT #)[0-9]+\]") rdata_regex = re.compile(r"lib/dns/rdata/") # Source: https://docs.gitlab.com/user/project/issues/managing_issues/#default-closing-pattern diff --git a/doc/arm/_ext/iscconf.py b/doc/arm/_ext/iscconf.py index 4313194119..0fe566a548 100644 --- a/doc/arm/_ext/iscconf.py +++ b/doc/arm/_ext/iscconf.py @@ -23,9 +23,8 @@ https://www.sphinx-doc.org/en/master/development/tutorials/recipe.html from collections import namedtuple -from docutils.parsers.rst import Directive, directives from docutils import nodes - +from docutils.parsers.rst import Directive, directives from sphinx import addnodes from sphinx.directives import ObjectDescription from sphinx.domains import Domain @@ -355,7 +354,7 @@ def domain_factory(domainname, domainlabel, todolist, grammar): ) def get_statement_name(self, signature): - return "{}.{}.{}".format(domainname, "statement", signature) + return f"{domainname}.statement.{signature}" def add_statement(self, signature, tags, short, short_node, lineno): """ @@ -363,7 +362,7 @@ def domain_factory(domainname, domainlabel, todolist, grammar): No visible effect. """ name = self.get_statement_name(signature) - anchor = "{}-statement-{}".format(domainname, signature) + anchor = f"{domainname}-statement-{signature}" new = { "tags": tags, diff --git a/doc/arm/_ext/mergegrammar.py b/doc/arm/_ext/mergegrammar.py index b0500eb4b5..b18e1e1626 100644 --- a/doc/arm/_ext/mergegrammar.py +++ b/doc/arm/_ext/mergegrammar.py @@ -13,9 +13,10 @@ # Depends on CWD - Sphinx plugin -import json from pathlib import Path +import json + import parsegrammar diff --git a/doc/arm/conf.py b/doc/arm/conf.py index 95a8dfd4c1..dd6f2aa29e 100644 --- a/doc/arm/conf.py +++ b/doc/arm/conf.py @@ -146,7 +146,6 @@ sys.path.append(str(Path(__file__).resolve().parent.parent / "misc")) # -- Project information ----------------------------------------------------- project = "BIND 9" -# pylint: disable=redefined-builtin copyright = "2023, Internet Systems Consortium" author = "Internet Systems Consortium" diff --git a/doc/man/conf.py b/doc/man/conf.py index 1ba2af8b1f..a8f8caecab 100644 --- a/doc/man/conf.py +++ b/doc/man/conf.py @@ -31,11 +31,9 @@ # -- Project information ----------------------------------------------------- project = "BIND 9" -# pylint: disable=wrong-import-position import datetime year = datetime.datetime.now().year -# pylint: disable=redefined-builtin copyright = "%d, Internet Systems Consortium" % year author = "Internet Systems Consortium" @@ -65,7 +63,6 @@ exclude_patterns = [ # The master toctree document. master_doc = "index" -# pylint: disable=line-too-long man_pages = [ ( "arpaname", diff --git a/doc/misc/checkgrammar.py b/doc/misc/checkgrammar.py index 09984eceb4..f08c1e43dd 100644 --- a/doc/misc/checkgrammar.py +++ b/doc/misc/checkgrammar.py @@ -20,6 +20,7 @@ vs. '( unlimited | ) used in options. from collections import namedtuple from itertools import groupby + import fileinput import parsegrammar diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..308c127568 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,125 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +[tool.pylint.basic] +good-names-rgxs = [ + # Allow names from KASP tests + "I(pub|ret)C?", + "T(act|pub|ret|rem|sbm)N1?", +] +[tool.pylint.imports] +deprecated-modules = [ + "dns.resolver", +] +[tool.pylint.messages_control] +disable = [ + "C0114", # missing-module-docstring + "C0115", # missing-class-docstring + "C0116", # missing-function-docstring + "C0301", # line-too-long, handled better by black + "C0302", # too-many-lines + "R0801", # duplicate-code + "R0902", # too-many-instance-attributes + "R0903", # too-few-public-methods + "R0912", # too-many-branches + "R0913", # too-many-arguments + "R0914", # too-many-locals + "R0915", # too-many-statements + "R0917", # too-many-positional-arguments +] +[tool.pylint.main] +ignore-paths = [ + ".git", + # Temporary directories created by the system test runner + # (see bin/tests/system/conftest.py:system_test_dir) + "bin/tests/system/.*_tmp_.*/", + "bin/tests/system/vulture_ignore_list.py", + "contrib", + "dangerfile.py", + "doc/arm/conf.py", + "doc/man/conf.py", +] + +# Both `init-hook` and `source-roots` are needed to avoid import errors, +# enable plugin loading and calling pylint from CI as `pylint $(git ls-files '*.py')` +init-hook = "import sys; sys.path.extend(('bin/tests/system', 'doc/misc', 'doc/arm/_ext'));" +source-roots = [ + "bin/tests/system", + "doc/misc", + "doc/arm/_ext", +] +load-plugins = [ + "re_compile_checker", + "dns_import_checker", +] + +[tool.vulture] +paths = [ + ".", +] +exclude = [ + "*ans.py", + "contrib", + "*doc/arm/_ext/*conf.py", + "doc/arm/conf.py", + "doc/man/conf.py", + "isctest", + "re_compile_checker.py", + "dns_import_checker.py", +] +ignore_decorators = [ + "@pytest.fixture", +] +ignore_names = [ + "pytest*", + # attributes of `isctest.kasp.KeyProperties` set but later not read in: + # - bin/tests/system/kasp/tests_kasp.py + # - bin/tests/system/multisigner/tests_multisigner.py + # - bin/tests/system/nsec3/common.py + # - bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py + "private", + "legacy", +] + +[tool.ruff] +target-version = "py310" +lint.select = [ + # import order + "I", + # unused imports + "F401", + # sorted __all__ + "RUF022", + # unnecessary `typing` imports + "UP006", + "UP007", + "UP035", + "UP045", + # f-strings + "UP031", + "UP032", +] +extend-exclude = [ + "bin/tests/system/vulture_ignore_list.py", + "contrib", + "dangerfile.py", + "doc/arm/conf.py", + "doc/man/conf.py", +] +src = [ + "bin/tests/system", + "doc/misc", + "doc/arm/_ext", +] +[tool.ruff.lint.isort] +from-first = true +lines-between-types = 1 +split-on-trailing-comma = false diff --git a/util/ci-wait-shotgun.py b/util/ci-wait-shotgun.py deleted file mode 100755 index 894dfa9f57..0000000000 --- a/util/ci-wait-shotgun.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -# -# SPDX-License-Identifier: MPL-2.0 -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, you can obtain one at https://mozilla.org/MPL/2.0/. -# -# See the COPYRIGHT file distributed with this work for additional -# information regarding copyright ownership. - -import os -import sys -import time - -import gitlab - - -def init_gitlab_project(): - if os.getenv("CI_SERVER_URL", None) is not None: - url = os.getenv("CI_SERVER_URL") - job_token = os.environ["CI_JOB_TOKEN"] - gl = gitlab.Gitlab(url, job_token=job_token) - else: # running locally on dev machine - gl = gitlab.Gitlab.from_config() - return gl.projects.get("isc-projects/bind9-shotgun-ci") - - -def parse_parent_pipeline_id(): - if len(sys.argv) != 2: - raise RuntimeError("usage: util/ci-wait-shotgun.py PIPELINE_ID") - try: - return int(sys.argv[1]) - except ValueError as exc: - raise RuntimeError("error: PIPELINE_ID must be a number") from exc - - -def wait_until(callback, timeout=1800, retry=10): - start = time.time() - while time.time() - start < timeout: - if callback(): - return - time.sleep(retry) - raise RuntimeError(f"error: timed out after {timeout}s") - - -def get_child_pipeline_id(project, pipeline_id): - pipeline = project.pipelines.get(pipeline_id) - - def pipeline_finished(): - pipeline.refresh() - return pipeline.finished_at is not None - - wait_until(pipeline_finished, timeout=6600) - - bridges = pipeline.bridges.list() - if len(bridges) != 1: - raise RuntimeError("error: expected exactly one child pipeline") - return bridges[0].downstream_pipeline["id"] - - -def get_postproc_job(project, pipeline_id): - pipeline = project.pipelines.get(pipeline_id) - postproc_job = None - - def job_finished(): - nonlocal postproc_job - for job in pipeline.jobs.list(get_all=True): - if job.name == "postproc": - postproc_job = job - if postproc_job is None: - raise RuntimeError("error: failed to find 'postproc' job in child pipeline") - return postproc_job.finished_at is not None - - wait_until(job_finished) - return postproc_job - - -def evaluate_postproc_job(job): - print(f"postproc job URL: {job.web_url}") - index_url = ( - "https://isc-projects.gitlab-pages.isc.org/-/" - f"bind9-shotgun-ci/-/jobs/{job.id}/artifacts/index.html" - ) - if job.status in ["success", "failed"]: - print(f"result for manual inspection: {index_url}") - if job.status != "success": - raise RuntimeError("error: 'postproc' job didn't succeed") - - -def main(): - project = init_gitlab_project() - parent_pipeline_id = parse_parent_pipeline_id() - child_pipeline_id = get_child_pipeline_id(project, parent_pipeline_id) - postproc_job = get_postproc_job(project, child_pipeline_id) - evaluate_postproc_job(postproc_job) - - -if __name__ == "__main__": - try: - main() - except RuntimeError as err: - print(err) - sys.exit(1) diff --git a/util/generate-tsan-stress-jobs.py b/util/generate-tsan-stress-jobs.py deleted file mode 100755 index 8ee649ed6f..0000000000 --- a/util/generate-tsan-stress-jobs.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -# -# SPDX-License-Identifier: MPL-2.0 -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, you can obtain one at https://mozilla.org/MPL/2.0/. -# -# See the COPYRIGHT file distributed with this work for additional -# information regarding copyright ownership. - -import yaml - -NUMBER_OF_TESTS_PER_TSAN_JOB = 50 - -with open(".gitlab-ci.yml", encoding="utf-8") as gitlab_ci_yml: - anchors = yaml.load(gitlab_ci_yml, Loader=yaml.Loader) - -for tsan_job in "gcc:tsan", "clang:tsan": - for test_type in "unit", "system": - tsan_stress_test_job = anchors[f"{test_type}:{tsan_job}"] - tsan_stress_test_job["stage"] = "test" - tsan_stress_test_job["rules"] = [ - {"if": '$CI_PIPELINE_SOURCE == "parent_pipeline"'} - ] - tsan_stress_test_job["parallel"] = NUMBER_OF_TESTS_PER_TSAN_JOB - tsan_stress_test_job["needs"] = [ - {"pipeline": "$PARENT_PIPELINE_ID", "job": tsan_job} - ] - - print( - yaml.dump( - {f"{test_type}:{tsan_job}:stress": tsan_stress_test_job}, - Dumper=yaml.Dumper, - ) - ) diff --git a/util/parse_tsan.py b/util/parse_tsan.py deleted file mode 100755 index 28afc34bff..0000000000 --- a/util/parse_tsan.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 -############################################################################ -# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -# -# SPDX-License-Identifier: MPL-2.0 -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, you can obtain one at https://mozilla.org/MPL/2.0/. -# -# See the COPYRIGHT file distributed with this work for additional -# information regarding copyright ownership. -############################################################################ - -"""Parse the ThreadSanizer reports, unify them and put them into unique dirs.""" - -import sys -import os -import os.path -import re -from hashlib import sha256 - - -class State: - """Class that holds state of the TSAN parser.""" - - inside = False - block = "" - last_line = None - - mutexes = {} - m_index = 1 - threads = {} - t_index = 1 - pointers = {} - p_index = 1 - - def __init__(self): - self.reset() - - def reset(self): - """Reset the object to initial state""" - - self.inside = False - self.block = "" - - self.mutexes = {} - self.threads = {} - self.pointers = {} - self.pointers["0x000000000000"] = 0 - - self.m_index = 1 - self.t_index = 1 - self.p_index = 1 - - -TOP = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - -OUT = os.path.join(TOP, "tsan") - -if not os.path.isdir(OUT): - os.mkdir(OUT) - -# Regular Expressions -MUTEX = re.compile(r"M\d+") -THREAD = re.compile(r"T\d+") -STACK = re.compile(r"\s\(\S+\+0x\S+\)") -POINTER = re.compile(r"0x[0-9a-f]+") -PID = re.compile(r"\(pid=\d+,?\)") -TID = re.compile(r"tid=\d+,?\s*") -WORKER = re.compile(r"\s+'(isc-worker|isc-net-)\d+'") -PATH = re.compile(TOP + "/") - -S = State() - -with open(sys.argv[1], "r", encoding="utf-8") as f: - for line in f.readlines(): - if line == "==================\n": - if not S.inside: - S.inside = True - else: - DNAME = sha256(S.last_line.encode("utf-8")).hexdigest() - DNAME = os.path.join(OUT, DNAME) - if not os.path.isdir(DNAME): - os.mkdir(DNAME) - FNAME = sha256(S.block.encode("utf-8")).hexdigest() + ".txt" - FNAME = os.path.join(DNAME, FNAME) - if not os.path.isfile(FNAME): - with open(FNAME, "w", encoding="utf-8") as w: - w.write(S.block) - S.reset() - else: - for m in MUTEX.finditer(line): - k = m.group() - if k not in S.mutexes: - S.mutexes[k] = S.m_index - S.m_index += 1 - for m in THREAD.finditer(line): - k = m.group() - if k not in S.threads: - S.threads[k] = S.t_index - S.t_index += 1 - for m in POINTER.finditer(line): - k = m.group() - if k not in S.pointers: - S.pointers[k] = S.p_index - S.p_index += 1 - for k, v in S.mutexes.items(): - r = re.compile(k) - line = r.sub("M{:04d}".format(v), line) - for k, v in S.threads.items(): - r = re.compile(k) - line = r.sub("T{:04d}".format(v), line) - for k, v in S.pointers.items(): - r = re.compile(k) - line = r.sub("0x{:012d}".format(v), line) - - line = STACK.sub("", line) - line = PID.sub("", line) - line = TID.sub("", line) - line = WORKER.sub("", line) - line = PATH.sub("", line) - - S.block += line - S.last_line = line