From b9dee9d4544f4c9a787bb79a364ce6f2b17d43cf Mon Sep 17 00:00:00 2001 From: jobrauer Date: Mon, 2 Mar 2020 16:54:43 +0100 Subject: [PATCH] Add test_reuse_tagged_module --- tests/integration/example.test.env.yaml | 5 ++ tests/integration/test_reuse_tagged_module.py | 60 +++++++++++++++++++ tests/integration/utils.py | 49 +++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 tests/integration/test_reuse_tagged_module.py diff --git a/tests/integration/example.test.env.yaml b/tests/integration/example.test.env.yaml index 16636cb3..b994a9e6 100644 --- a/tests/integration/example.test.env.yaml +++ b/tests/integration/example.test.env.yaml @@ -91,3 +91,8 @@ testdata: buildrequire_invalid_module: module: testmodule branch: test-buildrequire-invalid-module + reuse_tagged_module: + # This scenario expects testmodule to have at least one build tagged in brew + # with koji_tag_with_modules from testmodule's platform (stream 8.1.0.z) + module: testmodule + branch: test-reuse-tagged-module diff --git a/tests/integration/test_reuse_tagged_module.py b/tests/integration/test_reuse_tagged_module.py new file mode 100644 index 00000000..5f8a11bc --- /dev/null +++ b/tests/integration/test_reuse_tagged_module.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: MIT + + +def test_reuse_tagged_module(pkg_util, scenario, repo, koji, mbs): + """ + Check that for newer builds, Koji resolver picks the appropriately tagged + module build to be reused. + + Preconditions: + 1) Selected module under test has historically at least one tagged build in Koji. + This Koji build is tagged with the preconfigured 'koji_tag_with_modules' tag. + 2) At least one build afterwards with build strategy 'all' + + Steps: + 1) Build module. + 2) Query MBS for its 'reused' module & get the NVR. + 3) Query MBS for its buildrequire platform & get the 'koji_tag_with_modules'. + 4) Query Koji for the 'reused' build (NVR). + 5) Query Koji for all builds tagged with the 'koji_tag_with_modules'. + + Checks: + Assert that the 'reused' build is in the tagged collection. + """ + + repo.bump() + + # Build the build-under-test (should reuse all previous components) + builds = pkg_util.run("--watch") + assert len(builds) == 1 + new_build = builds[0] + + # Get the reused module as NVR + reused_build_id = new_build.module_build_data['reused_module_id'] + assert reused_build_id + reused_build = mbs.get_module_build(reused_build_id) + assert len(reused_build.nvr()) == 3 + + # Find configured 'koji_tag_with_modules' tag in the base module's metadata + platform_stream = new_build.module_build_data['buildrequires']['platform'].get('stream') + assert platform_stream + + platform_builds = mbs.get_module_builds(name='platform', stream=platform_stream, verbose=True) + platform_builds = [b for b in platform_builds if b.module_build_data['state'] == 5] # 'ready' + assert len(platform_builds) == 1, f"Platform {platform_stream}: no build in state ready." + + metadata = platform_builds[0].get_metadata() + koji_tag_with_modules = metadata['data']['xmd']['mbs'].get('koji_tag_with_modules') + assert koji_tag_with_modules, \ + f"Platform {platform_stream}: missing 'koji_tag_with_modules', Koji resolver disabled." + + # Get the reused build as Koji build + reused_koji_id = koji.get_build(reused_build.nvr())['id'] + + # Get all Koji builds tagged with our 'koji_tag_with_modules' + tagged_builds = koji._session.listTagged(koji_tag_with_modules) + assert tagged_builds, f"No builds tagged with: '{koji_tag_with_modules}'!" + + assert reused_koji_id in [b['id'] for b in tagged_builds],\ + f"Koji build '{reused_build.nvr()}' is not tagged with '{koji_tag_with_modules}'!" diff --git a/tests/integration/utils.py b/tests/integration/utils.py index 62dcbc00..1d61e070 100644 --- a/tests/integration/utils.py +++ b/tests/integration/utils.py @@ -75,6 +75,15 @@ class Koji: r.raise_for_status() return r.text + def get_tag(self, tag_info): + """Get tag detail + + :param str tag_info: either tag name or tag integer id + :return Tag detail + :rtype dict + """ + return self._session.getTag(tag_info) + def get_macro_specfile(self, build): """ Download macro src.rpm and extract spec file . @@ -391,6 +400,18 @@ class Build: return True return False + def get_metadata(self) -> dict: + """ + Get module's metadata (from MBS API) + + :return: module's metadata + :rtype: dict + """ + try: + return yaml.safe_load(self.module_build_data['modulemd']) + except (AttributeError, KeyError): + return {} + class Component: """Wrapper class to work with git repositories of components @@ -461,3 +482,31 @@ class MBS: r = requests.get(url, params=payload) r.raise_for_status() return [Build(self._mbs_api, build["id"]) for build in r.json()["items"]] + + def get_module_builds(self, **kwargs): + """ + Query MBS API on module-builds endpoint + + :attribute **kwargs: options for the HTTP GET + :return: list of Build objects + :rtype: list + """ + url = f"{self._mbs_api}module-builds/" + r = requests.get(url, params=kwargs) + + r.raise_for_status() + return [Build(self._mbs_api, build["id"]) for build in r.json()["items"]] + + def get_module_build(self, build_id, **kwargs): + """ + Query MBS API on module-builds endpoint for a specific build + + :attribute build_id (int): build ID + :return: module build object + :rtype: Build + """ + url = f"{self._mbs_api}module-builds/{build_id}" + r = requests.get(url, params=kwargs) + + r.raise_for_status() + return Build(self._mbs_api, r.json()["id"])