From 9aa56b71e965ed1b10bd64828a1398511f67e47a Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Sat, 31 Oct 2026 02:17:21 +0100 Subject: [PATCH] test(lookup): restore sys.modules after loading the sso plugins fresh test_sso.py, test_sso_oidc_plugin.py and test_sso_proxy_consumers.py evict utils, utils.cache, utils.cache.applications and the roles packages from sys.modules to import their plugin against fresh modules, and never put the originals back. Ansible's plugin loader keeps the applications lookup it loaded earlier in sys.modules, so that lookup stayed bound to the evicted utils.cache.applications, whose _MERGED_APPLICATIONS_CACHE utils.cache._reset_cache_for_tests() no longer reaches. On main this turned test_webserver_worker_limits red whenever one xdist worker ran a test that loads the applications lookup through Ansible, then one of these sso tests, then the worker-limits test: the stale cache served the cpus 0.5 payload of test_a_sub_cpu_proxy_still_runs_one_worker, so the later methods rendered worker_processes 1 instead of 4 (main run 41139196554, Workspace centos and fedora, second make test on gw1). _load_module now runs inside mock.patch.dict(sys.modules): the plugin keeps the fresh modules it was built against, and sys.modules returns to its prior state afterwards. This is the change store-i18n carries since ec0fde6561, ported unchanged so both lines stay identical. Evidence: - Before: pytest -n 0 test_tor_ports.py test_sso_oidc_plugin.py test_webserver_worker_limits.py -> "3 failed, 33 passed", the CI failure set ('1' != '4' twice, worker_processes 1 vs 4). - After: test_tor_ports.py, the four sso test files and test_webserver_worker_limits.py -> "68 passed". (cherry picked from commit ec0fde6561) Co-Authored-By: Claude Opus 5.5 --- tests/unit/python/plugins/lookup/test_sso.py | 37 ++++++++++--------- .../plugins/lookup/test_sso_oidc_plugin.py | 31 ++++++++-------- .../lookup/test_sso_proxy_consumers.py | 37 ++++++++++--------- 3 files changed, 54 insertions(+), 51 deletions(-) diff --git a/tests/unit/python/plugins/lookup/test_sso.py b/tests/unit/python/plugins/lookup/test_sso.py index 050fd488b0..9f01f26824 100644 --- a/tests/unit/python/plugins/lookup/test_sso.py +++ b/tests/unit/python/plugins/lookup/test_sso.py @@ -19,25 +19,26 @@ from . import PROJECT_ROOT def _load_module(rel_path: str, name: str): - for key in ( - "utils.roles.applications.config", - "utils.roles.applications", - "utils", - "utils.cache.applications", - "utils.cache", - "utils.roles.applications.services.sso", - "utils.roles.applications.services", - ): - sys.modules.pop(key, None) - importlib.import_module("utils.roles.applications.config") - importlib.import_module("utils.cache.applications") - importlib.import_module("utils.roles.applications.services.sso") + with mock.patch.dict(sys.modules): + for key in ( + "utils.roles.applications.config", + "utils.roles.applications", + "utils", + "utils.cache.applications", + "utils.cache", + "utils.roles.applications.services.sso", + "utils.roles.applications.services", + ): + sys.modules.pop(key, None) + importlib.import_module("utils.roles.applications.config") + importlib.import_module("utils.cache.applications") + importlib.import_module("utils.roles.applications.services.sso") - path = PROJECT_ROOT / rel_path - spec = importlib.util.spec_from_file_location(name, str(path)) - mod = importlib.util.module_from_spec(spec) - assert spec and spec.loader - spec.loader.exec_module(mod) + path = PROJECT_ROOT / rel_path + spec = importlib.util.spec_from_file_location(name, str(path)) + mod = importlib.util.module_from_spec(spec) + assert spec and spec.loader + spec.loader.exec_module(mod) return mod diff --git a/tests/unit/python/plugins/lookup/test_sso_oidc_plugin.py b/tests/unit/python/plugins/lookup/test_sso_oidc_plugin.py index af94622a39..30eb3ec8e3 100644 --- a/tests/unit/python/plugins/lookup/test_sso_oidc_plugin.py +++ b/tests/unit/python/plugins/lookup/test_sso_oidc_plugin.py @@ -13,22 +13,23 @@ def _load_module(rel_path: str, name: str): """Import ``rel_path`` fresh, evicting sibling-test stubs of ``utils.roles.applications.config`` from ``sys.modules`` first. """ - for key in ( - "utils.roles.applications.config", - "utils.roles.applications", - "utils", - "utils.cache.applications", - "utils.cache", - ): - sys.modules.pop(key, None) - importlib.import_module("utils.roles.applications.config") - importlib.import_module("utils.cache.applications") + with mock.patch.dict(sys.modules): + for key in ( + "utils.roles.applications.config", + "utils.roles.applications", + "utils", + "utils.cache.applications", + "utils.cache", + ): + sys.modules.pop(key, None) + importlib.import_module("utils.roles.applications.config") + importlib.import_module("utils.cache.applications") - path = PROJECT_ROOT / rel_path - spec = importlib.util.spec_from_file_location(name, str(path)) - mod = importlib.util.module_from_spec(spec) - assert spec and spec.loader - spec.loader.exec_module(mod) + path = PROJECT_ROOT / rel_path + spec = importlib.util.spec_from_file_location(name, str(path)) + mod = importlib.util.module_from_spec(spec) + assert spec and spec.loader + spec.loader.exec_module(mod) return mod diff --git a/tests/unit/python/plugins/lookup/test_sso_proxy_consumers.py b/tests/unit/python/plugins/lookup/test_sso_proxy_consumers.py index 3fd055e309..7d17a9d5ae 100644 --- a/tests/unit/python/plugins/lookup/test_sso_proxy_consumers.py +++ b/tests/unit/python/plugins/lookup/test_sso_proxy_consumers.py @@ -19,25 +19,26 @@ from . import PROJECT_ROOT def _load_module(rel_path: str, name: str): - for key in ( - "utils.roles.applications.config", - "utils.roles.applications", - "utils", - "utils.cache.applications", - "utils.cache", - "utils.roles.applications.services.sso", - "utils.roles.applications.services", - ): - sys.modules.pop(key, None) - importlib.import_module("utils.roles.applications.config") - importlib.import_module("utils.cache.applications") - importlib.import_module("utils.roles.applications.services.sso") + with mock.patch.dict(sys.modules): + for key in ( + "utils.roles.applications.config", + "utils.roles.applications", + "utils", + "utils.cache.applications", + "utils.cache", + "utils.roles.applications.services.sso", + "utils.roles.applications.services", + ): + sys.modules.pop(key, None) + importlib.import_module("utils.roles.applications.config") + importlib.import_module("utils.cache.applications") + importlib.import_module("utils.roles.applications.services.sso") - path = PROJECT_ROOT / rel_path - spec = importlib.util.spec_from_file_location(name, str(path)) - mod = importlib.util.module_from_spec(spec) - assert spec and spec.loader - spec.loader.exec_module(mod) + path = PROJECT_ROOT / rel_path + spec = importlib.util.spec_from_file_location(name, str(path)) + mod = importlib.util.module_from_spec(spec) + assert spec and spec.loader + spec.loader.exec_module(mod) return mod