# -*- coding: utf-8 -*- try: import unittest2 as unittest except ImportError: import unittest import six import mock from pungi import checks from tests.helpers import load_config, PKGSET_REPOS class ConfigTestCase(unittest.TestCase): def assertValidation(self, cfg, errors=[], warnings=[]): actual_errors, actual_warnings = checks.validate(cfg) six.assertCountEqual(self, errors, actual_errors) self.assertEqual(warnings, actual_warnings) class PkgsetConfigTestCase(ConfigTestCase): def test_validate_minimal_pkgset_koji(self): cfg = load_config( pkgset_source="koji", ) self.assertValidation(cfg) def test_validate_minimal_pkgset_repos(self): cfg = load_config( pkgset_source="repos", pkgset_repos={"x86_64": "/first", "ppc64": "/second"}, ) self.assertValidation(cfg) def test_pkgset_mismatch_repos(self): cfg = load_config( pkgset_source="repos", pkgset_koji_tag="f25", pkgset_koji_inherit=False, ) self.assertValidation( cfg, [ checks.REQUIRES.format("pkgset_source", "repos", "pkgset_repos"), checks.CONFLICTS.format("pkgset_source", "repos", "pkgset_koji_tag"), checks.CONFLICTS.format( "pkgset_source", "repos", "pkgset_koji_inherit" ), ], ) def test_pkgset_mismatch_koji(self): cfg = load_config( pkgset_source="koji", pkgset_repos={"whatever": "/foo"}, ) self.assertValidation( cfg, [checks.CONFLICTS.format("pkgset_source", "koji", "pkgset_repos")] ) def test_pkgset_multiple_koji_tags(self): cfg = load_config( pkgset_source="koji", pkgset_koji_tag=["f25", "f25-extra"], pkgset_koji_inherit=False, ) self.assertValidation(cfg) class ReleaseConfigTestCase(ConfigTestCase): def test_set_release_is_layered(self): cfg = load_config(PKGSET_REPOS, release_is_layered=True) self.assertValidation( cfg, warnings=[ "WARNING: Config option release_is_layered was removed and has no effect; remove it. It's layered if there's configuration for base product." # noqa: E501 ], ) def test_only_config_base_product_name(self): cfg = load_config( PKGSET_REPOS, base_product_name="Prod", ) self.assertValidation( cfg, [ checks.REQUIRES.format( "base_product_name", "Prod", "base_product_short" ), checks.REQUIRES.format( "base_product_name", "Prod", "base_product_version" ), checks.CONFLICTS.format( "base_product_short", None, "base_product_name" ), checks.CONFLICTS.format( "base_product_version", None, "base_product_name" ), ], ) def test_only_config_base_product_short(self): cfg = load_config( PKGSET_REPOS, base_product_short="bp", ) self.assertValidation( cfg, [ checks.REQUIRES.format("base_product_short", "bp", "base_product_name"), checks.REQUIRES.format( "base_product_short", "bp", "base_product_version" ), checks.CONFLICTS.format( "base_product_name", None, "base_product_short" ), checks.CONFLICTS.format( "base_product_version", None, "base_product_short" ), ], ) def test_only_config_base_product_version(self): cfg = load_config( PKGSET_REPOS, base_product_version="1.0", ) self.assertValidation( cfg, [ checks.REQUIRES.format( "base_product_version", "1.0", "base_product_name" ), checks.REQUIRES.format( "base_product_version", "1.0", "base_product_short" ), checks.CONFLICTS.format( "base_product_name", None, "base_product_version" ), checks.CONFLICTS.format( "base_product_short", None, "base_product_version" ), ], ) class ImageNameConfigTestCase(ConfigTestCase): def test_image_name_simple_string(self): cfg = load_config( PKGSET_REPOS, image_name_format="foobar", ) self.assertValidation(cfg, []) def test_image_name_variant_mapping(self): cfg = load_config( PKGSET_REPOS, image_name_format={"^Server$": "foobar"}, ) self.assertValidation(cfg, []) class RunrootConfigTestCase(ConfigTestCase): def test_set_runroot_true(self): cfg = load_config( PKGSET_REPOS, runroot=True, ) self.assertValidation( cfg, warnings=[ "WARNING: Config option runroot was removed and has no effect; remove it. Please specify 'runroot_method' if you want to enable runroot, otherwise run things locally." # noqa: E501 ], ) def test_set_runroot_false(self): cfg = load_config( PKGSET_REPOS, runroot=False, ) self.assertValidation( cfg, warnings=[ "WARNING: Config option runroot was removed and has no effect; remove it. Please specify 'runroot_method' if you want to enable runroot, otherwise run things locally." # noqa: E501 ], ) class BuildinstallConfigTestCase(ConfigTestCase): def test_bootable_deprecated(self): cfg = load_config( PKGSET_REPOS, bootable=True, ) self.assertValidation( cfg, warnings=[ "WARNING: Config option bootable was removed and has no effect; remove it. Setting buildinstall_method option if you want a bootable installer." # noqa: E501 ], ) def test_buildinstall_method_without_bootable(self): cfg = load_config( PKGSET_REPOS, buildinstall_method="lorax", ) self.assertValidation(cfg, []) def test_buildinstall_with_lorax_options(self): cfg = load_config( PKGSET_REPOS, buildinstall_method="buildinstall", lorax_options=[("^Server$", {})], ) self.assertValidation( cfg, [ checks.CONFLICTS.format( "buildinstall_method", "buildinstall", "lorax_options" ) ], ) def test_lorax_with_lorax_options(self): cfg = load_config(PKGSET_REPOS, buildinstall_method="lorax", lorax_options=[]) self.assertValidation(cfg) def test_lorax_options_without_bootable_and_method(self): cfg = load_config( PKGSET_REPOS, lorax_options=[("^Server$", {})], buildinstall_kickstart="foo", ) self.assertValidation( cfg, [ checks.CONFLICTS.format("buildinstall_method", "None", "lorax_options"), checks.CONFLICTS.format( "buildinstall_method", "None", "buildinstall_kickstart" ), ], ) class CreaterepoConfigTestCase(ConfigTestCase): def test_validate_minimal_pkgset_koji(self): cfg = load_config( pkgset_source="koji", pkgset_koji_tag="f25", product_id_allow_missing=True, ) self.assertValidation( cfg, [checks.CONFLICTS.format("product_id", "None", "product_id_allow_missing")], ) class GatherConfigTestCase(ConfigTestCase): def test_dnf_backend_is_default_on_py3(self): cfg = load_config( pkgset_source="koji", pkgset_koji_tag="f27", ) with mock.patch("six.PY2", new=False): self.assertValidation(cfg, []) self.assertEqual(cfg["gather_backend"], "dnf") def test_yum_backend_is_default_on_py2(self): cfg = load_config( pkgset_source="koji", pkgset_koji_tag="f27", ) with mock.patch("six.PY2", new=True): self.assertValidation(cfg, []) self.assertEqual(cfg["gather_backend"], "yum") def test_yum_backend_is_rejected_on_py3(self): cfg = load_config( pkgset_source="koji", pkgset_koji_tag="f27", gather_backend="yum", ) with mock.patch("six.PY2", new=False): self.assertValidation( cfg, ["Failed validation in gather_backend: 'yum' is not one of ['dnf']"], ) class OSBSConfigTestCase(ConfigTestCase): def test_validate(self): cfg = load_config( PKGSET_REPOS, osbs={ "^Server$": { "url": "http://example.com", "target": "f25-build", "git_branch": "f25", } }, ) self.assertValidation(cfg) def test_validate_bad_conf(self): cfg = load_config(PKGSET_REPOS, osbs="yes please") self.assertNotEqual(checks.validate(cfg), ([], [])) class OstreeConfigTestCase(ConfigTestCase): def test_validate(self): cfg = load_config( PKGSET_REPOS, ostree=[ ( "^Atomic$", { "x86_64": { "treefile": "fedora-atomic-docker-host.json", "config_url": "https://git.fedorahosted.org/git/fedora-atomic.git", # noqa: E501 "repo": "Everything", "ostree_repo": "/mnt/koji/compose/atomic/Rawhide/", "version": "!OSTREE_VERSION_FROM_LABEL_DATE_TYPE_RESPIN", } }, ) ], ) self.assertValidation(cfg) def test_validate_bad_conf(self): cfg = load_config(PKGSET_REPOS, ostree="yes please") self.assertNotEqual(checks.validate(cfg), ([], [])) class OstreeInstallerConfigTestCase(ConfigTestCase): def test_validate(self): cfg = load_config( PKGSET_REPOS, ostree_installer=[ ( "^Atomic$", { "x86_64": { "repo": "Everything", "release": None, "installpkgs": ["fedora-productimg-atomic"], "add_template": [ "/spin-kickstarts/atomic-installer/lorax-configure-repo.tmpl" # noqa: E501 ], "add_template_var": [ "ostree_osname=fedora-atomic", "ostree_ref=fedora-atomic/Rawhide/x86_64/docker-host", ], "add_arch_template": [ "/spin-kickstarts/atomic-installer/lorax-embed-repo.tmpl" # noqa: E501 ], "rootfs_size": "3", "add_arch_template_var": [ "ostree_repo=https://kojipkgs.fedoraproject.org/compose/atomic/Rawhide/", # noqa: E501 "ostree_osname=fedora-atomic", "ostree_ref=fedora-atomic/Rawhide/x86_64/docker-host", ], } }, ) ], ) self.assertValidation(cfg) def test_validate_bad_conf(self): cfg = load_config( PKGSET_REPOS, ostree_installer=[ ( "^Atomic$", { "x86_64": { "repo": "Everything", "release": None, "installpkgs": ["fedora-productimg-atomic"], "add_template": [ "/spin-kickstarts/atomic-installer/lorax-configure-repo.tmpl" # noqa: E501 ], "add_template_var": [ "ostree_osname=fedora-atomic", "ostree_ref=fedora-atomic/Rawhide/x86_64/docker-host", ], "add_arch_template": 15, "add_arch_template_var": [ "ostree_repo=https://kojipkgs.fedoraproject.org/compose/atomic/Rawhide/", # noqa: E501 "ostree_osname=fedora-atomic", "ostree_ref=fedora-atomic/Rawhide/x86_64/docker-host", ], } }, ) ], ) self.assertNotEqual(checks.validate(cfg), ([], [])) class LiveMediaConfigTestCase(ConfigTestCase): @mock.patch("pungi.util.resolve_git_url") def test_global_config_validation(self, resolve_git_url): cfg = load_config( PKGSET_REPOS, live_media_ksurl="git://example.com/repo.git#HEAD", live_media_target="f24", live_media_release="RRR", live_media_version="Rawhide", ) resolve_git_url.side_effect = lambda x: x.replace("HEAD", "CAFE") self.assertValidation(cfg) self.assertEqual(cfg["live_media_ksurl"], "git://example.com/repo.git#CAFE") def test_global_config_null_release(self): cfg = load_config( PKGSET_REPOS, live_media_release=None, ) self.assertValidation(cfg) class TestSuggestions(ConfigTestCase): def test_with_a_typo(self): cfg = load_config(PKGSET_REPOS, product_pid=None) self.assertValidation( cfg, [], [checks.UNKNOWN_SUGGEST.format("product_pid", "product_id")] ) class TestRegexValidation(ConfigTestCase): def test_incorrect_regular_expression(self): cfg = load_config(PKGSET_REPOS, multilib=[("^*$", {"*": []})]) msg = "Failed validation in multilib.0.0: incorrect regular expression: nothing to repeat" # noqa: E501 if six.PY3: msg += " at position 1" self.assertValidation(cfg, [msg], []) class RepoclosureTestCase(ConfigTestCase): def test_invalid_backend(self): cfg = load_config( PKGSET_REPOS, repoclosure_backend="fnd", # Intentionally with a typo ) options = ["yum", "dnf"] if six.PY2 else ["dnf"] self.assertValidation( cfg, [ "Failed validation in repoclosure_backend: 'fnd' is not one of %s" % options ], ) class VariantAsLookasideTestCase(ConfigTestCase): def test_empty(self): variant_as_lookaside = [] cfg = load_config( PKGSET_REPOS, variant_as_lookaside=variant_as_lookaside, ) self.assertValidation(cfg) def test_basic(self): variant_as_lookaside = [ ("Client", "Base"), ("Server", "Client"), ("Everything", "Spin"), ] cfg = load_config( PKGSET_REPOS, variant_as_lookaside=variant_as_lookaside, ) self.assertValidation(cfg) class SkipPhasesTestCase(ConfigTestCase): def test_empty(self): skip_phases = [] cfg = load_config( PKGSET_REPOS, skip_phases=skip_phases, ) self.assertValidation(cfg) def test_basic(self): skip_phases = [ "buildinstall", "gather", ] cfg = load_config( PKGSET_REPOS, skip_phases=skip_phases, ) self.assertValidation(cfg) def test_bad_phase_name(self): skip_phases = [ "gather", "non-existing-phase_name", ] cfg = load_config( PKGSET_REPOS, skip_phases=skip_phases, ) self.assertNotEqual(checks.validate(cfg), ([], []))