# Copyright: Contributors to the Ansible project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import annotations import collections from ansible.modules.apt import ( expand_pkgspec_from_fnmatches, ) import pytest FakePackage = collections.namedtuple("Package", ("name",)) fake_cache = [ FakePackage("apt"), FakePackage("apt-utils"), FakePackage("not-selected"), ] @pytest.mark.parametrize( ("test_input", "expected"), [ pytest.param( ["apt"], ["apt"], id="trivial", ), pytest.param( ["apt=1.0*"], ["apt=1.0*"], id="version-wildcard", ), pytest.param( ["apt*=1.0*"], ["apt", "apt-utils"], id="pkgname-wildcard-version", ), pytest.param( ["apt*"], ["apt", "apt-utils"], id="pkgname-expands", ), ], ) def test_expand_pkgspec_from_fnmatches(test_input, expected): """Test positive cases of ``expand_pkgspec_from_fnmatches``.""" assert expand_pkgspec_from_fnmatches(None, test_input, fake_cache) == expected def test_virtual_package_resolution_fixed(): """Test that virtual package dependencies are properly resolved with the fix.""" # Scenario: A package depends on virtual package 'libglib2.0-0' # which is provided by 'libglib2.0-0t64' virtual_dependency = 'libglib2.0-0' providing_package = 'libglib2.0-0t64' class MockCache: def is_virtual_package(self, pkg_name): return pkg_name == virtual_dependency def get_providing_packages(self, pkg_name): if pkg_name == virtual_dependency: return [providing_package] return [] def __contains__(self, pkg_name): # Virtual packages are not directly in cache, but have providers return pkg_name == providing_package # Only the provider is in cache def __getitem__(self, pkg_name): if pkg_name == providing_package: return MockPackage(installed=True) raise KeyError(pkg_name) class MockPackage: def __init__(self, installed=False): self.installed = installed cache = MockCache() unsatisfied_deps = [] # SIMULATE THE FIXED LOGIC (what we implemented): dep_name = virtual_dependency # FIXED IMPLEMENTATION (with virtual package handling): if cache.is_virtual_package(dep_name): providers = cache.get_providing_packages(dep_name) if providers: # Check if any provider is installed provider_installed = False for provider in providers: if provider in cache and cache[provider].installed: provider_installed = True break if not provider_installed: unsatisfied_deps.append(dep_name) else: unsatisfied_deps.append(dep_name) elif dep_name not in cache or not cache[dep_name].installed: unsatisfied_deps.append(dep_name) # With the fixed logic, virtual dependencies with installed providers should be satisfied assert virtual_dependency not in unsatisfied_deps, ( f"Virtual package {virtual_dependency} should be satisfied by {providing_package}" ) assert len(unsatisfied_deps) == 0