# -*- coding: utf-8 -*-
# Copyright (C) 2012-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 unicode_literals
import itertools
import logging
import dnf.exceptions
import tests.support
class CommonTest(tests.support.ResultTestCase):
"""Tests common to any 'multilib_policy' and 'best'.
The test fixture consists of a dnf.Base instance that:
- contains a package "lotus-3-17.x86_64" (The package can be installed.)
- contains a package "lotus-3-17.i686" (The package can be installed.)
- contains a package "trampoline-2.1-1.noarch" that contains
"/all/be/there", provides "splendid > 2.0" and "php(a/b)" (The package
can be installed.)
- contains a package "mrkite-2-0.x86_64" (The package can be installed
together with the package "trampoline".)
- contains a package "mrkite-k-h-1-1.x86_64" (The package can be
installed.)
- contains a package "pepper-20-0.src"
- contains a package "pepper-20-2.x86_64" (The package cannot be
installed.)
- contains a package "librita-1-1.x86_64" (The package is already
installed.)
- contains a package "hole-1-2.x86_64" (The package can be installed as an
upgrade.)
"""
REPOS = ['main', 'third_party', 'broken_deps']
def test_install_arch_glob(self):
"""Test that the pkg specification can contain an architecture glob."""
self.base.install("lotus.*6*")
installed = self.installed_removed(self.base)[0]
self.assertCountEqual(map(str, installed),
['lotus-3-17.i686',
'lotus-3-17.x86_64'])
def test_install_filename_glob(self):
"""Test that the pkg to be installed can be specified by fname glob."""
self.base.install("*/there")
(installed, _) = self.installed_removed(self.base)
self.assertCountEqual(map(str, installed),
('trampoline-2.1-1.noarch',))
self.base.install("/all/*/there")
(installed, _) = self.installed_removed(self.base)
self.assertCountEqual(map(str, installed),
('trampoline-2.1-1.noarch',))
def test_install_name(self):
"""Test that the package to be installed can be specified by name."""
self.base.install("mrkite")
available = self.base.sack.query().available()
expected = available.filter(name=["mrkite", "trampoline"]).run()
# ensure sanity of the test (otherwise it would pass no matter what):
self.assertEqual(len(expected), 2)
new_set = self.base.sack.query().installed() + expected
self.assertResult(self.base, new_set)
def test_install_name_glob(self):
"""Test that the pkg to be installed can be specified by name glob."""
self.base.install("mrkite*")
installed = self.installed_removed(self.base)[0]
self.assertCountEqual(map(str, installed),
['mrkite-2-0.x86_64',
'mrkite-k-h-1-1.x86_64',
'trampoline-2.1-1.noarch'])
def test_install_name_glob_exclude(self):
"""Test that glob excludes play well with glob installs."""
subj_ex = dnf.subject.Subject('*-1')
pkgs_ex = subj_ex.get_best_query(self.base.sack)
self.base.sack.add_excludes(pkgs_ex)
self.base.install('mrkite*')
(installed, _) = self.installed_removed(self.base)
self.assertCountEqual(map(str, installed),
['mrkite-2-0.x86_64',
'trampoline-2.1-1.noarch'])
def test_install_nevra(self):
"""Test that the package to be installed can be specified by NEVRA."""
self.base.install("lotus-3-17.i686")
lotus, = dnf.subject.Subject('lotus-3-17.i686').get_best_query(self.base.sack)
new_set = self.base.sack.query().installed() + [lotus]
self.assertResult(self.base, new_set)
def test_install_provide_slash(self):
self.base.install("php(a/b)")
(installed, _) = self.installed_removed(self.base)
self.assertCountEqual(map(str, installed),
('trampoline-2.1-1.noarch',))
def test_install_provide_version(self):
"""Test that the pkg to be installed can be spec. by provide ver."""
self.base.install('splendid > 2.0')
self.assertGreater(self.base._goal.req_length(), 0)
trampoline = self.base.sack.query().available().filter(
name="trampoline")
new_set = self.base.sack.query().installed() + trampoline.run()
self.assertResult(self.base, new_set)
def test_package_install_conflict(self):
"""Test that a conflicting package cannot be installed."""
p = self.base.sack.query().available().filter(
nevra='pepper-20-2.x86_64')[0]
self.assertEqual(1, self.base.package_install(p))
with self.assertRaises(dnf.exceptions.DepsolveError):
self.base.resolve()
def test_package_install_installed(self):
"""Test that nothing changes if an installed package matches."""
p = self.base.sack.query().available()._nevra("librita-1-1.x86_64")[0]
with tests.support.mock.patch('logging.Logger.warning'):
self.base.package_install(p)
self.base.resolve()
self.assertEmpty(self.base._goal.list_reinstalls())
self.base.history.close()
self.base.package_reinstall(p)
self.base.resolve()
self.assertLength(self.base._goal.list_reinstalls(), 1)
def test_package_install_upgrade(self):
"""Test that the pkg to be installed can be an upgrade."""
p = self.base.sack.query().available().filter(
nevra='hole-1-2.x86_64')[0]
self.assertEqual(1, self.base.package_install(p))
installed, removed = self.installed_removed(self.base)
self.assertIn(p, installed)
self.assertGreaterEqual(
removed,
set(self.base.sack.query().installed().filter(name='hole')))
def test_pkg_install_installable(self):
"""Test that the package to be installed can be a package instance."""
p = self.base.sack.query().available().filter(
nevra='lotus-3-17.x86_64')[0]
self.assertEqual(1, self.base.package_install(p))
self.base.resolve()
self.assertEqual(1, len(self.base._goal.list_installs()))
def test_pkg_install_installonly(self):
"""Test that installonly packages are installed, not upgraded."""
self.base.conf.installonlypkgs += ['hole']
p = self.base.sack.query().available().filter(
nevra='hole-1-2.x86_64')[0]
self.assertEqual(1, self.base.package_install(p))
installed, removed = self.installed_removed(self.base)
self.assertIn(p, installed)
self.assertFalse(
set(removed) &
set(self.base.sack.query().installed().filter(name='hole')))
class MultilibAllTest(tests.support.ResultTestCase):
"""Tests for multilib_policy='all'.
The test fixture consists of a dnf.Base instance that:
- has conf.multilib_policy == "all"
- has conf.best == False
- contains a package "pepper-20-2" (The package cannot be installed.)
- contains a package "lotus-3-16.x86_64" that contains "/usr/lib*/liblot*"
in a "main" repository (The package can be installed.)
- contains a package "lotus-3-16.i686" that contains "/usr/lib*/liblot*" in
the "main" repository (The package can be installed.)
- contains a package "librita-1-1.x86_64" (The package is already
installed.)
- contains a package "hole-1-2.x86_64" (The package can be installed as an
upgrade.)
- contains a package "pepper-20-0.src"
- contains a package "pepper-20-0.x86_64" (The package is already
installed.)
- contains nothing that matches "not-available"
- contains a package that provides "henry(the_horse)" (The package can be
installed.)
- contains a package "lotus-3-17.x86_64" not in a "main" repository (The
package can be installed.)
- contains a package "lotus-3-17.i686" not in the "main" repository (The
package can be installed.)
"""
REPOS = ['main', 'third_party', 'broken_deps']
def setUp(self):
super(MultilibAllTest, self).setUp()
self.base.conf.multilib_policy = "all"
assert self.base.conf.best is False
def test_install_conflict(self):
"""Test that the exception is raised if the package conflicts."""
self.base.install('pepper-20-2')
with self.assertRaises(dnf.exceptions.DepsolveError):
self.base.resolve()
def test_install_filename(self):
"""Test that the pkg to be installed can be specified by filename."""
self.base.install("/usr/lib*/liblot*")
inst, _ = self.installed_removed(self.base)
self.assertCountEqual(
map(str, inst), ['lotus-3-16.x86_64', 'lotus-3-16.i686'])
def test_install_installed(self):
"""Test that nothing changes if an installed package matches."""
stdout = dnf.pycomp.StringIO()
with tests.support.wiretap_logs('dnf', logging.INFO, stdout):
self.base.install('librita')
self.assertEqual(self.base._goal.req_length(), 0)
self.assertIn(
'Package librita-1-1.x86_64 is already installed.',
stdout.getvalue())
def test_install_installonly(self):
"""Test that installonly packages are installed, not upgraded."""
self.base.conf.installonlypkgs += ['hole']
self.base.install('hole-1-2')
installed, removed = self.installed_removed(self.base)
self.assertGreaterEqual(
installed,
set(self.base.sack.query().available()._nevra('hole-1-2.x86_64')))
self.assertEmpty(removed)
def test_install_multilib(self):
"""Test that pkgs for all architectures are installed if available."""
cnt = self.base.install("lotus")
self.assertEqual(cnt, 2)
installed = self.installed_removed(self.base)[0]
self.assertLessEqual(
set(installed),
set(self.base.sack.query().available().filter(name='lotus')))
def test_install_name_choice(self):
"""Test that the matching pkg that can be installed is installed."""
# Don't install the SRPM.
self.base.sack.add_excludes(
dnf.subject.Subject('pepper.src').get_best_query(self.base.sack))
stdout = dnf.pycomp.StringIO()
with tests.support.wiretap_logs('dnf', logging.INFO, stdout):
self.base.install('pepper')
self.assertEqual(self.base._goal.req_length(), 0)
self.assertIn(
'Package pepper-20-0.x86_64 is already installed.',
stdout.getvalue())
def test_install_nonexistent(self):
"""Test that the exception is raised if no package matches."""
with self.assertRaises(dnf.exceptions.MarkingError) as context:
self.base.install('not-available')
self.assertEqual(context.exception.pkg_spec, 'not-available')
installed_pkgs = self.base.sack.query().installed().run()
self.assertResult(self.base, installed_pkgs)
def test_install_provide(self):
"""Test that the pkg to be installed can be specified by provide."""
self.base.install("henry(the_horse)")
self.assertGreater(self.base._goal.req_length(), 0)
def test_install_reponame(self):
"""Test whether packages are filtered by the reponame."""
result = itertools.chain(
self.base.sack.query().installed(),
dnf.subject.Subject('lotus-3-16').get_best_query(self.base.sack))
self.base.install('lotus', reponame='main')
self.assertResult(self.base, result)
assert dnf.subject.Subject('lotus-3-17').get_best_query(self.base.sack), \
('the base must contain packages a package in another repo '
'which matches the pattern but is preferred, otherwise the '
'test makes no sense')
def test_install_upgrade(self):
"""Test that the pkg to be installed can be an upgrade."""
self.base.install('hole-1-2')
installed, removed = self.installed_removed(self.base)
self.assertGreaterEqual(
installed,
set(self.base.sack.query().available()._nevra('hole-1-2.x86_64')))
self.assertGreaterEqual(
removed,
set(self.base.sack.query().installed().filter(name='hole')))
class MultilibBestTest(tests.support.ResultTestCase):
"""Tests for multilib_policy='best'.
The test fixture consists of a dnf.Base instance that:
- has conf.multilib_policy == "best"
- has conf.best == False
- contains a package "pepper-20-2" (The package cannot be installed.)
- contains a package "lotus-3-16.x86_64" that contains "/usr/lib*/liblot*"
in a "main" repository (The package can be installed.)
- contains a package "lotus-3-16.i686" that contains "/usr/lib*/liblot*"
in the "main" repository (The package can be installed.)
- contains nothing that matches "/not/exist/"
- contains a package "librita-1-1.x86_64" (The package is already
installed.)
- contains a package "hole-1-2.x86_64" (The package can be installed as an
upgrade.)
- contains a package "lotus-3-17.x86_64" not in the "main" repository (The
package can be installed.)
- contains a package "pepper-20-0.src"
- contains a package "pepper-20-0.x86_64" (The package is already
installed.)
- contains nothing that matches "not-available"
- contains a package "trampoline" that provides "henry(the_horse)" (The
package can be installed.)
- contains a package "lotus-3-17.i686" not in the "main" repository (The
package can be installed.)
- contains a package "hole-1-1.x86_64" (The package is already installed
and is not available.)
"""
REPOS = ['main', 'third_party', 'broken_deps']
def setUp(self):
super(MultilibBestTest, self).setUp()
self.installed = self.base.sack.query().installed().run()
self.assertEqual(self.base.conf.multilib_policy, "best")
assert self.base.conf.best is False
def test_install_conflict(self):
"""Test that the exception is raised if the package conflicts."""
self.base.install('pepper-20-2')
with self.assertRaises(dnf.exceptions.DepsolveError):
self.base.resolve()
def test_install_filename(self):
"""Test that the pkg to be installed can be specified by filename."""
self.base.install("/usr/lib*/liblot*")
inst, _ = self.installed_removed(self.base)
self.assertCountEqual(map(str, inst), ['lotus-3-16.x86_64'])
self.assertRaises(dnf.exceptions.MarkingError,
self.base.install, "/not/exist/")
def test_install_installed(self):
"""Test that nothing changes if an installed package matches."""
stdout = dnf.pycomp.StringIO()
with tests.support.wiretap_logs('dnf', logging.INFO, stdout):
self.base.install('librita')
installed, removed = self.installed_removed(self.base)
self.assertEmpty(installed)
self.assertEmpty(removed)
self.assertIn(
'Package librita-1-1.x86_64 is already installed.',
stdout.getvalue())
def test_install_installonly(self):
"""Test that installonly packages are installed, not upgraded."""
self.base.conf.installonlypkgs += ['hole']
self.base.install('hole-1-2')
installed, removed = self.installed_removed(self.base)
self.assertGreaterEqual(
installed,
set(self.base.sack.query().available()._nevra('hole-1-2.x86_64')))
self.assertEmpty(removed)
def test_install_multilib(self):
"""Test that a pkg for only one architecture are installed."""
cnt = self.base.install("lotus")
self.assertEqual(cnt, 1)
new_package, = dnf.subject.Subject('lotus-3-17.x86_64').get_best_query(self.base.sack)
new_set = self.installed + [new_package]
self.assertResult(self.base, new_set)
def test_install_name_choice(self):
"""Test that the matching pkg that can be installed is installed."""
# Don't install the SRPM.
self.base.sack.add_excludes(
dnf.subject.Subject('pepper.src').get_best_query(self.base.sack))
stdout = dnf.pycomp.StringIO()
with tests.support.wiretap_logs('dnf', logging.INFO, stdout):
self.base.install('pepper')
installed, removed = self.installed_removed(self.base)
self.assertEmpty(installed | removed)
self.assertIn(
'Package pepper-20-0.x86_64 is already installed.',
stdout.getvalue())
def test_install_nonexistent(self):
"""Test that the exception is raised if no package matches."""
with self.assertRaises(dnf.exceptions.MarkingError) as context:
self.base.install('not-available')
self.assertEqual(context.exception.pkg_spec, 'not-available')
installed_pkgs = self.base.sack.query().installed().run()
self.assertResult(self.base, installed_pkgs)
def test_install_provide(self):
"""Test that the pkg to be installed can be specified by provide."""
self.base.install("henry(the_horse)")
self.assertGreater(self.base._goal.req_length(), 0)
trampoline = self.base.sack.query().available().filter(
name="trampoline")
new_set = self.installed + trampoline.run()
self.assertResult(self.base, new_set)
def test_install_reponame(self):
"""Test whether packages are filtered by the reponame."""
result = itertools.chain(
self.base.sack.query().installed(),
dnf.subject.Subject('lotus-3-16.x86_64')
.get_best_query(self.base.sack))
self.base.install('lotus', reponame='main')
self.assertResult(self.base, result)
assert dnf.subject.Subject('lotus-3-17.x86_64').get_best_query(self.base.sack), \
('the base must contain packages a package in another repo '
'which matches the pattern but is preferred, otherwise the '
'test makes no sense')
def test_install_unavailable(self):
"""Test that nothing changes if an unavailable package matches."""
stdout = dnf.pycomp.StringIO()
with tests.support.wiretap_logs('dnf', logging.INFO, stdout):
cnt = self.base.install('hole')
self.assertEqual(cnt, 1)
installed_pkgs = self.base.sack.query().installed().run()
self.assertResult(self.base, installed_pkgs)
self.assertIn(
'Package hole-1-1.x86_64 is already installed.',
stdout.getvalue())
def test_install_upgrade(self):
"""Test that the pkg to be installed can be an upgrade."""
self.base.install('hole-1-2')
installed, removed = self.installed_removed(self.base)
self.assertGreaterEqual(
installed,
set(self.base.sack.query().available()._nevra('hole-1-2.x86_64')))
self.assertGreaterEqual(
removed,
set(self.base.sack.query().installed().filter(name='hole')))
class BestTrueTest(tests.support.ResultTestCase):
"""Tests for best=True.
The test fixture consists of a dnf.Base instance that:
- has conf.best == True
- contains a package "pepper-20-2" (The package cannot be installed.)
"""
REPOS = ['broken_deps']
def setUp(self):
super(BestTrueTest, self).setUp()
self.base.conf.best = True
def test_install_name_choice(self):
"""Test that the latest version of the matching pkg is installed."""
with tests.support.mock.patch('logging.Logger.warning'):
self.base.install('pepper')
with self.assertRaises(dnf.exceptions.DepsolveError):
self.base.resolve()