From b21e130555abcd13c86871d13a73cee0a9c01767 Mon Sep 17 00:00:00 2001 From: Chenxiong Qi Date: Mar 03 2020 19:48:47 +0000 Subject: Reuse make_module in mmd resolver tests Signed-off-by: Chenxiong Qi --- diff --git a/tests/__init__.py b/tests/__init__.py index 0fce564..2752bee 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -5,6 +5,7 @@ from datetime import datetime, timedelta import functools import hashlib import os +import re import time from traceback import extract_stack @@ -489,10 +490,18 @@ def make_module( if arches: assert store_to_db - name, stream, version, context = nsvc.split(":") + nsvc_regex = re.compile(r"([^:]+):([^:]+):([^:]+)(?::(.+))?") + + match = nsvc_regex.match(nsvc) + if not match: + raise ValueError('Argument nsvc is not in format N:S:V or N:S:V:C') + + name, stream, version, context = match.groups() + mmd = Modulemd.ModuleStreamV2.new(name, stream) mmd.set_version(int(version)) - mmd.set_context(context) + if context: + mmd.set_context(context) mmd.set_summary("foo") # Test unicode in mmd. mmd.set_description(u"foo \u2019s") diff --git a/tests/test_web/test_mmd_resolver.py b/tests/test_web/test_mmd_resolver.py index 548f7a7..066c422 100644 --- a/tests/test_web/test_mmd_resolver.py +++ b/tests/test_web/test_mmd_resolver.py @@ -6,8 +6,8 @@ import collections import pytest import solv -from module_build_service import Modulemd from module_build_service.web.mmd_resolver import MMDResolver +from tests import make_module class TestMMDResolver: @@ -17,54 +17,6 @@ class TestMMDResolver: def teardown_method(self, test_method): pass - @staticmethod - def _make_mmd(nsvc, requires, xmd_buildrequires=None, virtual_streams=None): - name, stream, version = nsvc.split(":", 2) - mmd = Modulemd.ModuleStreamV2.new(name, stream) - mmd.set_summary("foo") - mmd.set_description("foo") - for license_ in mmd.get_module_licenses(): - mmd.remove_module_license(license_) - mmd.add_module_license("GPL") - - xmd = mmd.get_xmd() - xmd["mbs"] = {} - xmd["mbs"]["buildrequires"] = {} - if xmd_buildrequires: - for ns in xmd_buildrequires: - n, s = ns.split(":") - xmd["mbs"]["buildrequires"][n] = {"stream": s} - if virtual_streams: - xmd["mbs"]["virtual_streams"] = virtual_streams - mmd.set_xmd(xmd) - - if ":" in version: - version, context = version.split(":") - mmd.set_context(context) - add_requires = Modulemd.Dependencies.add_runtime_stream - add_empty_requires = Modulemd.Dependencies.set_empty_runtime_dependencies_for_module - else: - add_requires = Modulemd.Dependencies.add_buildtime_stream - add_empty_requires = Modulemd.Dependencies.set_empty_buildtime_dependencies_for_module - mmd.set_version(int(version)) - - if not isinstance(requires, list): - requires = [requires] - else: - requires = requires - - for reqs in requires: - deps = Modulemd.Dependencies() - for req_name, req_streams in reqs.items(): - if req_streams == []: - add_empty_requires(deps, req_name) - else: - for req_stream in req_streams: - add_requires(deps, req_name, req_stream) - mmd.add_dependencies(deps) - - return mmd - @pytest.mark.parametrize( "deps, expected", ( @@ -83,12 +35,25 @@ class TestMMDResolver: assert str(reqs) == expected @pytest.mark.parametrize( - "buildrequires, expected", + "dependencies, expected", ( - ({"platform": []}, [[["platform:f28:0:c0:x86_64"], ["platform:f29:0:c0:x86_64"]]]), - ({"platform": ["f28"]}, [[["platform:f28:0:c0:x86_64"]]]), ( - {"gtk": [], "qt": []}, + [{"buildrequires": {"platform": []}}], + [ + [ + ["platform:f28:0:c0:x86_64"], + ["platform:f29:0:c0:x86_64"], + ] + ] + ), + ( + [{"buildrequires": {"platform": ["f28"]}}], + [ + [["platform:f28:0:c0:x86_64"]] + ] + ), + ( + [{"buildrequires": {"gtk": [], "qt": []}}], [ [ ["gtk:3:0:c8:x86_64", "qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"], @@ -99,7 +64,7 @@ class TestMMDResolver: ], ), ( - {"gtk": [], "qt": [], "platform": []}, + [{"buildrequires": {"gtk": [], "qt": [], "platform": []}}], [ [ ["gtk:3:0:c8:x86_64", "qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"], @@ -114,7 +79,10 @@ class TestMMDResolver: ], ), ( - [{"qt": [], "platform": ["f28"]}, {"gtk": [], "platform": ["f29"]}], + [ + {"buildrequires": {"qt": [], "platform": ["f28"]}}, + {"buildrequires": {"gtk": [], "platform": ["f29"]}} + ], [ [ ["qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"], @@ -127,11 +95,11 @@ class TestMMDResolver: ], ), ( - {"mess": []}, + [{"buildrequires": {"mess": []}}], [[["mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64", "platform:f28:0:c0:x86_64"]]], ), ( - {"mess": [], "platform": []}, + [{"buildrequires": {"mess": [], "platform": []}}], [ [ ["mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64", "platform:f28:0:c0:x86_64"], @@ -141,27 +109,31 @@ class TestMMDResolver: ), ), ) - def test_solve(self, buildrequires, expected): + def test_solve(self, dependencies, expected): modules = ( - ("platform:f28:0:c0", {}), - ("platform:f29:0:c0", {}), - ("gtk:3:0:c8", {"platform": ["f28"]}), - ("gtk:3:0:c9", {"platform": ["f29"]}), - ("gtk:4:0:c8", {"platform": ["f28"]}), - ("gtk:4:0:c9", {"platform": ["f29"]}), - ("qt:4:0:c8", {"platform": ["f28"]}), - ("qt:4:0:c9", {"platform": ["f29"]}), - ("qt:5:0:c8", {"platform": ["f28"]}), - ("qt:5:0:c9", {"platform": ["f29"]}), + ("platform:f28:0:c0", []), + ("platform:f29:0:c0", []), + ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}]), + ("gtk:3:0:c9", [{"requires": {"platform": ["f29"]}}]), + ("gtk:4:0:c8", [{"requires": {"platform": ["f28"]}}]), + ("gtk:4:0:c9", [{"requires": {"platform": ["f29"]}}]), + ("qt:4:0:c8", [{"requires": {"platform": ["f28"]}}]), + ("qt:4:0:c9", [{"requires": {"platform": ["f29"]}}]), + ("qt:5:0:c8", [{"requires": {"platform": ["f28"]}}]), + ("qt:5:0:c9", [{"requires": {"platform": ["f29"]}}]), ( "mess:1:0:c0", - [{"gtk": ["3"], "platform": ["f28"]}, {"gtk": ["4"], "platform": ["f29"]}], + [ + {"requires": {"gtk": ["3"], "platform": ["f28"]}}, + {"requires": {"gtk": ["4"], "platform": ["f29"]}}, + ], ), ) - for n, req in modules: - self.mmd_resolver.add_modules(self._make_mmd(n, req)) + for nsvc, deps in modules: + self.mmd_resolver.add_modules( + make_module(nsvc, dependencies=deps)) - app = self._make_mmd("app:1:0", buildrequires) + app = make_module("app:1:0", dependencies=dependencies) expanded = self.mmd_resolver.solve(app) expected = set( @@ -171,11 +143,11 @@ class TestMMDResolver: assert expanded == expected @pytest.mark.parametrize( - "buildrequires, expected", + "dependencies, expected", ( # BR all platform streams -> build for all platform streams. ( - {"platform": []}, + [{"buildrequires": {"platform": []}}], [ [ ["platform:el8.2.0.z:0:c0:x86_64"], @@ -187,7 +159,7 @@ class TestMMDResolver: ), # BR "el8" platform stream -> build for all el8 platform streams. ( - {"platform": ["el8"]}, + [{"buildrequires": {"platform": ["el8"]}}], [ [ ["platform:el8.2.0.z:0:c0:x86_64"], @@ -197,18 +169,21 @@ class TestMMDResolver: ], ), # BR "el8.1.0" platform stream -> build just for el8.1.0. - ({"platform": ["el8.1.0"]}, [[["platform:el8.1.0:0:c0:x86_64"]]]), + ( + [{"buildrequires": {"platform": ["el8.1.0"]}}], + [[["platform:el8.1.0:0:c0:x86_64"]]] + ), # BR platform:el8.1.0 and gtk:3, which is not built against el8.1.0, # but it is built only against el8.0.0 -> cherry-pick gtk:3 from el8.0.0 # and build once against platform:el8.1.0. ( - {"platform": ["el8.1.0"], "gtk": ["3"]}, + [{"buildrequires": {"platform": ["el8.1.0"], "gtk": ["3"]}}], [[["platform:el8.1.0:0:c0:x86_64", "gtk:3:0:c8:x86_64"]]], ), # BR platform:el8.2.0 and gtk:3, this time gtk:3 build against el8.2.0 exists # -> use both platform and gtk from el8.2.0 and build once. ( - {"platform": ["el8.2.0.z"], "gtk": ["3"]}, + [{"buildrequires": {"platform": ["el8.2.0.z"], "gtk": ["3"]}}], [[["platform:el8.2.0.z:0:c0:x86_64", "gtk:3:1:c8:x86_64"]]], ), # BR platform:el8.2.0 and mess:1 which is built against platform:el8.1.0 and @@ -217,7 +192,7 @@ class TestMMDResolver: # -> cherry-pick mess:1 from el8.1.0 and # -> use gtk:3:1 from el8.2.0. ( - {"platform": ["el8.2.0.z"], "mess": ["1"]}, + [{"buildrequires": {"platform": ["el8.2.0.z"], "mess": ["1"]}}], [[["platform:el8.2.0.z:0:c0:x86_64", "mess:1:0:c0:x86_64", "gtk:3:1:c8:x86_64"]]], ), # BR platform:el8.1.0 and mess:1 which is built against platform:el8.1.0 and @@ -226,13 +201,13 @@ class TestMMDResolver: # -> Used mess:1 from el8.1.0 and # -> cherry-pick gtk:3:0 from el8.0.0. ( - {"platform": ["el8.1.0"], "mess": ["1"]}, + [{"buildrequires": {"platform": ["el8.1.0"], "mess": ["1"]}}], [[["platform:el8.1.0:0:c0:x86_64", "mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64"]]], ), # BR platform:el8.0.0 and mess:1 which is built against platform:el8.1.0 and # requires gtk:3 which is built against platform:el8.2.0 and platform:el8.0.0 # -> No valid combination, because mess:1 is only available in el8.1.0 and later. - ({"platform": ["el8.0.0"], "mess": ["1"]}, []), + ([{"buildrequires": {"platform": ["el8.0.0"], "mess": ["1"]}}], []), # This is undefined... it might build just once against latest platform or # against all the platforms... we don't know # ({"platform": ["el8"], "gtk": ["3"]}, {}, [ @@ -240,21 +215,40 @@ class TestMMDResolver: # ]), ), ) - def test_solve_virtual_streams(self, buildrequires, expected): + def test_solve_virtual_streams(self, dependencies, expected): modules = ( - # (nsvc, buildrequires, expanded_buildrequires, virtual_streams) - ("platform:el8.0.0:0:c0", {}, {}, ["el8"]), - ("platform:el8.1.0:0:c0", {}, {}, ["el8"]), - ("platform:el8.2.0.z:0:c0", {}, {}, ["el8"]), - ("platform:el7.6.0:0:c0", {}, {}, ["el7"]), - ("gtk:3:0:c8", {"platform": ["el8"]}, {"platform:el8.0.0"}, None), - ("gtk:3:1:c8", {"platform": ["el8"]}, {"platform:el8.2.0.z"}, None), - ("mess:1:0:c0", [{"gtk": ["3"], "platform": ["el8"]}], {"platform:el8.1.0"}, None), + # (nsvc, dependencies, xmd_mbs_buildrequires, virtual_streams) + ("platform:el8.0.0:0:c0", [], {}, ["el8"]), + ("platform:el8.1.0:0:c0", [], {}, ["el8"]), + ("platform:el8.2.0.z:0:c0", [], {}, ["el8"]), + ("platform:el7.6.0:0:c0", [], {}, ["el7"]), + ( + "gtk:3:0:c8", + [{"requires": {"platform": ["el8"]}}], + {"platform": {"stream": "el8.0.0"}}, + None + ), + ( + "gtk:3:1:c8", + [{"requires": {"platform": ["el8"]}}], + {"platform": {"stream": "el8.2.0.z"}}, + None + ), + ( + "mess:1:0:c0", + [{"requires": {"gtk": ["3"], "platform": ["el8"]}}], + {"platform": {"stream": "el8.1.0"}}, + None + ), ) - for n, req, xmd_br, virtual_streams in modules: - self.mmd_resolver.add_modules(self._make_mmd(n, req, xmd_br, virtual_streams)) - - app = self._make_mmd("app:1:0", buildrequires) + for nsvc, deps, xmd_mbs_brs, virtual_streams in modules: + xmd = {"mbs": {"buildrequires": xmd_mbs_brs}} + if virtual_streams: + xmd["mbs"]["virtual_streams"] = virtual_streams + self.mmd_resolver.add_modules( + make_module(nsvc, dependencies=deps, xmd=xmd)) + + app = make_module("app:1:0", dependencies=dependencies) if not expected: with pytest.raises(RuntimeError): self.mmd_resolver.solve(app) @@ -268,32 +262,32 @@ class TestMMDResolver: assert expanded == expected @pytest.mark.parametrize( - "app_buildrequires, modules, err_msg_regex", + "dependencies, modules, err_msg_regex", ( # app --br--> gtk:1 --req--> bar:1* ---req---> platform:f29 # \--br--> foo:1 --req--> bar:2* ---req--/ ( - {"gtk": "1", "foo": "1"}, + [{"buildrequires": {"gtk": ["1"], "foo": ["1"]}}], ( - ("platform:f29:0:c0", {}), - ("gtk:1:1:c01", {"bar": ["1"]}), - ("bar:1:0:c02", {"platform": ["f29"]}), - ("foo:1:1:c03", {"bar": ["2"]}), - ("bar:2:0:c04", {"platform": ["f29"]}), + ("platform:f29:0:c0", []), + ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]), + ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]), + ("foo:1:1:c03", [{"requires": {"bar": ["2"]}}]), + ("bar:2:0:c04", [{"requires": {"platform": ["f29"]}}]), ), "bar:1:0:c02 and bar:2:0:c04", ), # app --br--> gtk:1 --req--> bar:1* ----------req----------> platform:f29 # \--br--> foo:1 --req--> baz:1 --req--> bar:2* --req--/ ( - {"gtk": "1", "foo": "1"}, + [{"buildrequires": {"gtk": ["1"], "foo": ["1"]}}], ( - ("platform:f29:0:c0", {}), - ("gtk:1:1:c01", {"bar": ["1"]}), - ("bar:1:0:c02", {"platform": ["f29"]}), - ("foo:1:1:c03", {"baz": ["1"]}), - ("baz:1:1:c04", {"bar": ["2"]}), - ("bar:2:0:c05", {"platform": ["f29"]}), + ("platform:f29:0:c0", []), + ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]), + ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]), + ("foo:1:1:c03", [{"requires": {"baz": ["1"]}}]), + ("baz:1:1:c04", [{"requires": {"bar": ["2"]}}]), + ("bar:2:0:c05", [{"requires": {"platform": ["f29"]}}]), ), "bar:1:0:c02 and bar:2:0:c05", ), @@ -303,29 +297,37 @@ class TestMMDResolver: # \--br--> pkga:1 --req--> perl:5' -------req-----------/ # \--br--> pkgb:1 --req--> perl:6' -------req-----------/ ( - {"gtk": "1", "foo": "1", "pkga": "1", "pkgb": "1"}, + [{ + "buildrequires": { + "gtk": ["1"], + "foo": ["1"], + "pkga": ["1"], + "pkgb": ["1"], + } + }], ( ("platform:f29:0:c0", {}), - ("gtk:1:1:c01", {"bar": ["1"]}), - ("bar:1:0:c02", {"platform": ["f29"]}), - ("foo:1:1:c03", {"baz": ["1"]}), - ("baz:1:1:c04", {"bar": ["2"]}), - ("bar:2:0:c05", {"platform": ["f29"]}), - ("pkga:1:0:c06", {"perl": ["5"]}), - ("perl:5:0:c07", {"platform": ["f29"]}), - ("pkgb:1:0:c08", {"perl": ["6"]}), - ("perl:6:0:c09", {"platform": ["f29"]}), + ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]), + ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]), + ("foo:1:1:c03", [{"requires": {"baz": ["1"]}}]), + ("baz:1:1:c04", [{"requires": {"bar": ["2"]}}]), + ("bar:2:0:c05", [{"requires": {"platform": ["f29"]}}]), + ("pkga:1:0:c06", [{"requires": {"perl": ["5"]}}]), + ("perl:5:0:c07", [{"requires": {"platform": ["f29"]}}]), + ("pkgb:1:0:c08", [{"requires": {"perl": ["6"]}}]), + ("perl:6:0:c09", [{"requires": {"platform": ["f29"]}}]), ), # MMD Resolver should still catch a conflict "bar:1:0:c02 and bar:2:0:c05", ), ), ) - def test_solve_stream_conflicts(self, app_buildrequires, modules, err_msg_regex): - for n, req in modules: - self.mmd_resolver.add_modules(self._make_mmd(n, req)) + def test_solve_stream_conflicts(self, dependencies, modules, err_msg_regex): + for nsvc, deps in modules: + self.mmd_resolver.add_modules( + make_module(nsvc, dependencies=deps)) - app = self._make_mmd("app:1:0", app_buildrequires) + app = make_module("app:1:0", dependencies=dependencies) with pytest.raises(RuntimeError, match=err_msg_regex): self.mmd_resolver.solve(app) @@ -338,16 +340,19 @@ class TestMMDResolver: with all available platforms. """ modules = ( - ("platform:f28:0:c0", {}), - ("platform:f29:0:c0", {}), - ("platform:f30:0:c0", {}), - ("gtk:3:0:c8", {"platform": ["f28"]}), - ("gtk:3:0:c9", {"platform": ["f29"]}), + ("platform:f28:0:c0", []), + ("platform:f29:0:c0", []), + ("platform:f30:0:c0", []), + ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}]), + ("gtk:3:0:c9", [{"requires": {"platform": ["f29"]}}]), ) - for n, req in modules: - self.mmd_resolver.add_modules(self._make_mmd(n, req)) + for nsvc, deps in modules: + self.mmd_resolver.add_modules( + make_module(nsvc, dependencies=deps)) - app = self._make_mmd("app:1:0", {"platform": [], "gtk": ["3"]}) + app = make_module("app:1:0", dependencies=[ + {"buildrequires": {"platform": [], "gtk": ["3"]}} + ]) expanded = self.mmd_resolver.solve(app) # Build only against f28 and f29, because "gtk:3" is not built against f30. @@ -364,15 +369,24 @@ class TestMMDResolver: it was built on newer platform stream, but can run on any platform stream. """ modules = ( - ("platform:f28:0:c0", {}, {}), - ("platform:f29:0:c0", {}, {}), - ("platform:f30:0:c0", {}, {}), - ("foo:1:0:c8", {"platform": []}, ["platform:f29"]), + ("platform:f28:0:c0", [], {}), + ("platform:f29:0:c0", [], {}), + ("platform:f30:0:c0", [], {}), + ( + "foo:1:0:c8", + [{"requires": {"platform": []}}], + {"platform": {"stream": "f29"}} + ), ) - for n, req, xmd_req in modules: - self.mmd_resolver.add_modules(self._make_mmd(n, req, xmd_req)) - - app = self._make_mmd("app:1:0", {"platform": ["f28"], "foo": ["1"]}) + for nsvc, deps, xmd_mbs_brs in modules: + mmd = make_module(nsvc, dependencies=deps, xmd={ + "mbs": {"buildrequires": xmd_mbs_brs} + }) + self.mmd_resolver.add_modules(mmd) + + app = make_module("app:1:0", [ + {"buildrequires": {"platform": ["f28"], "foo": ["1"]}} + ]) expanded = self.mmd_resolver.solve(app) expected = { @@ -382,18 +396,18 @@ class TestMMDResolver: assert expanded == expected @pytest.mark.parametrize( - "nsvc, requires, expected", + "nsvc, dependencies, expected", ( - ("platform:f28:0:c0", {}, True), - ("platform:latest:5:c8", {}, False), - ("gtk:3:0:c8", {"platform": ["f28"]}, False) + ("platform:f28:0:c0", [], True), + ("platform:latest:5:c8", [], False), + ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}], False) ), ) - def test_base_module_stream_version(self, nsvc, requires, expected): + def test_base_module_stream_version(self, nsvc, dependencies, expected): """ Tests that add_base_module_provides returns True for base modules with stream versions """ - mmd = self._make_mmd(nsvc, requires) + mmd = make_module(nsvc, dependencies=dependencies) solvable = self.mmd_resolver.available_repo.add_solvable() solvable.name = nsvc solvable.evr = str(mmd.get_version()) @@ -408,7 +422,7 @@ class TestMMDResolver: ), ) def test_base_module_provides(self, nsvc, expected): - self.mmd_resolver.add_modules(self._make_mmd(nsvc, {})) + self.mmd_resolver.add_modules(make_module(nsvc)) ns = nsvc.rsplit(":", 2)[0] provides = self.mmd_resolver.solvables[ns][0].lookup_deparray(solv.SOLVABLE_PROVIDES) assert {str(provide) for provide in provides} == expected