Files
bearhub/tests/gems/arch/test_updates.py

1422 lines
85 KiB
Python

from unittest import TestCase
from unittest.mock import patch, Mock, MagicMock
from bauh import __app_name__
from bauh.api.abstract.controller import UpgradeRequirement
from bauh.gems.arch.dependencies import DependenciesAnalyser
from bauh.gems.arch.model import ArchPackage
from bauh.gems.arch.updates import UpdatesSummarizer
from bauh.view.util.translation import I18n
class UpdatesSummarizerGetUpgradeRequirementsTest(TestCase):
def setUp(self) -> None:
self.aur_client = MagicMock()
self.aur_client.read_index.return_value = set()
self.deps_analyser = MagicMock()
self._i18n = {"arch.info.conflicts with": "", "arch.update_summary.to_install.dep_conflict": "{} {}",
"arch.info.required by": "", "arch.info.depends on": ""}
self.i18n = I18n(default_key='en_US', default_locale=self._i18n, current_key='en_US', current_locale=self._i18n)
self.summarizer = UpdatesSummarizer(aur_client=self.aur_client,
aur_supported=True,
i18n=self.i18n,
logger=Mock(),
deps_analyser=self.deps_analyser,
watcher=Mock())
self.config_ = {"automatch_providers": True,
"prefer_repository_provider": True,
"check_dependency_breakage": True}
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_not_return_installed_to_remove_when_conflict_with_installed_version_fails(self, pacman: Mock):
"""
If the newest version o package A conflicts with an installed package named B, but the conflict expression
doesn't match (e.g: A conflict expressions (B <= 0.7), B (0.8)) then B should not be marked as a package
to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=0.8": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=0.8": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"B<=0.7"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.8-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps',):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_remove)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_return_installed_to_remove_when_conflict_with_installed_version_matches(self, pacman: Mock):
"""
If the newest version o package A conflicts with an installed package named B and the conflict expression
matches (e.g: A conflict expressions (B <= 0.7), B (0.7)) then B should be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A==1.0.1": {"A"},
"B": {"B"},
"B=0.7": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=0.7": {"B"}
},
{"B": {"B"}, # provided to remove
"B=0.7": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"B<=0.7"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.7-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="B", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_return_installed_to_remove_when_conflict_with_installed_matches(self, pacman: Mock):
"""
If the newest version o package A conflicts with an installed package named B,
then B should be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A==1.0.1": {"A"},
"B": {"B"},
"B=0.7": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=0.7": {"B"}
},
{"B": {"B"}, # provided to remove
"B=0.7": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"B"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.7-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="B", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_not_return_installed_to_remove_when_conflict_with_is_self_conflict(self, pacman: Mock):
"""
If the newest version o package A conflicts with itself, then A should not be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"C": {"A"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"C": {"A"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"A<=1.0.0"},
'p': {"A": {"A"},
"A=1.1.0": {"A"},
"C": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version}
pacman.get_installed_size.return_value = {"A": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
self.assertFalse(res.to_remove)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_not_return_installed_to_remove_when_conflict_with_provided_version_fails(self, pacman: Mock):
"""
If the newest version o package A conflicts with a provided package C (by installed package B),
but the conflict expression doesn't match (e.g: A conflict expressions (C <= 0.7), C (0.8))
then B should not be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B", "C"},
"B=0.8": {"B", "C"},
"C": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B", "C"},
"B=0.8": {"B", "C"},
"C": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C<=0.7"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.8-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
self.assertFalse(res.to_remove)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__not_return_to_remove_when_conflict_with_provided_virtual_package_with_version_fails(self, pacman: Mock):
"""
Scenario:
- Package V (2.5.0)[update] -> conflicts: X<21.1.1, X-ABI-VIDEODRV_VERSION<25, X-ABI-VIDEODRV_VERSION>=26
- Package X (21.1.5)[installed] -> provides: X-ABI-VIDEODRV_VERSION=25.2, X
* X provides X-ABI-VIDEODRV_VERSION with a specific version (25.2)
"""
pkg_a = ArchPackage(name="V", version="2.5.0-1", latest_version="2.6.0-1", repository="community")
pacman.map_provided.side_effect = [{"V": {"V"}, # remote provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=25.2": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X"}
},
{"V": {"V"}, # provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=25.2": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X"}
},
]
pacman.map_repositories.return_value = {"V": pkg_a.repository, "X": "community"}
pacman.map_updates_data.return_value = {"V": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"X<21.1.1",
"X-ABI-VIDEODRV_VERSION<25",
"X-ABI-VIDEODRV_VERSION>=26"},
'p': {"V": {"V"},
"V=2.5.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"V": pkg_a.version, "X": "21.1.5-1"}
pacman.get_installed_size.return_value = {"V": 1, "X": 1}
pacman.map_required_by.return_value = {"V": set()}
self.deps_analyser.map_missing_deps.return_value = list()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
self.assertFalse(res.to_remove)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_installed_virtual_with_defined_version_to_remove_when_conflict_version_matches(self, pacman: Mock):
"""
Scenario:
- Package V (2.5.0)[update] -> conflicts: X<21.1.1, X-ABI-VIDEODRV_VERSION<25, X-ABI-VIDEODRV_VERSION>=26
- Package X (21.1.5)[installed] -> provides: X-ABI-VIDEODRV_VERSION=26, X
* X provides X-ABI-VIDEODRV_VERSION with a specific version (26)
"""
pkg_a = ArchPackage(name="V", version="2.5.0-1", latest_version="2.6.0-1", repository="community")
pacman.map_provided.side_effect = [{"V": {"V"}, # remote provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X"}
},
{"V": {"V"}, # provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X"}
},
{"X": {"X"}, # provided to remove
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X"}
}
]
pacman.map_repositories.return_value = {"V": pkg_a.repository, "X": "community"}
pacman.map_updates_data.return_value = {"V": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"X<21.1.1",
"X-ABI-VIDEODRV_VERSION<25",
"X-ABI-VIDEODRV_VERSION>=26"},
'p': {"V": {"V"},
"V=2.5.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"V": pkg_a.version, "X": "21.1.5-1"}
pacman.get_installed_size.return_value = {"V": 1, "X": 1}
pacman.map_required_by.return_value = {"V": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="X", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'V'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_installed_virtual_with_defined_version_to_remove_when_conflict_matches__case_2(self, pacman: Mock):
"""
This test case covers the same scenario as the above, but adds an additional provider for the same
virtual package with a non-conflicting version
Scenario:
- Package V (2.5.0)[update] -> conflicts: X<21.1.1, X-ABI-VIDEODRV_VERSION<25, X-ABI-VIDEODRV_VERSION>=26
- Package X (21.1.5)[installed] -> provides: X-ABI-VIDEODRV_VERSION=26, X
- Package Z (2.0.0)[installed] -> provides: X-ABI-VIDEODRV_VERSION=25.2, Z
* X provides X-ABI-VIDEODRV_VERSION with a specific version (26) [conflict]
* Z provides X-ABI-VIDEODRV_VERSION with a specific version (25.2) [no conflict]
"""
pkg_a = ArchPackage(name="V", version="2.5.0-1", latest_version="2.6.0-1", repository="community")
pacman.map_provided.side_effect = [{"V": {"V"}, # remote provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"Z": {"Z"},
"Z=2.0.0": {"X"},
"X-ABI-VIDEODRV_VERSION=25.2": {"Z"},
"X-ABI-VIDEODRV_VERSION": {"X", "Z"},
},
{"V": {"V"}, # provided
"V=2.5.0": {"V"},
"X": {"X"},
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"Z": {"Z"},
"Z=2.0.0": {"X"},
"X-ABI-VIDEODRV_VERSION=25.2": {"Z"},
"X-ABI-VIDEODRV_VERSION": {"X", "Z"},
},
{"X": {"X"}, # provided to remove
"X=21.1.5": {"X"},
"X-ABI-VIDEODRV_VERSION=26": {"X"},
"X-ABI-VIDEODRV_VERSION": {"X", "Z"}
}
]
pacman.map_repositories.return_value = {"V": pkg_a.repository, "X": "community"}
pacman.map_updates_data.return_value = {"V": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"X<21.1.1",
"X-ABI-VIDEODRV_VERSION<25",
"X-ABI-VIDEODRV_VERSION>=26"},
'p': {"V": {"V"},
"V=2.5.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"V": pkg_a.version, "X": "21.1.5-1", "Z": "2.0.0-1"}
pacman.get_installed_size.return_value = {"V": 1, "X": 1, "Z": 1}
pacman.map_required_by.return_value = {"V": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="X", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'V'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_return_installed_package_to_remove_when_conflict_with_provided_matches_version(self, pacman: Mock):
"""
If the newest version o package A conflicts with a provided package C (by installed package B),
and the conflict expression matches (e.g: A conflict expressions (C <= 0.7), C (0.7))
then B should be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B", "C"},
"B=0.8": {"B", "C"},
"C": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B", "C"},
"B=0.7": {"B", "C"},
"C": {"B"}
},
{"B": {"B"}, # provided to remove
"B=0.7": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C<=0.7"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.7-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="B", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_return_installed_package_to_remove_when_conflict_with_provided_matches(self, pacman: Mock):
"""
If the newest version o package A conflicts with a provided package C (by installed package B),
then B should be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B", "C"},
"B=0.8": {"B", "C"},
"C": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B", "C"},
"B=0.7": {"B", "C"},
"C": {"B"}
},
{"B": {"B"}, # provided to remove
"B=0.7": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": "community"}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": "0.7-1"}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_b = ArchPackage(name="B", installed=True, i18n=self.i18n)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__should_not_return_installed_to_remove_when_conflict_with_provider_is_self_conflict(self, pacman: Mock):
"""
If the newest version o package A conflicts with a provided package C (by A itself),
then A should not be marked as a package to be removed.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"C": {"A"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"C": {"A"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C<=1.0.0"},
'p': {"A": {"A"},
"A=1.1.0": {"A"},
"C": {"A"}},
'd': set(),
'r': "community",
'des': pkg_a.name}}
pacman.map_installed.return_value = {"A": pkg_a.version}
pacman.get_installed_size.return_value = {"A": 1}
pacman.map_required_by.return_value = {"A": set()}
self.deps_analyser.map_missing_deps.return_value = list()
res = self.summarizer.summarize(pkgs=[pkg_a], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
self.assertFalse(res.to_remove)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_cannot_upgrade_when_several_to_upgrade_conflict_with_each_other(self, pacman: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A conflicts with B, and newest version of B conflicts with A, then
both should be returned as "cannot upgrade"
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": pkg_b.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"B"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"A"},
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps',):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertFalse(res.to_upgrade)
self.assertEqual(2, len(res.cannot_upgrade))
self.assertIn(UpgradeRequirement(pkg=pkg_a, reason=" 'B'"), res.cannot_upgrade)
self.assertIn(UpgradeRequirement(pkg=pkg_b, reason=" 'A'"), res.cannot_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_cannot_upgrade_when_several_to_upgrade_conflict_with_provided_by_each_other(self, pacman: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A conflicts with C (provided by B), and newest version of B
conflicts with D (provided by A), then both should be returned as "cannot upgrade"
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": pkg_b.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C"},
'p': {"A": {"A"},
"A=1.1.0": {"A"},
"D": {"A"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"D"},
'p': {"B": {"B"},
"B=1.1.0": {"B"},
"C": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps',):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.to_install)
self.assertFalse(res.to_upgrade)
self.assertEqual(2, len(res.cannot_upgrade))
self.assertIn(UpgradeRequirement(pkg=pkg_a, reason=" 'B'"), res.cannot_upgrade)
self.assertIn(UpgradeRequirement(pkg=pkg_b, reason=" 'A'"), res.cannot_upgrade)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_a_package_to_upgrade_conflicts_with_another(self, pacman: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A conflicts with B, then B should be marked as 'to_remove'
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": pkg_b.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"B"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set(), "B": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.cannot_upgrade)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_a_package_to_upgrade_conflicts_with_provided_by_another(self, pacman: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A conflicts with C (provided by B), then B should be marked as 'to_remove'
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
"C": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": pkg_b.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"},
"C": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set(), "B": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.cannot_upgrade)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_a_package_to_upgrade_conflicts_with_provided_version_by_another(self, pacman: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A conflicts with specific version of C (provided by B),
then B should be marked as 'to_remove'
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"B"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
"C": {"B"}
}
]
pacman.map_repositories.return_value = {"A": pkg_a.repository, "B": pkg_b.repository}
pacman.map_updates_data.return_value = {"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': {"C<=1.1.0"},
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"},
"C": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': pkg_a.name}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.get_installed_size.return_value = {"A": 1, "B": 1}
pacman.map_required_by.return_value = {"A": set(), "B": set()}
self.deps_analyser.map_missing_deps.return_value = list()
self.deps_analyser.map_all_required_by.return_value = set()
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed',
'get_installed_size', 'map_required_by'):
getattr(pacman, method).assert_called()
for method in ('map_missing_deps', 'map_all_required_by'):
getattr(self.deps_analyser, method).assert_called()
self.assertFalse(res.cannot_upgrade)
self.assertFalse(res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, reason=" 'A'", extra_size=1)], res.to_remove)
@patch(f"{__app_name__}.gems.arch.dependencies.pacman")
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_cannot_upgrade_when_several_packages_to_install_conflict_with_each_other(self, *mocks: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A requires a new package C that conflicts D (new dependency of B),
and D conflicts with C, then A and B should be marked as 'cannot upgrade'.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman, pacman_dependencies = mocks[0], mocks[1]
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"C"},
"D": {"D"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {c: "community" for c in ("A", "B", "C", "D")}
pacman.map_updates_data.side_effect = [{"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': set(),
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': {"C"},
'r': pkg_a.repository,
'des': "A"},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': {"D"},
'r': pkg_a.repository,
'des': "B"}
},
{"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"D"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"},
"D": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"C"},
'p': {"D": {"D"},
"D=1.1.0": {"D"}},
'd': set(),
'r': "community",
'des': "D"}
}]
pacman_dependencies.map_updates_data.return_value = {"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"D"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"},
"D": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"C"},
'p': {"D": {"D"},
"D=1.1.0": {"D"}},
'd': set(),
'r': "community",
'des': "D"}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.map_required_by.return_value = {c: set() for c in ("A", "B", "C", "D")}
self.deps_analyser = DependenciesAnalyser(aur_client=self.aur_client, i18n=self.i18n, logger=Mock())
self.summarizer.deps_analyser = self.deps_analyser
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed'):
getattr(pacman, method).assert_called()
pacman_dependencies.map_updates_data.assert_called()
self.assertFalse(res.to_install)
self.assertFalse(res.to_upgrade)
self.assertEqual(2, len(res.cannot_upgrade))
self.assertIn(UpgradeRequirement(pkg=pkg_a, reason="'C' 'D'"), res.cannot_upgrade)
self.assertIn(UpgradeRequirement(pkg=pkg_b, reason="'C' 'D'"), res.cannot_upgrade)
@patch(f"{__app_name__}.gems.arch.dependencies.pacman")
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_cannot_upgrade_when_packages_to_install_conflict_with_version_of_each_other(self, *mocks: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A requires a new package C that conflicts with D's version
(new dependency of B), and D conflicts with C's version, then A and B should be marked as 'cannot upgrade'.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman, pacman_dependencies = mocks[0], mocks[1]
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"C"},
"D": {"D"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {c: "community" for c in ("A", "B", "C", "D")}
pacman.map_updates_data.side_effect = [{"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': set(),
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': {"C"},
'r': pkg_a.repository,
'des': "A"},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': {"D"},
'r': pkg_a.repository,
'des': "B"}
},
{"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"D<=1.1.0"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"},
"D": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"C<=1.1.0"},
'p': {"D": {"D"},
"D=1.1.0": {"D"}},
'd': set(),
'r': "community",
'des': "D"}
}]
pacman_dependencies.map_updates_data.return_value = {"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"D<=1.1.0"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"},
"D": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': {"C<=1.1.0"},
'p': {"D": {"D"},
"D=1.1.0": {"D"}},
'd': set(),
'r': "community",
'des': "D"}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.map_required_by.return_value = {c: set() for c in ("A", "B", "C", "D")}
self.deps_analyser = DependenciesAnalyser(aur_client=self.aur_client, i18n=self.i18n, logger=Mock())
self.summarizer.deps_analyser = self.deps_analyser
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed'):
getattr(pacman, method).assert_called()
pacman_dependencies.map_updates_data.assert_called()
self.assertFalse(res.to_install)
self.assertFalse(res.to_upgrade)
self.assertEqual(2, len(res.cannot_upgrade))
self.assertIn(UpgradeRequirement(pkg=pkg_a, reason="'C' 'D'"), res.cannot_upgrade)
self.assertIn(UpgradeRequirement(pkg=pkg_b, reason="'C' 'D'"), res.cannot_upgrade)
@patch(f"{__app_name__}.gems.arch.dependencies.pacman")
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_to_update_conflicts_with_to_install(self, *mocks: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A requires a new package C that conflicts with B,
then B should be marked as "to_remove"
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman, pacman_dependencies = mocks[0], mocks[1]
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"C"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {c: "community" for c in ("A", "B", "C")}
pacman.map_updates_data.side_effect = [{"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': set(),
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': {"C"},
'r': pkg_a.repository,
'des': "A"},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': "B"}
},
{"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
]
pacman_dependencies.map_updates_data.return_value = {"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.map_required_by.return_value = {c: set() for c in ("A", "B", "C")}
pacman.get_installed_size.return_value = {"A": 1, "B": 1, "C": 1}
self.deps_analyser = DependenciesAnalyser(aur_client=self.aur_client, i18n=self.i18n, logger=Mock())
self.summarizer.deps_analyser = self.deps_analyser
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed', 'get_installed_size',
'map_required_by'):
getattr(pacman, method).assert_called()
pacman_dependencies.map_updates_data.assert_called()
self.assertFalse(res.cannot_upgrade)
pkg_c = ArchPackage(name="C", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
self.assertEqual([UpgradeRequirement(pkg=pkg_c, required_size=1, extra_size=1, reason=": A")], res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, extra_size=1, reason=" 'C'")], res.to_remove)
@patch(f"{__app_name__}.gems.arch.dependencies.pacman")
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_to_update_conflicts_with_specific_version_of_install(self, *mocks: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A requires a new package C that conflicts with latest version of B,
then B should be marked as 'to_remove'.
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman, pacman_dependencies = mocks[0], mocks[1]
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"C"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
}
]
pacman.map_repositories.return_value = {c: "community" for c in ("A", "B", "C")}
pacman.map_updates_data.side_effect = [{"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': set(),
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': {"C"},
'r': pkg_a.repository,
'des': "A"},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': "B"}
},
{"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B<=1.1.0"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
]
pacman_dependencies.map_updates_data.return_value = {"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B<=1.1.0"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version}
pacman.map_required_by.return_value = {c: set() for c in ("A", "B", "C")}
pacman.get_installed_size.return_value = {"A": 1, "B": 1, "C": 1}
self.deps_analyser = DependenciesAnalyser(aur_client=self.aur_client, i18n=self.i18n, logger=Mock())
self.summarizer.deps_analyser = self.deps_analyser
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed', 'get_installed_size',
'map_required_by'):
getattr(pacman, method).assert_called()
pacman_dependencies.map_updates_data.assert_called()
self.assertFalse(res.cannot_upgrade)
pkg_c = ArchPackage(name="C", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
self.assertEqual([UpgradeRequirement(pkg=pkg_c, required_size=1, extra_size=1, reason=": A")], res.to_install)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_b, extra_size=1, reason=" 'C'")], res.to_remove)
@patch(f"{__app_name__}.gems.arch.dependencies.pacman")
@patch(f"{__app_name__}.gems.arch.updates.pacman")
def test__return_as_to_remove_when_to_update_conflicts_with_to_install_and_it_has_deps(self, *mocks: Mock):
"""
Consider package A and B are selected to be upgraded:
If the newest version o package A requires a new package C that conflicts with B,
then B should be marked as "to_remove" and its dependents as well (package 'D').
"""
pkg_a = ArchPackage(name="A", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pkg_b = ArchPackage(name="B", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
pacman, pacman_dependencies = mocks[0], mocks[1]
pacman.map_provided.side_effect = [{"A": {"A"}, # remote provided
"A=1.1.0": {"A"},
"B": {"B"},
"B=1.1.0": {"B"},
"C": {"C"}
},
{"A": {"A"}, # provided
"A=1.0.0": {"A"},
"B": {"B"},
"B=1.0.0": {"B"},
"D": {"D"},
"D=0.7.0": {"D"}
},
{"B": {"B"}, # provided to remove
"B=1.0.0": {"B"},
"D": {"D"},
"D=0.7.0": {"D"}
}
]
pacman.map_repositories.return_value = {c: "community" for c in ("A", "B", "C", "D")}
pacman.map_updates_data.side_effect = [{"A": {'ds': 1,
's': 1,
'v': pkg_a.latest_version,
'c': set(),
'p': {"A": {"A"},
"A=1.1.0": {"A"}},
'd': {"C"},
'r': pkg_a.repository,
'des': "A"},
"B": {'ds': 1,
's': 1,
'v': pkg_b.latest_version,
'c': set(),
'p': {"B": {"B"},
"B=1.1.0": {"B"}},
'd': set(),
'r': pkg_a.repository,
'des': "B"}
},
{"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
]
pacman_dependencies.map_updates_data.return_value = {"C": {'ds': 1,
's': 1,
'v': "1.1.0-1",
'c': {"B"},
'p': {"C": {"C"},
"C=1.1.0": {"C"}},
'd': set(),
'r': "community",
'des': "C"}
}
pacman_dependencies.map_required_by.return_value = {"B": {"D"}}
pacman.map_installed.return_value = {"A": pkg_a.version, "B": pkg_b.version, "D": "0.7.0"}
pacman.map_required_by.return_value = {**{c: set() for c in ("A", "C", "D")}, "B": {"D"}}
pacman.map_required_dependencies.return_value = {"D": {"B"}}
pacman.get_installed_size.return_value = {"A": 1, "B": 1, "C": 1, "D": 1}
self.deps_analyser = DependenciesAnalyser(aur_client=self.aur_client, i18n=self.i18n, logger=Mock())
self.summarizer.deps_analyser = self.deps_analyser
res = self.summarizer.summarize(pkgs=[pkg_a, pkg_b], root_password=None, arch_config=self.config_)
for method in ('map_provided', 'map_repositories', 'map_updates_data', 'map_installed', 'get_installed_size',
'map_required_by', 'map_required_dependencies'):
getattr(pacman, method).assert_called()
for method in ('map_updates_data', 'map_required_by'):
getattr(pacman_dependencies, method).assert_called()
self.assertFalse(res.cannot_upgrade)
self.assertEqual([UpgradeRequirement(pkg=pkg_a, required_size=1, extra_size=0)], res.to_upgrade)
pkg_c = ArchPackage(name="C", version="1.0.0-1", latest_version="1.1.0-1", repository="community")
self.assertEqual([UpgradeRequirement(pkg=pkg_c, required_size=1, extra_size=1, reason=": A")], res.to_install)
self.assertEqual(2, len(res.to_remove))
self.assertIn(UpgradeRequirement(pkg=pkg_b, extra_size=1, reason=" 'C'"), res.to_remove)
pkg_d = ArchPackage(name="D", repository="community", version="0.7.0-1", latest_version="0.7.0-1")
self.assertIn(UpgradeRequirement(pkg=pkg_d, extra_size=1, reason=" 'B=1.0.0'"), res.to_remove)