""" Test the methods that generate buildroot_lock.json """ import copy import json import os import tempfile from unittest import TestCase from unittest.mock import MagicMock, patch import jsonschema from mockbuild.plugins.buildroot_lock import init import mockbuild.exception # gpg-pubkey packages stay ignored # fedora-release is normal package with simple license RPM_OUTPUT = """\ gpg-pubkey|/@(none)|/@pubkey|/@105ef944|/@65ca83d1|/@(none)|/@(none)|/@(none) gpg-pubkey|/@(none)|/@pubkey|/@e99d6ad1|/@64d2612c|/@(none)|/@(none)|/@(none) fedora-release|/@noarch|/@MIT|/@42|/@0.3|/@(none)|/@cf31d87e5e3eac97ff32a98e7e073f37|/@(none) bash|/@x86_64|/@GPLv3+|/@5.1.8|/@9.el9|/@(none)|/@57e93b1739cc3512f9f29dcaa8a38055|/@RSA/SHA256, Sun Mar 31 12:41:20 2024, Key ID 199e2f91fd431d51 """ # noqa: E501 # cyrus-sasl-lib is not present in the REPOQUERY_OUTPUT RPM_ONLY_RPM = """\ cyrus-sasl-lib|/@x86_64|/@BSD with advertising|/@2.1.27|/@21.el9|/@(none)|/@9e1caba09fac94568419b9dfd14fb4c5|/@RSA/SHA256, Mon Sep 12 23:24:22 2022, Key ID 199e2f91fd431d51 """ # noqa: E501 REPOQUERY_OUTPUT = """\ http://ftp.fi.muni.cz/pub/linux/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/f/fedora-release-42-0.3.noarch.rpm https://cdn.redhat.com/content/dist/rhel9/9/x86_64/baseos/os/Packages/b/bash-5.1.8-9.el9.x86_64.rpm """ EXPECTED_OUTPUT = { 'version': '1.1.0', 'buildroot': { 'rpms': [{ 'arch': 'x86_64', 'epoch': None, 'license': 'GPLv3+', 'name': 'bash', 'release': '9.el9', 'sigmd5': '57e93b1739cc3512f9f29dcaa8a38055', 'signature': 'fd431d51', 'url': 'https://cdn.redhat.com/content/dist/rhel9/9/x86_64' '/baseos/os/Packages/b/bash-5.1.8-9.el9.x86_64.rpm', 'version': '5.1.8' }, { 'arch': 'noarch', 'epoch': None, 'license': 'MIT', 'name': 'fedora-release', 'release': '0.3', 'sigmd5': 'cf31d87e5e3eac97ff32a98e7e073f37', 'signature': None, 'url': 'http://ftp.fi.muni.cz/pub/linux/fedora/linux' '/development/rawhide/Everything/x86_64/os' '/Packages/f/fedora-release-42-0.3.noarch.rpm', 'version': '42', }] }, "bootstrap": { "image_digest": "sha256:ba1067bef190fbe88f085bd019464a8c0803b7cd1e3f", "pull_digest": "sha256:1d9f0eaec60b59a669b285d1e775d970061b9694d4998b5bdb9626c9f33685cd", "id": "b222730c2ba32385173fe3351026c316c9a294fa8d8c3c0f80d8afdb1b1aeef7", "architecture": "amd64", }, 'config': { 'bootstrap_image': 'foo', 'bootstrap_image_ready': True, "legal_host_arches": ["x86_64"], "target_arch": "x86_64", "dist": ".f42", }, } def _exp_output_bootstrap(exp_data): data = copy.deepcopy(exp_data["bootstrap"]) del data["image_digest"] return data def _mock_vars(rpm_out, repoquery_out): tc = TestCase() tc.maxDiff = None buildroot = MagicMock() buildroot.state = MagicMock() buildroot.uid_manager = MagicMock() buildroot.doOutChroot = MagicMock( side_effect=iter([ (rpm_out, None), (repoquery_out, None), ]) ) buildroot.config = EXPECTED_OUTPUT['config'] buildroot.resultdir = tempfile.mkdtemp(prefix="mock-test-buildroot-lock") plugins = MagicMock() plugins.add_hook = MagicMock() return tc, buildroot, plugins def _call_method(plugins, buildroot): # initialize the plugin init(plugins, {}, buildroot) # obtain the hook method, and call it plugins.add_hook.assert_called_once() _, method = plugins.add_hook.call_args[0] podman_obj = MagicMock() podman_obj.get_oci_digest.return_value = EXPECTED_OUTPUT["bootstrap"]["image_digest"] podman_obj.inspect_hermetic_metadata.return_value = _exp_output_bootstrap(EXPECTED_OUTPUT) podman_cls = MagicMock(return_value=podman_obj) with patch("mockbuild.plugins.buildroot_lock.Podman", side_effect=podman_cls): method() def test_nonexisting_file_in_repo(): """ Test the situation when RPM is installed, and no longer available in repository. """ _, buildroot, plugins = _mock_vars( RPM_OUTPUT + RPM_ONLY_RPM, REPOQUERY_OUTPUT, ) raised = False try: _call_method(plugins, buildroot) except mockbuild.exception.Error as e: assert e.msg == "Can't get location for cyrus-sasl-lib-2.1.27-21.el9.x86_64" raised = True assert raised def _get_json_schema(): testdir = os.path.dirname(__file__) basename = "buildroot-lock-schema-" + EXPECTED_OUTPUT["version"] + ".json" with open(os.path.join(testdir, "..", "docs", basename), "r", encoding="utf-8") as fd: return json.load(fd) def test_buildroot_lock_output(): """ test the buildroot_lock.json file format """ tc, buildroot, plugins = _mock_vars(RPM_OUTPUT, REPOQUERY_OUTPUT) _call_method(plugins, buildroot) with open(os.path.join(buildroot.resultdir, "buildroot_lock.json"), "r", encoding="utf-8") as fd: data = json.load(fd) tc.assertDictEqual(data, EXPECTED_OUTPUT) schema = _get_json_schema() jsonschema.validate(EXPECTED_OUTPUT, schema) def test_json_schema_metadata(): """ Test basic format of the json schema """ schema = _get_json_schema() version = EXPECTED_OUTPUT["version"] assert "Version " + version + ";" in schema["description"] assert "schema-" + version + ".json" in schema["$id"]