From 4a44d537b898be0f02c336df322cd8b16b8a6223 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Mar 17 2021 19:33:57 +0000 Subject: Merge #1688 `Integration tests: add v3-packager coverage` --- diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 9ee8b7e..fdcfa49 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -96,10 +96,23 @@ def clone_and_start_build(repo, pkg_util): :rtype utils.Repo, list: """ repo.bump() - builds = pkg_util.run("--optional", "rebuild_strategy=all") - yield repo, builds - for build in builds: - pkg_util.cancel(build, ignore_errors=True) + _builds = [] + _cancel = True + + def _build(*args, cancel=True, **kwargs): + nonlocal _builds, _cancel + options = [str(i) for i in args] + builds = pkg_util.run(*options, **kwargs) + if not builds: + raise AssertionError(f"Packaging utility args={options} did not produce any builds") + _builds, _cancel = (builds, cancel) + return repo, builds + + yield _build + + if _cancel: + for build in _builds: + pkg_util.cancel(build, ignore_errors=True) @pytest.fixture(scope="function") diff --git a/tests/integration/example.test.env.yaml b/tests/integration/example.test.env.yaml index 1ea2549..ab9e26d 100644 --- a/tests/integration/example.test.env.yaml +++ b/tests/integration/example.test.env.yaml @@ -139,3 +139,15 @@ testdata: rest_submit_module_build: module: testmodule branch: test-submit-module + v3_normal_build: + module: testmodule + branch: test-v3-normal-build + v3_multiple_contexts: + module: testmodule + branch: test-v3-multiple-contexts + v3_no_components: + module: testmodule + branch: test-v3-no-components + v3_buildrequire: + module: testmodule + branch: test-v3-buildrequire diff --git a/tests/integration/test_buildonly.py b/tests/integration/test_buildonly.py index 2bf0ffa..49b54ec 100644 --- a/tests/integration/test_buildonly.py +++ b/tests/integration/test_buildonly.py @@ -9,7 +9,7 @@ def test_buildonly(clone_and_start_build, mbs): * Assert that the expected filter field was created in the module metadata. """ - repo, builds = clone_and_start_build + repo, builds = clone_and_start_build("--optional", "rebuild_strategy=all") # Check the original modulemd modulemd = repo.modulemd diff --git a/tests/integration/test_rest_build_state.py b/tests/integration/test_rest_build_state.py index 3301d96..a0dc44f 100644 --- a/tests/integration/test_rest_build_state.py +++ b/tests/integration/test_rest_build_state.py @@ -8,7 +8,7 @@ def test_rest_module_build(clone_and_start_build, mbs, koji, pkg_util): * There is no need for exhaustive testing of the REST API here, as extensive coverage of it is already implemented in tests/test_web/test_views.py. """ - repo, builds = clone_and_start_build + repo, builds = clone_and_start_build("--optional", "rebuild_strategy=all") assert len(builds) >= 1 username = getpass.getuser() diff --git a/tests/integration/test_static_context.py b/tests/integration/test_static_context.py index ff74c23..5f9cd47 100644 --- a/tests/integration/test_static_context.py +++ b/tests/integration/test_static_context.py @@ -1,6 +1,6 @@ def test_static_context(clone_and_start_build, mbs): - repo, builds = clone_and_start_build + repo, builds = clone_and_start_build("--optional", "rebuild_strategy=all") static_contexts = repo.modulemd["data"]["xmd"]["mbs_options"]["contexts"] diff --git a/tests/integration/test_v3_buildrequire.py b/tests/integration/test_v3_buildrequire.py new file mode 100644 index 0000000..0f398ce --- /dev/null +++ b/tests/integration/test_v3_buildrequire.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: MIT + + +def test_v3_buildrequire(mbs, clone_and_start_build): + """Test buildrequire fields in the v3-packager mmd. + + Preconditions: + * 2 contexts defined in mmd, one of which 'build-requires' another module + (as well as a koji-resolver enabled platform). + * Build-required module is tagged in koji with koji_tag_with_modules from said platform. + + Steps: + * Submit a build. + * Wait until the build(s) are in build state. + * Cancel the build(s). + + Checks: + * That that number of builds produced is equal to the number of configurations. + * That each build has expected buildrequires items. + """ + + repo, builds = clone_and_start_build() + contexts = { + cfg["context"]: cfg for cfg in repo.modulemd["data"]["configurations"] + } + + assert len(builds) == len(contexts) + + for build in builds: + mbs.wait_for_module_build(build, lambda bld: bld.get("state") >= 2) + ctx = build.module_build_data["context"] + + assert ctx in contexts + for buildrequire, data in build.module_build_data["buildrequires"].items(): + if buildrequire == "platform": + mmd_platform = contexts[ctx]["platform"] + assert data["stream"] == mmd_platform \ + if mmd_platform.endswith(".z") else f"{mmd_platform}.z" + continue + assert buildrequire in contexts[ctx]["buildrequires"] + assert data["stream"] == contexts[ctx]["buildrequires"][buildrequire][0] + + diff --git a/tests/integration/test_v3_multiple_contexts.py b/tests/integration/test_v3_multiple_contexts.py new file mode 100644 index 0000000..d7b78b4 --- /dev/null +++ b/tests/integration/test_v3_multiple_contexts.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: MIT + + +def test_v3_multiple_contexts(clone_and_start_build): + """Test that multiple configurations in v3-packager modulemd produce multiple module builds""" + repo, builds = clone_and_start_build("--optional", "rebuild_strategy=all") + assert len(builds) == len(repo.modulemd["data"]["configurations"]) diff --git a/tests/integration/test_v3_no_components.py b/tests/integration/test_v3_no_components.py new file mode 100644 index 0000000..99a5284 --- /dev/null +++ b/tests/integration/test_v3_no_components.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: MIT + + +def test_v3_no_components(mbs, clone_and_start_build): + """Test a minimal mmd - with no RPM components""" + _, builds = clone_and_start_build(cancel=False) + assert len(builds) == 1 + build = builds[0] + + mbs.wait_for_module_build_to_succeed(build) + assert not build.data["component_builds"] diff --git a/tests/integration/test_v3_normal_build.py b/tests/integration/test_v3_normal_build.py new file mode 100644 index 0000000..3bc9d3e --- /dev/null +++ b/tests/integration/test_v3_normal_build.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: MIT + + +def test_v3_normal_build(mbs, koji, clone_and_start_build): + """Test a normal module-build submitted with v3-packager YAML modulemd.""" + + repo, builds = clone_and_start_build("--optional", "rebuild_strategy=all", cancel=False) + build = builds[0] + + # actual input (v3 packager mmd) + assert len(repo.modulemd["data"]["configurations"]) == 1 + mmd_configuration = repo.modulemd["data"]["configurations"][0] + mmd_context = mmd_configuration["context"] + mmd_platform = mmd_configuration["platform"] + + mbs.wait_for_module_build_to_succeed(build) + + # assert module build components + assert sorted(build.component_names()) == sorted(repo.components + ["module-build-macros"]) + for component_rpm in build.components(): + assert koji.get_task(component_rpm["task_id"])["state"] == 2 # is closed + + # assert produced koji build + koji_build = koji.get_build(build.nvr()) + koji_build_devel = koji.get_build(build.nvr(name_suffix="-devel")) + assert koji_build and koji_build_devel + module_data = koji_build['extra']['typeinfo']['module'] + assert module_data['module_build_service_id'] == int(build.id) + assert module_data['context'] == mmd_context + koji_mmd = koji.get_modulemd(koji_build) + actual_platforms = koji_mmd["data"]["dependencies"][0]["buildrequires"]["platform"] + assert len(actual_platforms) == 1 + assert actual_platforms[0] == f"{mmd_platform}.z" diff --git a/tests/integration/utils.py b/tests/integration/utils.py index 3a1fe4c..6d3bbcd 100644 --- a/tests/integration/utils.py +++ b/tests/integration/utils.py @@ -79,6 +79,15 @@ class Koji: self._session = koji.ClientSession(self._server) self._pathinfo = koji.PathInfo(self._topurl) + def get_task(self, task_id): + """Koji task data for task id + + :param int task_id: task id + :return: Dictionary with Koji task data or None, if task is not found + :rtype: dict or None + """ + return self._session.getTaskInfo(task_id) + def get_build(self, nvr_dict): """Koji build data for NVR