From 905b8e1aa13524cc113ad193f9a529d791b51ed3 Mon Sep 17 00:00:00 2001 From: Martin Curlej Date: Dec 08 2017 14:03:37 +0000 Subject: initial commit Redone the main diff loop, added more cli options Signed-off-by: Martin Curlej --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1472e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.swp +report.xml +.ropeproject/ +.cache/ +*.egg-info/ +*__pycache__/ diff --git a/README.md b/README.md index 1e0e0d8..5252d4d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,29 @@ # module_diff -Creates diffs between 2 versions of module. \ No newline at end of file +Creates diffs between 2 versions of module. Written in Python 3. + +# Development + +Has external dependencies (koji, rpm etc.) so you need to enable site-packages when creating venv. + +To install the tool do: + +``` +python setup.py install +``` + +For development create a venv with site-packages enabled and do: + +``` +python setup.py develop +``` + +# Tests + +To run tests do: +``` +python -m pytest -s +``` + + + diff --git a/bin/module_diff b/bin/module_diff new file mode 100755 index 0000000..ec01496 --- /dev/null +++ b/bin/module_diff @@ -0,0 +1,28 @@ +#!/bin/env python3 + +import argparse +from module_diff import module_diff + + +def main(org_nsv, diff_nsv, json=False, dist=False, reused=False): + module_diff(org_nsv, diff_nsv, json=json) + + +def parse_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("org_nsv", action="store", + help="The NSV of a module we are comparing to.") + parser.add_argument("diff_nsv", action="store", + help="The NSV of a module we want to compare.") + parser.add_argument("-j", "--json", action="store_true", + help="The module diff will returned as json.") + parser.add_argument("-d", "--dist", action="store_true", + help="Will display also rpms with changed only dist tag") + parser.add_argument("-r", "--reused", action="store_true", + help="Will display also rpms which where reused between versions.") + + return parser.parse_args() + +if __name__ == "__main__": + args = parse_arguments() + main(args.org_nsv, args.diff_nsv, json=args.json, dist=args.dist, reused=args.reused) diff --git a/module_diff/__init__.py b/module_diff/__init__.py new file mode 100644 index 0000000..3c17ed2 --- /dev/null +++ b/module_diff/__init__.py @@ -0,0 +1,69 @@ +import json +from module_diff.pdc import PDC + + +class CliColors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + +def module_diff(org_nsv, diff_nsv, json=False, dist=False, reused=False): + pdc = PDC() + # TODO is check for not found module needed? + org_module = pdc.get_module(org_nsv) + diff_module = pdc.get_module(diff_nsv) + + diff = org_module.get_diff(diff_module, dist=dist, reused=reused) + if json: + jsonify_diff(diff) + else: + human_readable_diff(diff, reused=reused, dist=dist) + + +def human_readable_diff(diff, reused=False, dist=False): + print("---- Stats ----\n") + stats = diff["stats"] + print("Compared modules:") + print("NSV: %s, # of RPMs: %s" % (stats["org_module"]["nsv"], stats["org_module"]["num_rpms"])) + print("NSV: %s, # of RPMs: %s" % (stats["diff_module"]["nsv"], stats["diff_module"]["num_rpms"])) + print("# of RPMs added: %s" % stats["num_added"]) + print("# of RPMs removed: %s" % stats["num_removed"]) + print("# of RPMs upgraded: %s" % stats["num_upgraded"]) + print("# of RPMs downgraded: %s" % stats["num_downgraded"]) + + if reused: + print("# of RPMs reused: %s" % stats["num_reused"]) + + if dist: + print("# of RPMs which dist tag changed: %s" % stats["changed_distag_rpms"]) + + print("---- RPMs Added ----\n") + for rpm in diff["added_rpms"]: + print("%s+ %s%s" % (CliColors.OKGREEN, rpm, CliColors.ENDC)) + print("\n---- RPMs Removed ----\n") + for rpm in diff["removed_rpms"]: + print("%s- %s%s" % (CliColors.FAIL, rpm, CliColors.ENDC)) + print("\n---- RPMs Upgraded ----\n") + for rpm in diff["upgraded_rpms"]: + print("U %s -> %s" % (rpm[0], rpm[1])) + print("\n---- RPMs Downgraded ----\n") + for rpm in diff["downgraded_rpms"]: + print("D %s -> %s" % (rpm[0], rpm[1])) + if reused: + print("\n---- RPMs Reused ----\n") + for rpm in diff["reused_rpms"]: + print("R %s" % rpm) + + if dist: + print("\n---- RPMs which dist tag changed ----\n") + for rpm in diff["changed_distag_rpms"]: + print("C %s -> %s" % (rpm[0], rpm[1])) + +def jsonify_diff(diff): + print(json.dumps(diff)) diff --git a/module_diff/module.py b/module_diff/module.py new file mode 100644 index 0000000..9e0cfcc --- /dev/null +++ b/module_diff/module.py @@ -0,0 +1,157 @@ +import re + +from kobo.rpmlib import parse_nvr, compare_nvr + +from modulemd import ModuleMetadata + + +class Module(object): + """ Represents a Module for diff purposes. """ + + def __init__(self, pdc_module_data): + """ + Args: + pdc_module_data (dict): the module data PDC response. + """ + module_data = pdc_module_data["results"][0] + self.variant_uid = module_data["variant_uid"] + self.variant_name = module_data["variant_name"] + self.variant_version = module_data["variant_version"] + self.variant_release = module_data["variant_release"] + self.koji_tag = module_data["koji_tag"] + self.dist_tag = module_data["koji_tag"][0:15].replace("-", "_") + self.pdc_modulemd = module_data["modulemd"] + self.rpms_set = set(module_data["rpms"]) + + @property + def modulemd(self): + """ + returns: + (ModuleMetadata): Metadata of the current module. + """ + if not hasattr(self, "mmd"): + self.mmd = ModuleMetadata() + self.mmd.loads(self.pdc_modulemd) + return self.mmd + + def get_diff(self, diff_module, dist=False, reused=False): + """ + Makes a diff between 2 modules. + Args: + diff_module (Module): Other Module object which we want to diff. + + Returns: + (dict): returns a dict with the results of a diff + """ + + if self.variant_name != diff_module.variant_name and \ + self.variant_version != diff_module.variant_version: + # NOTE Should we allow between stream diff? + message = ("Module %s and %s don't have the same name and stream! Can't diff!" + % (self.variant_uid, diff_module.variant_uid)) + raise ValueError(message) + + diff = {} + diff["stats"] = {} + added_rpms = [] + removed_rpms = [] + upgraded_rpms = [] + downgraded_rpms = [] + reused_rpms = [] + changed_distag_rpms = [] + + # first search for full matches, so we can remove reused rpms from previous builds + for org_rpm in self.rpms_set: + if org_rpm in diff_module.rpms_set: + reused_rpms.append(org_rpm) + else: + removed_rpms.append(org_rpm) + + added_rpms = list(diff_module.rpms_set - self.rpms_set) + + # now when we have reused rpms out of the way, we will inspect the removed and added rpms + # closely what changes where made to them. We need to have both lists with elements or we + # can't compare. + if removed_rpms and added_rpms: + removed_rpm_md = [] + added_rpm_md = [] + + # get metadata from both lists + for rpm in removed_rpms: + removed_rpm_md.append(self.get_rpm_md(rpm)) + + for rpm in added_rpms: + added_rpm_md.append(self.get_rpm_md(rpm)) + + for rem_rpm in removed_rpm_md: + for add_rpm in added_rpm_md: + # if we have a match between removed and added lists it means that the the rpm + # was not removed/added but there was some other change i. e. version change. + if rem_rpm["name"] == add_rpm["name"] and rem_rpm["arch"] == add_rpm["arch"]: + # we compare the versions of the rpms + result = compare_nvr(rem_rpm, add_rpm) + + if result == -1: + upgraded_rpms.append((rem_rpm["full_name"], add_rpm["full_name"])) + removed_rpms.remove(rem_rpm["full_name"]) + added_rpms.remove(add_rpm["full_name"]) + elif result == 1: + downgraded_rpms.append((rem_rpm["full_name"], add_rpm["full_name"])) + removed_rpms.remove(rem_rpm["full_name"]) + added_rpms.remove(add_rpm["full_name"]) + else: + # if the modules have the same version the only change is the dist tag. + changed_distag_rpms.append((rem_rpm["full_name"], add_rpm["full_name"])) + removed_rpms.remove(rem_rpm["full_name"]) + added_rpms.remove(add_rpm["full_name"]) + + diff["stats"]["org_module"] = {} + diff["stats"]["org_module"]["num_rpms"] = len(self.rpms_set) + diff["stats"]["org_module"]["nsv"] = self.variant_uid + diff["stats"]["diff_module"] = {} + diff["stats"]["diff_module"]["num_rpms"] = len(diff_module.rpms_set) + diff["stats"]["diff_module"]["nsv"] = diff_module.variant_uid + diff["stats"]["num_added"] = len(added_rpms) + diff["stats"]["num_removed"] = len(removed_rpms) + diff["stats"]["num_upgraded"] = len(upgraded_rpms) + diff["stats"]["num_downgraded"] = len(downgraded_rpms) + diff["added_rpms"] = added_rpms + diff["removed_rpms"] = removed_rpms + diff["upgraded_rpms"] = upgraded_rpms + diff["downgraded_rpms"] = downgraded_rpms + + if reused: + diff["stats"]["num_reused"] = len(reused_rpms) + diff["reused_rpms"] = reused_rpms + + if dist: + diff["stats"]["num_changed_dist"] = len(changed_distag_rpms) + diff["changed_distag_rpms"] = changed_distag_rpms + + return diff + + def get_rpm_md(self, rpm): + """ + Args: + rpm (str): full name of the rpm. + + Returns: + (dict): metadata for a given rpm + """ + md = {} + nvr_md = rpm.rsplit(".", 3) + # NOTE we are creating an NVR here without the module dist tag. As kobo.rpmlib.parse_nvr is + # not able to work with modules and will be not able to compare the rpms correctly. + nvr = "".join(nvr_md[0:1] + nvr_md[2:]) + md = parse_nvr(nvr) + md["full_name"] = rpm + # The release can be different for each rpm. We are using regex as we are not able to + # extract the dist tag other way. + match = re.search("\.(module\_\w+)\.", rpm) + md["dist_tag"] = match.group(1) + md["arch"] = nvr_md[2] + + return md + + def diff_modulemd(self): + pass diff --git a/module_diff/pdc.py b/module_diff/pdc.py new file mode 100644 index 0000000..9b6ad35 --- /dev/null +++ b/module_diff/pdc.py @@ -0,0 +1,20 @@ +import pdc_client + +from module_diff.module import Module + + +class PDC(object): + + def __init__(self): + self.module_namespace = "unreleasedvariants/" + self.pdc_url = "https://pdc.fedoraproject.org/rest_api/v1" + self.ssl_verify = False + self.develop = True + self.client = pdc_client.PDCClient(server=self.pdc_url, develop=self.develop, + ssl_verify=self.ssl_verify) + + def get_module(self, nsv): + pdc_module_data = self.client[self.module_namespace](page_size=1, **{"variant_uid": nsv}) + if not len(pdc_module_data["results"]): + raise Exception("No data found for module '%s' in PDC" % nsv) + return Module(pdc_module_data) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..939d0e4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +modulemd==1.3.2 +pdc-client==1.7.0 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..caae62d --- /dev/null +++ b/setup.py @@ -0,0 +1,30 @@ +from setuptools import setup, find_packages + +with open('requirements.txt') as f: + requirements = f.readlines() + +with open('test-requirements.txt') as f: + test_requirements = f.readlines() + +setup(name='module_diff', + description='Diffing tool for modules.', + version='1.0', + classifiers=[ + "Programming Language :: Python", + "Topic :: Software Development :: Build Tools" + ], + keywords='module build service utils fedora modularity koji mock rpm', + author='The Factory 2.0 Team', + author_email='mcurlej@redhat.com', + url='', + license='MIT', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requirements, + tests_require=test_requirements, + entry_points={}, + scripts=["bin/module_diff"], + data_files=[], + ) + diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..ed85ce0 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +pytest==3.2.5 +requests-mock==1.3.0 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..6b00f45 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,82 @@ +import copy +import pytest + + +@pytest.fixture +def pdc_json_res(): + """ Mock for module PDC response data """ + + dummy_mmd = ('data:\n components:\n rpms:\n mariadb:\n rationale: mariadb\n' + ' ref: master\n dependencies:\n buildrequires:\n host: master\n' + ' platform: master\n requires:\n platform: master\n description: ' + 'desc\n license:\n module:\n - MIT\n references:\n community: ' + 'modularity\n documentation: wiki\n summary: dummy\ndocument: modulemd' + '\nversion: 1\n') + + pdc_data = { + "count": 1, + "next": None, + "previous": None, + "results": [ + { + "variant_id": "mariadb", + "variant_uid": "mariadb-f26-20170517122119", + "variant_name": "mariadb", + "variant_type": "module", + "variant_version": "f26", + "variant_release": "20170517122119", + "koji_tag": "module-629c669e304b6950", + "modulemd": dummy_mmd, + "active": True, + "runtime_deps": [ + { + "dependency": "perl", + "stream": "f26" + }, + { + "dependency": "shared-userspace", + "stream": "f26" + }, + { + "dependency": "base-runtime", + "stream": "f26" + } + ], + "build_deps": [ + { + "dependency": "perl", + "stream": "f26" + }, + { + "dependency": "common-build-dependencies", + "stream": "f26" + }, + { + "dependency": "shared-userspace", + "stream": "f26" + }, + { + "dependency": "bootstrap", + "stream": "f26" + } + ], + "rpms": [ + "mariadb-3:10.2.9-3.module_629c669e.src.rpm", + "mariadb-debugsource-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-devel-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-connect-engine-3:10.2.9-3.module_629c669e.x86_64.rpm", + ] + } + ] + } + + # using the same data for multiple testcases, we are modifying it heavilly so we need a copy + # everytime + class PDCDataFactory(object): + def get(self): + return copy.deepcopy(pdc_data) + + return PDCDataFactory() diff --git a/tests/test_module.py b/tests/test_module.py new file mode 100644 index 0000000..c9ef050 --- /dev/null +++ b/tests/test_module.py @@ -0,0 +1,221 @@ +import pytest +import requests_mock + +from module_diff.pdc import PDC + + +module1_url = ("https://pdc.fedoraproject.org/rest_api/v1" + "/unreleasedvariants/" + "?page_size=1&variant_uid=mariadb-10.2-20171019133930") + +module2_url = ("https://pdc.fedoraproject.org/rest_api/v1" + "/unreleasedvariants/" + "?page_size=1&variant_uid=mariadb-10.2-20171103103655") + +module_diff_ns_url = ("https://pdc.fedoraproject.org/rest_api/v1" + "/unreleasedvariants/" + "?page_size=1&variant_uid=platform-f27-20171011150016") + + +@pytest.mark.usefixtures("pdc_json_res") +class TestModule(object): + """ + Test for the Module Class + """ + + def test_get_diff_no_diff(self, pdc_json_res): + """ Test if we dont have any diff between modules. """ + + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module2_res["results"][0]["koji_tag"] = "module-15d35d06c29b1848" + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module2_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("mariadb-10.2-20171103103655") + + diff = module1.get_diff(module2, reused=True) + + assert diff["added_rpms"] == [] + assert diff["removed_rpms"] == [] + assert diff["upgraded_rpms"] == [] + assert diff["downgraded_rpms"] == [] + assert len(diff["reused_rpms"]) == 7 + + def test_get_diff(self, pdc_json_res): + """ Testing different kinds of changes in modules """ + + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module1_res["results"][0]["rpms"].remove( + "mariadb-connect-engine-3:10.2.9-3.module_629c669e.x86_64.rpm") + module2_res["results"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["results"][0]["rpms"] = [ + "mariadb-debugsource-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-debuginfo-3:11.2.9-3.module_15d35d06.x86_64.rpm", + "mariadb-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-devel-3:9.2.9-3.module_15d35d06.x86_64.rpm", + "mariadb-connect-engine-3:10.2.9-3.module_15d35d06.x86_64.rpm" + ] + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module2_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("mariadb-10.2-20171103103655") + + diff = module1.get_diff(module2, reused=True) + + assert diff["added_rpms"] == [ + "mariadb-connect-engine-3:10.2.9-3.module_15d35d06.x86_64.rpm"] + assert diff["removed_rpms"] == ["mariadb-3:10.2.9-3.module_629c669e.src.rpm"] + assert diff["upgraded_rpms"] == [ + ('mariadb-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm', + 'mariadb-debuginfo-3:11.2.9-3.module_15d35d06.x86_64.rpm')] + assert diff["downgraded_rpms"] == [ + ('mariadb-devel-3:10.2.9-3.module_629c669e.x86_64.rpm', + 'mariadb-devel-3:9.2.9-3.module_15d35d06.x86_64.rpm')] + assert len(diff["reused_rpms"]) == 3 + + def test_get_diff_rpm_version_change(self, pdc_json_res): + """ Testing if a version changes """ + + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module2_res["results"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["results"][0]["rpms"] = [ + "mariadb-3:10.2.9-3.module_629c669e.src.rpm", + "mariadb-debugsource-3:11.2.9-3.module_15d35d06.x86_64.rpm", + "mariadb-connect-engine-debuginfo-3:10.2.8-3.module_15d35d06.x86_64.rpm", + "mariadb-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-devel-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-connect-engine-3:10.2.9-3.module_629c669e.x86_64.rpm" + ] + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module2_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("mariadb-10.2-20171103103655") + + diff = module1.get_diff(module2, reused=True) + + assert diff["added_rpms"] == [] + assert diff["removed_rpms"] == [] + assert diff["upgraded_rpms"] == [ + ('mariadb-debugsource-3:10.2.9-3.module_629c669e.x86_64.rpm', + 'mariadb-debugsource-3:11.2.9-3.module_15d35d06.x86_64.rpm')] + assert diff["downgraded_rpms"] == [ + ('mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm', + 'mariadb-connect-engine-debuginfo-3:10.2.8-3.module_15d35d06.x86_64.rpm')] + assert len(diff["reused_rpms"]) == 5 + + def test_get_diff_rpm_removed(self, pdc_json_res): + """ Testing if the module changes of an RPM """ + + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module2_res["results"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["results"][0]["rpms"].remove("mariadb-3:10.2.9-3.module_629c669e.src.rpm") + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module2_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("mariadb-10.2-20171103103655") + + diff = module1.get_diff(module2, reused=True) + + assert diff["added_rpms"] == [] + assert diff["removed_rpms"] == ["mariadb-3:10.2.9-3.module_629c669e.src.rpm"] + assert diff["upgraded_rpms"] == [] + assert diff["downgraded_rpms"] == [] + assert len(diff["reused_rpms"]) == 6 + + def test_get_diff_different_ns(self, pdc_json_res): + """ + If we have different name and stream between compared modules an error should be raised + """ + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module2_res["results"][0]["variant_uid"] = "platform-f27-20171011150016" + module2_res["results"][0]["variant_name"] = "platform" + module2_res["results"][0]["variant_version"] = "f27" + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module_diff_ns_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("platform-f27-20171011150016") + + with pytest.raises(ValueError): + module1.get_diff(module2) + + def test_get_diff_change_dist_tag(self, pdc_json_res): + """ + Testing if a distag changes between modules + """ + module1_res = pdc_json_res.get() + module2_res = pdc_json_res.get() + module2_res["results"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["results"][0]["rpms"] = [ + "mariadb-3:10.2.9-3.module_629c669e.src.rpm", + "mariadb-debugsource-3:10.2.9-3.module_15d35d06.x86_64.rpm", + "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-debuginfo-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-devel-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-connect-engine-3:10.2.9-3.module_629c669e.x86_64.rpm" + ] + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + mock_http.register_uri("GET", module2_url, json=module2_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + module2 = pdc.get_module("mariadb-10.2-20171103103655") + + diff = module1.get_diff(module2, reused=True, dist=True) + + assert diff["added_rpms"] == [] + assert diff["removed_rpms"] == [] + assert diff["upgraded_rpms"] == [] + assert diff["downgraded_rpms"] == [] + assert len(diff["reused_rpms"]) == 6 + assert diff["changed_distag_rpms"] == [ + ("mariadb-debugsource-3:10.2.9-3.module_629c669e.x86_64.rpm", + "mariadb-debugsource-3:10.2.9-3.module_15d35d06.x86_64.rpm")] + + def test_get_rpm_md(self, pdc_json_res): + """ + Testing to get correct metadata from name of a rpm file. + """ + module1_res = pdc_json_res.get() + + with requests_mock.mock() as mock_http: + mock_http.register_uri("GET", module1_url, json=module1_res) + pdc = PDC() + module1 = pdc.get_module("mariadb-10.2-20171019133930") + + rpm = "python3-hawkey-debuginfo-0:0.10.1-2.module_80d712e7.modularity.1.x86_64.rpm" + + md = module1.get_rpm_md(rpm) + + expected_md = {'arch': 'x86_64', + 'dist_tag': 'module_80d712e7', + 'epoch': '0', + 'full_name': 'python3-hawkey-debuginfo-0:0.10.1-2.module_80d712e7.modularity.1.x86_64.rpm', + 'name': 'python3-hawkey-debuginfo', + 'release': '2.module_80d712e7.modularityx86_64rpm', + 'version': '0.10.1'} + + assert md == expected_md diff --git a/tests/test_pdc.py b/tests/test_pdc.py new file mode 100644 index 0000000..80f5061 --- /dev/null +++ b/tests/test_pdc.py @@ -0,0 +1,43 @@ +import requests_mock +import pytest + +from modulemd import ModuleMetadata + +from module_diff.pdc import PDC +from module_diff.module import Module + + +@pytest.mark.usefixtures("pdc_json_res") +class TestPDC(object): + + def test_get_module(self, pdc_json_res): + api_url = ("https://pdc.fedoraproject.org/rest_api/v1" + "/unreleasedvariants/" + "?page_size=1&variant_uid=mariadb-f26-20170517122119") + + json = pdc_json_res.get() + + with requests_mock.mock() as mock_http: + mock_http.get(api_url, json=json) + pdc = PDC() + module = pdc.get_module("mariadb-f26-20170517122119") + + assert isinstance(module, Module) + assert isinstance(module.modulemd, ModuleMetadata) + + def test_get_module_not_found(self, pdc_json_res): + api_url = ("https://pdc.fedoraproject.org/rest_api/v1" + "/unreleasedvariants/" + "?page_size=1&variant_uid=mariadb-f26-20170517122119") + + json = pdc_json_res.get() + json["results"] = [] + + with requests_mock.mock() as mock_http: + mock_http.get(api_url, json=json) + pdc = PDC() + with pytest.raises(Exception) as ex: + pdc.get_module("mariadb-f26-20170517122119") + + assert ex.value.args[0] == ("No data found for module 'mariadb-f26-20170517122119'" + " in PDC")