mirror of https://github.com/ansible/ansible.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.4 KiB
Python
108 lines
3.4 KiB
Python
# 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 |