# -*- coding: utf-8 -*-
# Copyright (C) 2013-2018 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import operator
import libcomps
import libdnf.transaction
import dnf.comps
import dnf.exceptions
import dnf.persistor
import dnf.util
import tests.support
from tests.support import mock
TRANSLATION = u"""Tato skupina zahrnuje nejmenší možnou množinu balíčků. Je vhodná například na instalace malých routerů nebo firewallů."""
class LangsTest(tests.support.TestCase):
@mock.patch('locale.getlocale', return_value=('cs_CZ', 'UTF-8'))
def test_get(self, _unused):
langs = dnf.comps._Langs().get()
self.assertEqual(langs, ['cs_CZ.UTF-8', 'cs_CZ', 'cs.UTF-8', 'cs', 'C'])
class CompsTest(tests.support.TestCase):
def setUp(self):
comps = dnf.comps.Comps()
comps._add_from_xml_filename(tests.support.COMPS_PATH)
self.comps = comps
def test_by_pattern(self):
comps = self.comps
self.assertLength(comps.groups_by_pattern('Base'), 1)
self.assertLength(comps.groups_by_pattern('*'), tests.support.TOTAL_GROUPS)
self.assertLength(comps.groups_by_pattern('Solid*'), 1)
group = dnf.util.first(comps.groups_by_pattern('Base'))
self.assertIsInstance(group, dnf.comps.Group)
def test_categories(self):
cat = self.comps.categories[0]
self.assertEqual(cat.name_by_lang['cs'], u'Základ systému')
self.assertEqual(cat.desc_by_lang['de'],
u'Verschiedene Kernstücke des Systems.')
self.assertCountEqual((id_.name for id_ in cat.group_ids),
('base', ))
self.assertCountEqual((id_.default for id_ in cat.group_ids),
(False, ))
self.assertTrue(all(isinstance(grp, dnf.comps.Group)
for grp in cat.groups_iter()))
def test_environments(self):
env = self.comps.environments[0]
self.assertEqual(env.name_by_lang['cs'], u'Prostředí Sugar')
self.assertEqual(env.desc_by_lang['de'],
u'Eine Software-Spielwiese zum Lernen des Lernens.')
self.assertCountEqual((id_.name for id_ in env.group_ids),
('somerset', 'Peppers'))
self.assertEqual(2, len(env.mandatory_groups))
self.assertTrue(all(isinstance(grp, dnf.comps.Group)
for grp in env.mandatory_groups))
self.assertCountEqual((id_.default for id_ in env.group_ids),
(True, False))
self.assertCountEqual((id_.name for id_ in env.option_ids),
('base',))
self.assertEqual(1, len(env.optional_groups))
self.assertTrue(all(isinstance(grp, dnf.comps.Group)
for grp in env.optional_groups))
self.assertTrue(all(isinstance(grp, dnf.comps.Group)
for grp in env.groups_iter()))
def test_groups(self):
g = self.comps.group_by_pattern('base')
self.assertTrue(g.visible)
g = self.comps.group_by_pattern('somerset')
self.assertFalse(g.visible)
def test_group_packages(self):
g = self.comps.group_by_pattern('base')
self.assertCountEqual(map(operator.attrgetter('name'), g.packages_iter()),
('tour', 'pepper'))
def test_iteration(self):
comps = self.comps
self.assertEqual([g.name for g in comps.groups_iter()],
['Base', 'Solid Ground', "Pepper's", "Broken Group"])
self.assertEqual([c.name for c in comps.categories_iter()],
['Base System'])
g = dnf.util.first(comps.groups_iter())
self.assertEqual(g.desc_by_lang['cs'], TRANSLATION)
def test_group_display_order(self):
self.assertEqual([g.name for g in self.comps.groups],
["Pepper's", 'Base', 'Solid Ground', 'Broken Group'])
def test_packages(self):
comps = self.comps
group = dnf.util.first(comps.groups_iter())
self.assertSequenceEqual([pkg.name for pkg in group.packages],
(u'pepper', u'tour'))
self.assertSequenceEqual([pkg.name for pkg in group.mandatory_packages],
(u'pepper', u'tour'))
def test_size(self):
comps = self.comps
self.assertLength(comps, 6)
self.assertLength(comps.groups, tests.support.TOTAL_GROUPS)
self.assertLength(comps.categories, 1)
self.assertLength(comps.environments, 1)
@mock.patch('locale.getlocale', return_value=('cs_CZ', 'UTF-8'))
def test_ui_name(self, _unused):
comps = self.comps
group = dnf.util.first(comps.groups_by_pattern('base'))
self.assertEqual(group.ui_name, u'Kritická cesta (Základ)')
@mock.patch('locale.getlocale', return_value=('cs_CZ', 'UTF-8'))
def test_ui_desc(self, _unused):
comps = self.comps
env = dnf.util.first(comps.environments_by_pattern('sugar-*'))
self.assertEqual(env.ui_description, u'Software pro výuku o vyučování.')
class PackageTest(tests.support.TestCase):
def test_instance(self):
lc_pkg = libcomps.Package('weather', libcomps.PACKAGE_TYPE_OPTIONAL)
pkg = dnf.comps.Package(lc_pkg)
self.assertEqual(pkg.name, 'weather')
self.assertEqual(pkg.option_type, dnf.comps.OPTIONAL)
class TestTransactionBunch(tests.support.TestCase):
def test_adding(self):
t1 = dnf.comps.TransactionBunch()
t1.install = {'right'}
t1.upgrade = {'tour'}
t1.remove = {'pepper'}
t2 = dnf.comps.TransactionBunch()
t2.install = {'pepper'}
t2.upgrade = {'right'}
t1 += t2
self.assertTransEqual(t1.install, ('right', 'pepper'))
self.assertTransEqual(t1.upgrade, ('tour', 'right'))
self.assertEmpty(t1.remove)
class SolverGroupTest(tests.support.DnfBaseTestCase):
REPOS = []
COMPS = True
COMPS_SOLVER = True
def test_install(self):
group_id = 'base'
trans = self.solver._group_install(group_id, dnf.comps.MANDATORY)
self.assertLength(trans.install, 2)
self._swdb_commit()
swdb_group = self.history.group.get(group_id)
self.assertCountEqual([i.getName() for i in swdb_group.getPackages()], ['pepper', 'tour'])
self.assertEqual(swdb_group.getPackageTypes(), dnf.comps.MANDATORY)
def test_removable_pkg(self):
comps_group = self.comps.group_by_pattern('base')
self.solver._group_install(comps_group.id, dnf.comps.MANDATORY, [])
tsis = []
pkg1 = self.base.sack.query().filter(name="pepper", epoch=0, version="20", release="0", arch="x86_64")[0]
self.history.rpm.add_install(pkg1, reason=libdnf.transaction.TransactionItemReason_GROUP)
pkg3 = self.base.sack.query().filter(name="tour", version="5", release="0", arch="noarch")[0]
self.history.rpm.add_install(pkg3, reason=libdnf.transaction.TransactionItemReason_GROUP)
group_id = "dupl"
swdb_group = self.history.group.new(group_id, group_id, group_id, dnf.comps.DEFAULT)
swdb_group.addPackage("tour", True, dnf.comps.MANDATORY)
self.history.group.install(swdb_group)
self._swdb_commit(tsis)
# pepper is in single group with reason "group"
self.assertTrue(self.solver._removable_pkg('pepper'))
# right's reason is "dep"
self.assertFalse(self.solver._removable_pkg('right'))
# tour appears in more than one group
self.assertFalse(self.solver._removable_pkg('tour'))
swdb_group = self.history.group.get(group_id)
self.history.group.remove(swdb_group)
# tour appears only in one group now
self.assertTrue(self.solver._removable_pkg('tour'))
def test_remove(self):
grp = self.comps.group_by_pattern('base')
self.solver._group_install(grp.id, dnf.comps.MANDATORY, [])
grps = self.history.group.search_by_pattern('base')
for grp in grps:
self.solver._group_remove(grp)
# need to load groups again - loaded object is stays the same
grps = self.history.group.search_by_pattern('base')
for grp in grps:
self.assertFalse(grp.installed)
def test_upgrade(self):
# setup of the "current state"
group_id = 'base'
swdb_group = self.history.group.new(group_id, group_id, group_id, dnf.comps.MANDATORY)
for pkg_name in ['pepper', 'handerson']:
swdb_group.addPackage(pkg_name, True, dnf.comps.MANDATORY)
self.history.group.install(swdb_group)
self._swdb_commit()
swdb_group = self.history.group.get(group_id)
self.assertCountEqual([i.getName() for i in swdb_group.getPackages()], ('handerson', 'pepper'))
comps_group = self.comps.group_by_pattern(group_id)
trans = self.solver._group_upgrade(group_id)
self.assertTransEqual(trans.install, ('tour',))
self.assertTransEqual(trans.remove, ('handerson',))
self.assertTransEqual(trans.upgrade, ('pepper',))
self._swdb_commit()
swdb_group = self.history.group.get(group_id)
self.assertCountEqual([i.getName() for i in swdb_group.getPackages()], ('tour', 'pepper'))
class SolverEnvironmentTest(tests.support.DnfBaseTestCase):
REPOS = []
COMPS = True
COMPS_SOLVER = True
def test_install(self):
env_id = 'sugar-desktop-environment'
env = self.comps._environment_by_id(env_id)
trans = self.solver._environment_install(env_id, dnf.comps.MANDATORY, [])
self._swdb_commit()
self.assertCountEqual([pkg.name for pkg in trans.install], ('pepper', 'trampoline', 'hole', 'lotus'))
sugar = self.history.env.get(env_id)
self.assertCountEqual([i.getGroupId() for i in sugar.getGroups()], ('Peppers', 'somerset', 'base'))
somerset = self.history.group.get('somerset')
self.assertIsNotNone(somerset)
self.assertEqual(somerset.getPackageTypes(), dnf.comps.MANDATORY)
base = self.history.group.get('base')
self.assertEqual(base, None)
def test_remove(self):
env_id = 'sugar-desktop-environment'
comps_env = self.comps.environment_by_pattern(env_id)
self.solver._environment_install(comps_env.id, dnf.comps.MANDATORY, [])
self._swdb_commit()
swdb_env = self.history.env.get(comps_env.id)
self.assertEqual(swdb_env.getPackageTypes(), dnf.comps.MANDATORY)
group_ids = [i.getGroupId() for i in swdb_env.getGroups()]
self.solver._environment_remove(comps_env.id)
self._swdb_commit()
swdb_env = self.history.env.get(comps_env.id)
# if swdb_env is None, then it's removed
self.assertIsNone(swdb_env)
# test if also all groups were removed
for group_id in group_ids:
swdb_group = self.history.group.get(group_id)
self.assertIsNone(swdb_group)
# install it again with different pkg_types
self.solver._environment_install(comps_env.id, dnf.comps.OPTIONAL, [])
self._swdb_commit()
swdb_env = self.history.env.get(comps_env.id)
self.assertIsNotNone(swdb_env)
self.assertEqual(swdb_env.getPackageTypes(), dnf.comps.OPTIONAL)
group_ids = [i.getGroupId() for i in swdb_env.getGroups()]
self.assertTrue(len(group_ids))
for group_id in group_ids:
swdb_group = self.history.group.get(group_id)
if group_id == "base" and swdb_group is None:
continue
self.assertEqual(swdb_group.getPackageTypes(), dnf.comps.OPTIONAL)
def test_upgrade(self):
"""Upgrade environment, the one group it knows is no longer installed."""
env_id = "sugar-desktop-environment"
comps_env = self.comps.environment_by_pattern(env_id)
self.solver._environment_install(comps_env.id, dnf.comps.ALL_TYPES, [])
self._swdb_commit()
swdb_env = self.history.env.get(comps_env.id)
self.assertNotEqual(swdb_env, None)
# create a new transaction item for group Peppers with no packages
self._swdb_commit()
swdb_group = self.history.group.get('Peppers')
swdb_group = self.history.group.new(swdb_group.getGroupId(), swdb_group.getName(), swdb_group.getTranslatedName(), swdb_group.getPackageTypes())
self.history.group.install(swdb_group)
self._swdb_commit()
trans = self.solver._environment_upgrade(comps_env.id)
self._swdb_commit()
self.assertTransEqual(trans.install, ('hole', 'lotus'))
self.assertTransEqual(trans.upgrade, ('pepper', 'trampoline', 'lotus'))
self.assertEmpty(trans.remove)