pungi/tests/test_gather_phase.py

1195 lines
52 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
import copy
import mock
import os
import sys
try:
import unittest2 as unittest
except ImportError:
import unittest
import six
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from pungi.phases import gather
from pungi.phases.pkgset.common import MaterializedPackageSet
from pungi.phases.gather import _mk_pkg_map
from tests import helpers
class MockPackageSet(dict):
def __init__(self, *args):
for pkg in args:
self[pkg.path] = pkg
class MockPkg(object):
def __init__(self, path, is_system_release=False):
self.path = path
self.is_system_release = is_system_release
filename = os.path.basename(path)
self.nvr, self.arch, _ = filename.rsplit('.', 2)
self.name, self.version, self.release = self.nvr.rsplit('-', 2)
def __repr__(self):
return self.nvr
def __lt__(self, another):
return self.nvr < another.nvr
def _join(a, *rest):
res = copy.deepcopy(a)
for b in rest:
for key in res:
res[key].extend(b[key])
return res
class TestGatherWrapper(helpers.PungiTestCase):
def setUp(self):
super(TestGatherWrapper, self).setUp()
self.compose = helpers.DummyCompose(self.topdir, {})
self.package_set = mock.Mock()
self.variant = helpers.MockVariant(
uid='Server', arches=['x86_64'], type='variant')
self.optional = helpers.MockVariant(
uid='Server-optional', arches=['x86_64'], type='optional', parent=self.variant)
self.addon = helpers.MockVariant(
uid='Server-HA', arches=['x86_64'], type='addon', parent=self.variant)
self.lp = helpers.MockVariant(
uid='Server-LP', arches=['x86_64'], type='layered-product', parent=self.variant)
self.server_packages = {
"rpm": [{'path': '/build/foo-1.0-1.x86_64.rpm', 'flags': ['input']}],
"srpm": [{'path': '/build/foo-1.0-1.src.rpm', 'flags': []}],
"debuginfo": [{'path': '/build/foo-debuginfo-1.0-1.x86_64.rpm', 'flags': []}],
}
self.maxDiff = None
def _dummy_gather(self, compose, arch, variant, package_sets, **kwargs):
self.assertEqual(
package_sets, self.package_set,
'Called gather_packages on %s.%s with bad package sets' % (variant.uid, arch))
if variant.uid == 'Server':
return self.server_packages
if variant.uid == 'Server-optional':
return self.optional_packages
if variant.uid == 'Server-HA':
return self.addon_packages
if variant.uid == 'Server-LP':
return self.lp_packages
self.assertFalse('This should not be reached - variant %s' % variant.uid)
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_single_variant(self, gather_packages, write_packages):
# There is only one variant: exactly the packages returned by gather
# method should be returned without modifications.
self.compose.all_variants = {'Server': self.variant}
expected_server_packages = copy.deepcopy(self.server_packages)
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages}})
self.assertEqual(
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.variant,
expected_server_packages, path_prefix='/build')])
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_addon(self, gather_packages, write_packages):
# Addon has all packages that parent has, plus one extra input package
# and one fulltree-exclude package. Only the input one should remain in
# addon, and the fulltree one should move to parent.
self.compose.all_variants = {'Server': self.variant, 'Server-HA': self.addon}
move_to_parent = {'path': '/build/foo-common-1.0-1.x86_64.rpm', 'flags': ['fulltree-exclude']}
keep_in_addon = {'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']}
expected_server_packages = _join(self.server_packages, _mk_pkg_map([move_to_parent]))
self.addon_packages = _join(self.server_packages, _mk_pkg_map([keep_in_addon, move_to_parent]))
expected_addon_packages = _mk_pkg_map(
[{'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']}])
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages,
'Server-HA': expected_addon_packages}})
six.assertCountEqual(
self,
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.variant,
expected_server_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.addon,
expected_addon_packages, path_prefix='/build')])
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_layered_product(self, gather_packages, write_packages):
# This test is pretty much identical to the one for addon.
self.compose.all_variants = {'Server': self.variant, 'Server-LP': self.lp}
move_to_parent = {'path': '/build/foo-common-1.0-1.x86_64.rpm', 'flags': ['fulltree-exclude']}
keep_in_lp = {'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']}
expected_server_packages = copy.deepcopy(self.server_packages)
expected_server_packages['rpm'].append(move_to_parent)
self.lp_packages = _join(self.server_packages, _mk_pkg_map([keep_in_lp, move_to_parent]))
expected_lp_packages = _mk_pkg_map(
[{'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']}])
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages,
'Server-LP': expected_lp_packages}})
six.assertCountEqual(
self,
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.variant,
expected_server_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.lp,
expected_lp_packages, path_prefix='/build')])
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_optional(self, gather_packages, write_packages):
# All packages in optional that are present in parent should be removed
# from optional. There is no move to parent here.
self.compose.all_variants = {'Server': self.variant, 'Server-optional': self.optional}
expected_server_packages = copy.deepcopy(self.server_packages)
self.optional_packages = _join(self.server_packages, _mk_pkg_map(
[{'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']},
{'path': '/build/foo-common-1.0-1.x86_64.rpm', 'flags': ['fulltree-exclude']}]))
expected_optional_packages = _mk_pkg_map(
[{'path': '/build/bar-1.0-1.x86_64.rpm', 'flags': ['input']}])
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages,
'Server-optional': expected_optional_packages}})
six.assertCountEqual(
self,
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.variant,
expected_server_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.optional,
expected_optional_packages, path_prefix='/build')])
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_all(self, gather_packages, write_packages):
# Addon contains an extra package compared to parent. Layered product
# contains an extra package compared to addon. Optional has one extra
# package on it's own compared to addon. Only the one extra package
# should remain in all non-parent variants.
#
# There are also two packages that should move to parent variant. Addon
# has one of them, layered product has both.
self.compose.all_variants = {'Server': self.variant, 'Server-optional': self.optional,
'Server-HA': self.addon, 'Server-LP': self.lp}
addon_extra_package = {'path': '/build/foo-addon-1.0.1-1.noarch.rpm', 'flags': []}
lp_extra_package = {'path': '/build/foo-layer-1.0.1-1.noarch.rpm', 'flags': []}
optional_extra_package = {'path': '/build/foo-optional-1.0.1-1.noarch.rpm', 'flags': []}
move_from_addon = {'path': '/build/foo-addon-contrib-1.0-1.noarch.rpm', 'flags': ['fulltree-exclude']}
move_from_lp = {'path': '/build/foo-layer-contrib-1.0-1.noarch.rpm', 'flags': ['fulltree-exclude']}
self.addon_packages = _join(self.server_packages, _mk_pkg_map(
[addon_extra_package, move_from_addon]))
self.lp_packages = _join(self.addon_packages, _mk_pkg_map(
[lp_extra_package, move_from_lp]))
self.optional_packages = _join(self.lp_packages, _mk_pkg_map(
[optional_extra_package]))
expected_server_packages = _join(self.server_packages, _mk_pkg_map(
[move_from_addon, move_from_lp]))
expected_addon_packages = _mk_pkg_map([addon_extra_package])
expected_lp_packages = _mk_pkg_map([lp_extra_package])
expected_optional_packages = _mk_pkg_map([optional_extra_package])
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages,
'Server-optional': expected_optional_packages,
'Server-HA': expected_addon_packages,
'Server-LP': expected_lp_packages}})
six.assertCountEqual(
self,
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.compose.all_variants['Server'],
expected_server_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.compose.all_variants['Server-optional'],
expected_optional_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.compose.all_variants['Server-HA'],
expected_addon_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.compose.all_variants['Server-LP'],
expected_lp_packages, path_prefix='/build')])
@mock.patch('pungi.phases.gather.write_packages')
@mock.patch('pungi.phases.gather.gather_packages')
def test_keep_srpm_in_lp(self, gather_packages, write_packages):
# There is one binary and source package in addon and lp but not in
# parent. Addon should remain unchanged and the binary package should
# disappear from lp.
# This seems peculiar and may not be correct.
self.compose.all_variants = {'Server': self.variant,
'Server-HA': self.addon,
'Server-LP': self.lp}
addon_extra_package = {'path': '/build/foo-addon-1.0.1-1.noarch.rpm', 'flags': []}
addon_extra_source = {'path': '/build/foo-addon-1.0.1-1.src.rpm', 'flags': []}
self.addon_packages = _join(self.server_packages, _mk_pkg_map(
[addon_extra_package], [addon_extra_source]))
self.lp_packages = _join(self.addon_packages)
expected_server_packages = _join(self.server_packages)
expected_addon_packages = _mk_pkg_map([addon_extra_package], [addon_extra_source])
expected_lp_packages = _mk_pkg_map([], [addon_extra_source])
gather_packages.side_effect = self._dummy_gather
result = gather.gather_wrapper(self.compose, self.package_set, '/build')
self.assertEqual(result, {'x86_64': {'Server': expected_server_packages,
'Server-HA': expected_addon_packages,
'Server-LP': expected_lp_packages}})
six.assertCountEqual(
self,
write_packages.call_args_list,
[mock.call(self.compose, 'x86_64', self.compose.all_variants['Server'],
expected_server_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.compose.all_variants['Server-HA'],
expected_addon_packages, path_prefix='/build'),
mock.call(self.compose, 'x86_64', self.compose.all_variants['Server-LP'],
expected_lp_packages, path_prefix='/build')])
def _make_materialized_pkgsets(pkgsets):
return [MaterializedPackageSet(pkgsets, {})]
class TestGetSystemRelease(unittest.TestCase):
def setUp(self):
self.compose = mock.Mock()
self.variant = helpers.MockVariant(uid='Server', arches=['x86_64'],
type='variant')
self.addon = helpers.MockVariant(uid='Server-HA', arches=['x86_64'],
type='addon', parent=self.variant)
def test_no_package_set(self):
self.assertEqual(
gather.get_system_release_packages(self.compose, 'x86_64',
self.variant, None),
(set(), set())
)
def test_no_arch_in_package_set(self):
self.assertEqual(
gather.get_system_release_packages(
self.compose, 'x86_64', self.variant, _make_materialized_pkgsets({})
),
(set(), set())
)
def test_no_system_release_package(self):
pkgset = MockPackageSet(MockPkg('/build/bash-1.0.0-1.x86_64.rpm'))
packages, filter_packages = gather.get_system_release_packages(
self.compose,
"x86_64",
self.variant,
_make_materialized_pkgsets({"x86_64": pkgset}),
)
self.assertEqual(packages, set())
self.assertEqual(filter_packages, set())
def test_picks_single(self):
pkgset = MockPackageSet(
MockPkg('/build/dummy-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, filter_packages = gather.get_system_release_packages(
self.compose,
"x86_64",
self.variant,
_make_materialized_pkgsets({"x86_64": pkgset}),
)
self.assertEqual(packages, set([("dummy", None)]))
self.assertEqual(filter_packages, set())
def test_prefers_variant(self):
pkgset = MockPackageSet(
MockPkg('/build/system-release-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-server-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, filter_packages = gather.get_system_release_packages(
self.compose,
"x86_64",
self.variant,
[MaterializedPackageSet({"x86_64": pkgset}, {})],
)
self.assertEqual(packages, set([("system-release-server", None)]))
self.assertEqual(filter_packages, set([("system-release", None)]))
def test_no_best_match(self):
pkgset = MockPackageSet(
MockPkg('/build/system-release-foo-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-bar-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, filter_packages = gather.get_system_release_packages(
self.compose,
"x86_64",
self.variant,
[MaterializedPackageSet({"x86_64": pkgset}, {})],
)
# In this case a random package is picked, so let's check that both
# list contain one package and that they are different.
self.assertEqual(len(packages), 1)
self.assertEqual(len(filter_packages), 1)
self.assertNotEqual(packages, filter_packages)
def test_optional_picks_parent(self):
pkgset = MockPackageSet(
MockPkg('/build/system-release-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-server-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-client-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, filter_packages = gather.get_system_release_packages(
self.compose,
"x86_64",
self.addon,
[MaterializedPackageSet({"x86_64": pkgset}, {})],
)
self.assertEqual(packages, set([("system-release-server", None)]))
six.assertCountEqual(
self,
filter_packages,
set([("system-release-client", None), ("system-release", None)]),
)
class TestTrimPackages(unittest.TestCase):
def setUp(self):
self.compose = mock.Mock()
self.variant = helpers.MockVariant(uid='Server', arches=['x86_64'],
type='variant')
self.addon = helpers.MockVariant(uid='Server-HA', arches=['x86_64'],
type='addon', parent=self.variant)
def test_trim_toplevel(self):
self.assertIsNone(gather.trim_packages(self.compose, 'x86_64', self.variant, {}))
def test_remove_package_explicitly(self):
to_remove = {'path': '/build/required-1.0.0-1.x86_64.rpm', 'flags': ['input']}
to_keep = {'path': '/build/empty-1.0.0-1.x86_64.rpm', 'flags': []}
pkg_map = _mk_pkg_map([to_remove, to_keep])
addon_pkgs, moved_to_parent, removed_pkgs = gather.trim_packages(
self.compose, 'x86_64', self.addon, pkg_map, remove_pkgs={'rpm': ['required']})
self.assertEqual(removed_pkgs, _mk_pkg_map([to_remove]))
self.assertEqual(addon_pkgs, _mk_pkg_map(set(['empty']), iterable_class=set))
self.assertEqual(moved_to_parent, _mk_pkg_map())
self.assertEqual(pkg_map, _mk_pkg_map([to_keep]))
def test_remove_package_present_in_parent(self):
# packages present in parent will be removed from addon
parent_pkgs = {
'rpm': [
('wanted', 'x86_64'),
]
}
to_remove = {'path': '/build/wanted-1.0.0-1.x86_64.rpm', 'flags': []}
pkg_map = _mk_pkg_map([to_remove])
addon_pkgs, moved_to_parent, removed_pkgs = gather.trim_packages(
self.compose, 'x86_64', self.addon, pkg_map, parent_pkgs=parent_pkgs)
self.assertEqual(removed_pkgs, _mk_pkg_map([to_remove]))
self.assertEqual(addon_pkgs, _mk_pkg_map(iterable_class=set))
self.assertEqual(moved_to_parent, _mk_pkg_map())
self.assertEqual(pkg_map, _mk_pkg_map())
def test_move_package_to_parent(self):
# fulltree-exclude packages in addon only will move to parent
to_move = {'path': '/build/wanted-1.0.0-1.x86_64.rpm', 'flags': ['fulltree-exclude']}
pkg_map = _mk_pkg_map([to_move])
addon_pkgs, moved_to_parent, removed_pkgs = gather.trim_packages(
self.compose, 'x86_64', self.addon, pkg_map, parent_pkgs={'rpm': []})
self.assertEqual(removed_pkgs, _mk_pkg_map())
self.assertEqual(addon_pkgs, _mk_pkg_map(iterable_class=set))
self.assertEqual(moved_to_parent, _mk_pkg_map([to_move]))
self.assertEqual(pkg_map, _mk_pkg_map())
def test_keep_explicit_input_in_addon(self):
# fulltree-exclude packages explictly in addon will be kept in addon
parent_pkgs = {'rpm': []}
pkg = {'path': '/build/wanted-1.0.0-1.x86_64.rpm', 'flags': ['fulltree-exclude', 'input']}
pkg_map = _mk_pkg_map([pkg])
addon_pkgs, moved_to_parent, removed_pkgs = gather.trim_packages(
self.compose, 'x86_64', self.addon, pkg_map, parent_pkgs=parent_pkgs)
self.assertEqual(removed_pkgs, _mk_pkg_map())
self.assertEqual(addon_pkgs, _mk_pkg_map(set(['wanted']), iterable_class=set))
self.assertEqual(moved_to_parent, _mk_pkg_map())
self.assertEqual(pkg_map, _mk_pkg_map([pkg]))
class TestWritePackages(helpers.PungiTestCase):
def test_write_packages(self):
self.compose = helpers.DummyCompose(self.topdir, {})
pkg_map = {
'rpm': [
{'path': '/build/foo-1.0-1.x86_64.rpm', 'flags': []},
{'path': '/build/foo-common-1.0-1.x86_64.rpm', 'flags': []},
{'path': '/alt/build/bar-1.0-1.noarch.rpm', 'flags': []},
],
'srpm': [
{'path': '/build/foo-1.0-1.src.rpm', 'flags': []},
{'path': '/alt/build/bar-1.0-1.src.rpm', 'flags': []},
],
'debuginfo': [
{'path': '/build/foo-debuginfo-1.0-1.x86_64.rpm', 'flags': []},
],
}
gather.write_packages(self.compose, 'x86_64', self.compose.variants['Server'], pkg_map, '/alt')
with open(os.path.join(self.topdir, 'work', 'x86_64', 'package_list',
'Server.x86_64.rpm.conf')) as f:
six.assertCountEqual(
self,
f.read().strip().split("\n"),
["/build/foo-1.0-1.x86_64.rpm",
"/build/foo-common-1.0-1.x86_64.rpm",
"/build/bar-1.0-1.noarch.rpm"]
)
with open(os.path.join(self.topdir, 'work', 'x86_64', 'package_list',
'Server.x86_64.srpm.conf')) as f:
six.assertCountEqual(
self,
f.read().strip().split("\n"),
["/build/foo-1.0-1.src.rpm", "/build/bar-1.0-1.src.rpm"],
)
with open(os.path.join(self.topdir, 'work', 'x86_64', 'package_list',
'Server.x86_64.debuginfo.conf')) as f:
self.assertEqual(f.read(), "/build/foo-debuginfo-1.0-1.x86_64.rpm\n")
class TestGetVariantPackages(helpers.PungiTestCase):
def test_no_variant(self):
compose = helpers.DummyCompose(self.topdir, {})
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', None, 'comps')
self.assertEqual(packages, set())
self.assertEqual(groups, set())
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_just_source(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set(['foo']), set(['core'])))
)
compose = helpers.DummyCompose(self.topdir, {})
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', compose.variants['Server'], 'comps')
self.assertEqual(packages, set(["foo"]))
self.assertEqual(groups, set(["core"]))
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_filter_system_release(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set(), set()))
)
compose = helpers.DummyCompose(self.topdir, {})
pkgset = MockPackageSet(
MockPkg('/build/system-release-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-server-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, groups, filter_packages = gather.get_variant_packages(
compose,
"x86_64",
compose.variants["Server"], "comps",
package_sets=[MaterializedPackageSet({"x86_64": pkgset}, {})],
)
self.assertEqual(packages, set([("system-release-server", None)]))
self.assertEqual(groups, set())
self.assertEqual(filter_packages, set([("system-release", None)]))
@mock.patch('pungi.phases.gather.get_gather_source')
def test_disable_filter_system_release(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([]), set([])))
)
compose = helpers.DummyCompose(self.topdir, {
'filter_system_release_packages': False
})
pkgset = MockPackageSet(
MockPkg('/build/system-release-1.0.0-1.x86_64.rpm', is_system_release=True),
MockPkg('/build/system-release-server-1.0.0-1.x86_64.rpm', is_system_release=True),
)
packages, groups, filter_packages = gather.get_variant_packages(
compose,
"x86_64",
compose.variants["Server"],
"comps",
package_sets=[MaterializedPackageSet({"x86_64": pkgset}, {})],
)
self.assertEqual(packages, set())
self.assertEqual(groups, set())
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_optional_gets_parent_and_addon(self, get_gather_source):
compose = helpers.DummyCompose(self.topdir, {})
compose.setup_optional()
compose.setup_addon()
def dummy_source(arch, variant):
if variant.uid == 'Server':
return (set(['server-pkg']), set(['server-group']))
if variant.uid == 'Server-HA':
return (set(['addon-pkg']), set(['addon-group']))
if variant.uid == 'Server-optional':
return (set(['opt-pkg']), set(['opt-group']))
self.assertFalse('This should not be reached')
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(side_effect=dummy_source)
)
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', compose.all_variants['Server-optional'], 'comps')
six.assertCountEqual(self, packages, ["server-pkg", "addon-pkg", "opt-pkg"])
six.assertCountEqual(self, groups, ["server-group", "addon-group", "opt-group"])
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_optional_does_not_inherit_filters(self, get_gather_source):
compose = helpers.DummyCompose(self.topdir, {
'filter_packages': [
('^Server(-HA)?$', {'*': ['filter-me']}),
]
})
compose.setup_optional()
compose.setup_addon()
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set(), set()))
)
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', compose.all_variants['Server-optional'], 'comps')
self.assertEqual(packages, set())
self.assertEqual(groups, set())
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_additional_packages(self, get_gather_source):
compose = helpers.DummyCompose(self.topdir, {
'additional_packages': [
('.*', {'*': ['pkg', 'foo.x86_64']}),
]
})
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set(), set()))
)
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', compose.all_variants['Server'], 'comps')
six.assertCountEqual(self, packages, [("pkg", None), ("foo", "x86_64")])
self.assertEqual(groups, set())
self.assertEqual(filter_packages, set())
@mock.patch('pungi.phases.gather.get_gather_source')
def test_additional_packages_incompatible_arch(self, get_gather_source):
compose = helpers.DummyCompose(self.topdir, {
'additional_packages': [
('.*', {'*': ['foo.ppc64']}),
]
})
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set(), set()))
)
with self.assertRaises(ValueError) as ctx:
packages, groups, filter_packages = gather.get_variant_packages(
compose, 'x86_64', compose.all_variants['Server'], 'comps')
self.assertIn('Incompatible package arch', str(ctx.exception))
class TestGetParentPkgs(unittest.TestCase):
def setUp(self):
self.variant = helpers.MockVariant(uid='Server', arches=['x86_64'],
type='variant')
self.addon = helpers.MockVariant(uid='Server-HA', arches=['x86_64'],
type='addon', parent=self.variant)
def test_returns_empty_for_toplevel(self):
pkg_map = mock.Mock()
result = gather.get_parent_pkgs('x86_64', self.variant, pkg_map)
self.assertEqual(result, _mk_pkg_map(iterable_class=set))
def test_on_addon(self):
pkg_map = {
'x86_64': {
'Server': {
'rpm': [
{'path': '/build/foo-1.0-1.x86_64.rpm', 'flags': []},
],
'srpm': [
{'path': '/build/foo-1.0-1.src.rpm', 'flags': []},
],
'debuginfo': [
{'path': '/build/foo-debuginfo-1.0-1.x86_64.rpm', 'flags': []},
],
}
}
}
result = gather.get_parent_pkgs('x86_64', self.addon, pkg_map)
self.assertEqual(result,
{'rpm': set([('foo', 'x86_64')]),
'srpm': set([('foo', 'src')]),
'debuginfo': set([('foo-debuginfo', 'x86_64')])})
class TestGatherPackages(helpers.PungiTestCase):
@mock.patch('pungi.phases.gather.get_variant_packages')
@mock.patch('pungi.phases.gather.get_gather_method')
def test_no_extra_options(self, get_gather_method, get_variant_packages):
packages, groups, filters = mock.Mock(), mock.Mock(), mock.Mock()
get_variant_packages.return_value = (packages, groups, filters)
compose = helpers.DummyCompose(self.topdir, {})
pkg_set = mock.Mock()
self.assertEqual(
gather.gather_packages(compose, 'x86_64', compose.variants['Server'], pkg_set),
{'rpm': [], 'srpm': [], 'debuginfo': []}
)
self.assertEqual(get_gather_method.call_args_list,
[mock.call(compose.conf['gather_method'])] * 3)
self.assertEqual(
get_variant_packages.call_args_list,
[
mock.call(compose, 'x86_64', compose.variants['Server'], 'module', pkg_set),
mock.call(compose, 'x86_64', compose.variants['Server'], 'comps', pkg_set),
mock.call(compose, 'x86_64', compose.variants['Server'], 'json', pkg_set),
],
)
self.assertEqual(
get_gather_method.return_value.return_value.call_args_list,
[mock.call('x86_64', compose.variants['Server'], packages, groups,
filters, set(), set(), pkg_set, fulltree_excludes=set(),
prepopulate=set())] * 3
)
@mock.patch('pungi.phases.gather.get_variant_packages')
def test_empty_variant(self, get_variant_packages):
packages, groups, filters = mock.Mock(), mock.Mock(), mock.Mock()
get_variant_packages.return_value = (packages, groups, filters)
compose = helpers.DummyCompose(self.topdir, {})
compose.variants['Server'].is_empty = True
pkg_set = mock.Mock()
self.assertEqual(
gather.gather_packages(compose, 'x86_64', compose.variants['Server'], pkg_set),
_mk_pkg_map()
)
self.assertEqual(get_variant_packages.call_args_list, [])
@mock.patch('pungi.phases.gather.get_variant_packages')
@mock.patch('pungi.phases.gather.get_gather_method')
def test_multilib_white_black_list(self, get_gather_method, get_variant_packages):
packages, groups, filters = mock.Mock(), mock.Mock(), mock.Mock()
get_variant_packages.return_value = (packages, groups, filters)
compose = helpers.DummyCompose(self.topdir, {
'multilib_whitelist': {'*': ['white']},
'multilib_blacklist': {'*': ['black']},
})
pkg_set = mock.Mock()
self.assertEqual(
gather.gather_packages(compose, 'x86_64', compose.variants['Server'], pkg_set),
{'rpm': [], 'srpm': [], 'debuginfo': []}
)
self.assertEqual(get_gather_method.call_args_list,
[mock.call(compose.conf['gather_method'])] * 3)
self.assertEqual(
get_variant_packages.call_args_list,
[
mock.call(compose, 'x86_64', compose.variants['Server'], 'module', pkg_set),
mock.call(compose, 'x86_64', compose.variants['Server'], 'comps', pkg_set),
mock.call(compose, 'x86_64', compose.variants['Server'], 'json', pkg_set),
],
)
self.assertEqual(
get_gather_method.return_value.return_value.call_args_list,
[mock.call('x86_64', compose.variants['Server'], packages, groups,
filters, set(['white']), set(['black']), pkg_set,
fulltree_excludes=set(), prepopulate=set())] * 3
)
@mock.patch('pungi.phases.gather.get_variant_packages')
@mock.patch('pungi.phases.gather.get_gather_method')
def test_per_source_method(self, get_gather_method, get_variant_packages):
packages, groups, filters = mock.Mock(), mock.Mock(), mock.Mock()
get_variant_packages.return_value = (packages, groups, filters)
compose = helpers.DummyCompose(self.topdir, {
'multilib_whitelist': {'*': ['white']},
'multilib_blacklist': {'*': ['black']},
'gather_method': {'^Server$': {'comps': 'deps', 'module': 'nodeps', 'json': 'deps'}},
})
pkg_set = mock.Mock()
gather.gather_packages(compose, 'x86_64', compose.variants['Server'], pkg_set),
self.assertEqual(get_gather_method.call_args_list,
[mock.call('nodeps'), mock.call('deps'), mock.call('deps')])
@mock.patch("pungi.phases.gather.get_variant_packages")
@mock.patch("pungi.phases.gather.get_gather_method")
def test_hybrid_method(self, get_gather_method, get_variant_packages):
packages, groups, filters = mock.Mock(), mock.Mock(), mock.Mock()
get_variant_packages.side_effect = (
lambda c, v, a, s, p: (packages, groups, filters)
if s == "comps"
else (None, None, None)
)
compose = helpers.DummyCompose(self.topdir, {"gather_method": "hybrid"})
variant = compose.variants["Server"]
pkg_set = mock.Mock()
gather.gather_packages(compose, "x86_64", variant, pkg_set),
self.assertEqual(
get_variant_packages.call_args_list,
[
mock.call(compose, "x86_64", variant, "comps", pkg_set)
],
)
self.assertEqual(get_gather_method.call_args_list, [mock.call("hybrid")])
method_kwargs = get_gather_method.return_value.return_value.call_args_list[0][1]
self.assertEqual(method_kwargs["packages"], packages)
self.assertEqual(method_kwargs["groups"], groups)
class TestWritePrepopulate(helpers.PungiTestCase):
def test_without_config(self):
compose = helpers.DummyCompose(self.topdir, {})
gather.write_prepopulate_file(compose)
self.assertFalse(os.path.isfile(os.path.join(self.topdir, 'work', 'global', 'prepopulate.json')))
def test_copy_by_filename(self):
compose = helpers.DummyCompose(self.topdir, {
'gather_prepopulate': 'input-prepopulate.json',
})
compose.config_dir = self.topdir
helpers.copy_fixture('prepopulate.json', os.path.join(self.topdir, 'input-prepopulate.json'))
gather.write_prepopulate_file(compose)
self.assertTrue(os.path.isfile(os.path.join(self.topdir, 'work', 'global', 'prepopulate.json')))
def test_copy_local_by_scm_dict(self):
compose = helpers.DummyCompose(self.topdir, {
'gather_prepopulate': {
'file': 'input-prepopulate.json',
'scm': 'file',
'repo': None,
}
})
compose.config_dir = self.topdir
helpers.copy_fixture('prepopulate.json', os.path.join(self.topdir, 'input-prepopulate.json'))
gather.write_prepopulate_file(compose)
self.assertTrue(os.path.isfile(os.path.join(self.topdir, 'work', 'global', 'prepopulate.json')))
class TestGetPrepopulate(helpers.PungiTestCase):
def setUp(self):
super(TestGetPrepopulate, self).setUp()
self.compose = helpers.DummyCompose(self.topdir, {})
def test_no_file(self):
self.assertEqual(
gather.get_prepopulate_packages(self.compose, 'x86_64', self.compose.variants['Server']),
set()
)
def test_for_one_variant(self):
helpers.copy_fixture('prepopulate.json',
os.path.join(self.topdir, 'work', 'global', 'prepopulate.json'))
six.assertCountEqual(
self,
gather.get_prepopulate_packages(self.compose, 'x86_64', self.compose.variants['Server']),
["foo-common.noarch",
"foo.i686",
"foo.x86_64"]
)
def test_for_all_variants(self):
helpers.copy_fixture('prepopulate.json',
os.path.join(self.topdir, 'work', 'global', 'prepopulate.json'))
six.assertCountEqual(
self,
gather.get_prepopulate_packages(self.compose, 'x86_64', None),
["foo-common.noarch",
"foo.i686",
"foo.x86_64",
"bar.x86_64"]
)
def test_for_all_variants_include_arch_set_to_false(self):
helpers.copy_fixture('prepopulate.json',
os.path.join(self.topdir, 'work', 'global', 'prepopulate.json'))
six.assertCountEqual(
self,
gather.get_prepopulate_packages(self.compose, 'x86_64', None,
include_arch=False),
["foo-common",
"foo",
"bar"]
)
class TestGatherPhase(helpers.PungiTestCase):
@mock.patch('pungi.phases.gather.link_files')
@mock.patch('pungi.phases.gather.gather_wrapper')
def test_run(self, gather_wrapper, link_files):
pkgset_phase = mock.Mock()
compose = helpers.DummyCompose(self.topdir, {})
compose.notifier = mock.Mock()
compose.all_variants['Client'].is_empty = True
pkg_map = gather_wrapper.return_value
def _mk_link_call(arch, variant):
return mock.call(compose, arch, compose.all_variants[variant],
pkg_map[arch][variant],
pkgset_phase.package_sets, manifest=phase.manifest)
phase = gather.GatherPhase(compose, pkgset_phase)
phase.run()
phase.stop()
self.assertEqual(gather_wrapper.call_args_list,
[mock.call(compose, pkgset_phase.package_sets, pkgset_phase.path_prefix)])
six.assertCountEqual(
self,
link_files.call_args_list,
[_mk_link_call('x86_64', 'Server'),
_mk_link_call('amd64', 'Server'),
_mk_link_call('amd64', 'Everything'),
_mk_link_call('x86_64', 'Everything')])
self.assertTrue(os.path.isfile(os.path.join(self.topdir, 'compose', 'metadata', 'rpms.json')))
@mock.patch('pungi.phases.gather.link_files')
@mock.patch('pungi.phases.gather.gather_wrapper')
def test_writes_manifest_when_skipped(self, gather_wrapper, link_files):
pkgset_phase = mock.Mock()
compose = helpers.DummyCompose(self.topdir, {})
compose.notifier = mock.Mock()
phase = gather.GatherPhase(compose, pkgset_phase)
phase.stop()
self.assertEqual(gather_wrapper.call_args_list, [])
self.assertTrue(os.path.isfile(os.path.join(self.topdir, 'compose', 'metadata', 'rpms.json')))
def test_validates_wrong_requiring_variant(self):
pkgset_phase = mock.Mock()
compose = helpers.DummyCompose(
self.topdir, {"variant_as_lookaside": [("foo", "Server")]}
)
phase = gather.GatherPhase(compose, pkgset_phase)
phase.validate()
def test_validates_wrong_required_variant(self):
pkgset_phase = mock.Mock()
compose = helpers.DummyCompose(
self.topdir, {"variant_as_lookaside": [("Server", "foo")]}
)
phase = gather.GatherPhase(compose, pkgset_phase)
with self.assertRaises(ValueError) as ctx:
phase.validate()
self.assertIn("'foo' doesn't exist", str(ctx.exception))
def test_validates_both_requires_missing(self):
pkgset_phase = mock.Mock()
compose = helpers.DummyCompose(
self.topdir, {"variant_as_lookaside": [("foo", "bar")]}
)
phase = gather.GatherPhase(compose, pkgset_phase)
phase.validate()
class TestGetPackagesToGather(helpers.PungiTestCase):
def setUp(self):
super(TestGetPackagesToGather, self).setUp()
self.compose = helpers.DummyCompose(self.topdir, {
'additional_packages': [
('.*', {'*': ['pkg', 'foo2.x86_64']}),
]
})
helpers.copy_fixture('prepopulate.json',
os.path.join(self.topdir, 'work', 'global', 'prepopulate.json'))
@mock.patch('pungi.phases.gather.get_gather_source')
def test_all_arches(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([('foo', None)]), set(['core'])))
)
packages, groups = gather.get_packages_to_gather(self.compose)
six.assertCountEqual(self, packages, ["foo", "foo2.x86_64", "pkg"])
self.assertEqual(groups, ["core"])
@mock.patch('pungi.phases.gather.get_gather_source')
def test_all_include_arch_set_to_false(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([('foo', None)]), set(['core'])))
)
packages, groups = gather.get_packages_to_gather(self.compose, include_arch=False)
six.assertCountEqual(self, packages, ["foo", "foo2", "pkg"])
self.assertEqual(groups, ["core"])
@mock.patch('pungi.phases.gather.get_gather_source')
def test_all_include_prepopulated(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([('foo', None)]), set(['core'])))
)
packages, groups = gather.get_packages_to_gather(self.compose, include_prepopulated=True)
six.assertCountEqual(
self,
packages,
["foo", "pkg", "foo-common.noarch", "foo.x86_64", "foo.i686", "foo2.x86_64",
"bar.x86_64"],
)
self.assertEqual(groups, ["core"])
@mock.patch('pungi.phases.gather.get_gather_source')
def test_all_include_prepopulated_no_include_arch(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([('foo', None)]), set(['core'])))
)
packages, groups = gather.get_packages_to_gather(self.compose, include_prepopulated=True,
include_arch=False)
six.assertCountEqual(
self, packages, ["foo", "pkg", "foo-common", "foo2", "bar"]
)
self.assertEqual(groups, ["core"])
@mock.patch('pungi.phases.gather.get_gather_source')
def test_all_one_arch(self, get_gather_source):
get_gather_source.return_value = mock.Mock(
return_value=mock.Mock(return_value=(set([('foo', None)]), set(['core'])))
)
packages, groups = gather.get_packages_to_gather(self.compose, "x86_64")
six.assertCountEqual(self, packages, ["foo", "pkg", "foo2.x86_64"])
self.assertEqual(groups, ["core"])
class TestUpdateConfig(unittest.TestCase):
def test_add_to_empty(self):
compose = mock.Mock(conf={})
gather._update_config(compose, 'Server', 'x86_64', '/tmp/foo')
self.assertEqual(compose.conf,
{'gather_lookaside_repos': [
('^Server$', {'x86_64': '/tmp/foo'})
]})
def test_add_to_existing(self):
compose = mock.Mock(conf={'gather_lookaside_repos': [
('^Server$', {'x86_64': '/tmp/bar'}),
]})
gather._update_config(compose, 'Server', 'x86_64', '/tmp/foo')
self.assertEqual(compose.conf,
{'gather_lookaside_repos': [
('^Server$', {'x86_64': '/tmp/bar'}),
('^Server$', {'x86_64': '/tmp/foo'})
]})
class TestUpdateLookasideConfig(helpers.PungiTestCase):
def setUp(self):
super(TestUpdateLookasideConfig, self).setUp()
self.compose = helpers.DummyCompose(self.topdir, {})
self.pkg_map = mock.Mock()
@mock.patch('pungi.phases.gather._update_config')
@mock.patch('pungi.phases.gather._make_lookaside_repo')
def test_no_config(self, mock_make_repo, mock_update_config):
gather._update_lookaside_config(self.compose, self.compose.variants['Server'],
'x86_64', self.pkg_map)
self.assertEqual(mock_make_repo.call_args_list, [])
self.assertEqual(mock_update_config.call_args_list, [])
@mock.patch('pungi.phases.gather._update_config')
@mock.patch('pungi.phases.gather._make_lookaside_repo')
def test_no_matching_config(self, mock_make_repo, mock_update_config):
self.compose.conf['variant_as_lookaside'] = [('Everything', 'Client')]
gather._update_lookaside_config(self.compose, self.compose.variants['Server'],
'x86_64', self.pkg_map)
self.assertEqual(mock_make_repo.call_args_list, [])
self.assertEqual(mock_update_config.call_args_list, [])
@mock.patch('pungi.phases.gather._update_config')
@mock.patch('pungi.phases.gather._make_lookaside_repo')
def test_missing_arch(self, mock_make_repo, mock_update_config):
# Client only has amd64
self.compose.conf['variant_as_lookaside'] = [('Server', 'Client')]
gather._update_lookaside_config(self.compose, self.compose.variants['Server'],
'x86_64', self.pkg_map)
self.assertEqual(len(self.compose.log_warning.call_args_list), 1)
self.assertEqual(mock_make_repo.call_args_list, [])
self.assertEqual(mock_update_config.call_args_list, [])
@mock.patch('pungi.phases.gather._update_config')
@mock.patch('pungi.phases.gather._make_lookaside_repo')
def test_match(self, mock_make_repo, mock_update_config):
self.compose.conf['variant_as_lookaside'] = [('Server', 'Everything')]
gather._update_lookaside_config(self.compose, self.compose.variants['Server'],
'x86_64', self.pkg_map)
self.assertEqual(len(self.compose.log_warning.call_args_list), 0)
self.assertEqual(mock_make_repo.call_args_list,
[mock.call(self.compose,
self.compose.variants['Everything'],
'x86_64',
self.pkg_map, None)])
self.assertEqual(mock_update_config.call_args_list,
[mock.call(self.compose, 'Server', 'x86_64',
mock_make_repo.return_value)])
class TestMakeLookasideRepo(helpers.PungiTestCase):
def setUp(self):
super(TestMakeLookasideRepo, self).setUp()
self.compose = helpers.DummyCompose(self.topdir, {})
self.variant = self.compose.variants['Server']
self.arch = 'x86_64'
self.repodir = self.compose.paths.work.lookaside_repo(self.arch, self.variant, create_dir=False)
self.pkglist = self.compose.paths.work.lookaside_package_list(self.arch, self.variant)
self.package_sets = self._make_pkgset_phase(["p1", "p2"]).package_sets
@mock.patch('pungi.phases.gather.run')
def test_existing_repo(self, mock_run):
helpers.touch(os.path.join(self.repodir, 'repodata', 'primary.xml'))
repopath = gather._make_lookaside_repo(self.compose, self.variant, self.arch, {})
self.assertEqual(self.repodir, repopath)
self.assertFalse(os.path.exists(self.pkglist))
self.assertEqual(mock_run.call_args_list, [])
def assertCorrect(self, repopath, path_prefix, MockCR, mock_run):
with open(self.pkglist) as f:
packages = f.read().splitlines()
six.assertCountEqual(
self,
packages,
[
"pkg/pkg-1.0-1.x86_64.rpm",
"pkg/pkg-debuginfo-1.0-1.x86_64.rpm",
"pkg/pkg-1.0-1.src.rpm",
],
)
self.assertEqual(self.repodir, repopath)
self.assertEqual(MockCR.return_value.get_createrepo_cmd.call_args_list,
[mock.call(path_prefix, update=True, database=True, skip_stat=True,
pkglist=self.pkglist, outputdir=repopath,
baseurl="file://%s" % path_prefix, workers=3,
update_md_path=self.compose.paths.work.pkgset_repo("p2", self.arch))])
self.assertEqual(mock_run.call_args_list,
[mock.call(MockCR.return_value.get_createrepo_cmd.return_value,
logfile=os.path.join(
self.topdir, 'logs', self.arch,
'lookaside_repo_Server.%s.log' % self.arch),
show_cmd=True)])
@mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper')
@mock.patch('pungi.phases.gather.CreaterepoWrapper')
@mock.patch('pungi.phases.gather.run')
def test_create_repo_koji_pkgset(self, mock_run, MockCR, MockKW):
self.compose.conf.update({
'pkgset_source': 'koji',
'koji_profile': 'koji',
})
pkg_map = {
self.arch: {
self.variant.uid: {
'rpm': [{'path': '/tmp/packages/pkg/pkg-1.0-1.x86_64.rpm'}],
'debuginfo': [{'path': '/tmp/packages/pkg/pkg-debuginfo-1.0-1.x86_64.rpm'}],
'srpm': [{'path': '/tmp/packages/pkg/pkg-1.0-1.src.rpm'}],
}
}
}
MockKW.return_value.koji_module.config.topdir = '/tmp/packages'
repopath = gather._make_lookaside_repo(
self.compose, self.variant, self.arch, pkg_map, self.package_sets
)
self.assertCorrect(repopath, '/tmp/packages/', MockCR, mock_run)
@mock.patch('pungi.phases.gather.CreaterepoWrapper')
@mock.patch('pungi.phases.gather.run')
def test_create_repo_repos_pkgset(self, mock_run, MockCR):
self.compose.conf.update({
'pkgset_source': 'repos',
})
dl_dir = self.compose.paths.work.topdir('global')
pkg_map = {
self.arch: {
self.variant.uid: {
'rpm': [
{'path': os.path.join(dl_dir, 'download/pkg/pkg-1.0-1.x86_64.rpm')}
],
'debuginfo': [
{'path': os.path.join(dl_dir, 'download/pkg/pkg-debuginfo-1.0-1.x86_64.rpm')}
],
'srpm': [
{'path': os.path.join(dl_dir, 'download/pkg/pkg-1.0-1.src.rpm')}
],
}
}
}
repopath = gather._make_lookaside_repo(
self.compose, self.variant, self.arch, pkg_map, self.package_sets
)
self.assertCorrect(repopath, dl_dir + '/download/', MockCR, mock_run)