From a512ac9ac848b2019784f2d73430f1b0baebbeae Mon Sep 17 00:00:00 2001 From: Filip Valder Date: Jun 29 2018 10:49:41 +0000 Subject: module_diff without PDC --- diff --git a/.gitignore b/.gitignore index 850825d..c54392a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ -*.swp -report.xml -.ropeproject/ -.cache/ *.egg-info/ *__pycache__/ +.cache/ +.ropeproject/ .tox/ +*.pyc +*.pytest_cache/ +*.swp module_diffc +report.xml diff --git a/README.md b/README.md index 963c1a3..b1d7b69 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # module_diff -Creates diffs between 2 versions of module. Written in Python 3, but is compatible with python 2.7. +Creates diffs between two versions of a module. Written in Python 3, but is compatible with Python 2.7. -# Development - -Has external dependencies (koji, rpm etc.) so you need to enable site-packages when creating venv. +## Development To install the tool do: @@ -12,18 +10,15 @@ To install the tool do: python setup.py install ``` -For development create a venv with site-packages enabled and do: +For development create a venv and do: ``` python setup.py develop ``` -# Tests +## Tests To run tests do: ``` tox -e py27,py36,flake8 ``` - - - diff --git a/bin/module_diff b/bin/module_diff index 5be7b69..4649456 100755 --- a/bin/module_diff +++ b/bin/module_diff @@ -1,4 +1,4 @@ -#!/bin/env python3 +#!/bin/env python import argparse from module_diff import module_diff @@ -6,23 +6,24 @@ from module_diff import module_diff def main(): args = parse_arguments() - module_diff(args.org_nsv, args.diff_nsv, json=args.json, dist=args.dist, reused=args.reused) + module_diff(args.src_nsvc, args.dst_nsvc, json=args.json, dist=args.dist, reused=args.reused) 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.") + parser.add_argument("src_nsvc", action="store", + help="The NSVC of a source module to compare 'from'") + parser.add_argument("dst_nsvc", action="store", + help="The NSVC of a destination module to compare 'to'") + parser.add_argument("-j", "--json", action="store_true", + help="The module diff will be 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__": main() diff --git a/module_diff/__init__.py b/module_diff/__init__.py index 2f71060..6892dcc 100644 --- a/module_diff/__init__.py +++ b/module_diff/__init__.py @@ -1,5 +1,7 @@ import json -from module_diff.pdc import PDC + +from module_diff.mbs import MBS +from module_diff.module import Module class CliColors: @@ -13,12 +15,12 @@ class CliColors: UNDERLINE = '\033[4m' -def module_diff(org_nsv, diff_nsv, json=False, dist=False, reused=False): - pdc = PDC() - org_module = pdc.get_module(org_nsv) - diff_module = pdc.get_module(diff_nsv) +def module_diff(src_nsvc, dst_nsvc, json=False, dist=False, reused=False): + mbs = MBS() + src_module = Module(mbs.get_module(src_nsvc), dist, reused) + dst_module = Module(mbs.get_module(dst_nsvc), dist, reused) - diff = org_module.get_diff(diff_module, dist=dist, reused=reused) + diff = src_module.get_diff(dst_module) if json: jsonify_diff(diff) else: @@ -29,9 +31,10 @@ 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("NSVC: %s, # of RPMs: %s" % (stats["src_module"]["nsvc"], + stats["src_module"]["num_rpms"])) + print("NSVC: %s, # of RPMs: %s" % (stats["dst_module"]["nsvc"], + stats["dst_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"]) diff --git a/module_diff/mbs.py b/module_diff/mbs.py new file mode 100644 index 0000000..e904018 --- /dev/null +++ b/module_diff/mbs.py @@ -0,0 +1,34 @@ +import requests + + +class MBS(object): + + def __init__(self): + self.mbs_url = ('https://mbs.fedoraproject.org' + '/module-build-service/1/module-builds/') + self.params = {'verbose': 'true'} + + def get_module(self, nsvc): + name = nsvc.split("-")[0:-3] + stream = nsvc.split("-")[-3] + version = nsvc.split("-")[-2] + context = nsvc.split("-")[-1] + params = dict(self.params) + params.update({'name': name, 'stream': stream, 'version': version, 'context': context}) + res = requests.get(self.mbs_url, params=params) + + if not res.ok: + raise requests.HTTPError( + "Couldn't get module data. Check the URL: %s" % res.url) + + try: + module_data = res.json() + except Exception: + raise RuntimeError( + "Couldn't process module data. Check the response: %s" % res.text) + + if not module_data['meta']['total'] == 1: + raise RuntimeError('We need exactly one module in response from MBS.' + ' Check the URL: %s' % res.url) + + return module_data["items"][0] diff --git a/module_diff/module.py b/module_diff/module.py index 9e0cfcc..a77887c 100644 --- a/module_diff/module.py +++ b/module_diff/module.py @@ -1,58 +1,65 @@ import re +from itertools import product from kobo.rpmlib import parse_nvr, compare_nvr - from modulemd import ModuleMetadata +DISTAG_PATTERN = r"\.(module\_[0-9a-f]+)$" + + class Module(object): """ Represents a Module for diff purposes. """ - def __init__(self, pdc_module_data): + def __init__(self, module_data, dist=False, reused=False): """ Args: - pdc_module_data (dict): the module data PDC response. + module_data (dict): the module data from MBS 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.dist = dist + self.reused = reused + + self.name = module_data["name"] + self.stream = module_data["stream"] + self.version = module_data["version"] + self.context = module_data["context"] + self.nsvc = "-".join((self.name, + self.stream, + self.version, + self.context)) 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"]) + self.modulemd = module_data["modulemd"] + self.rpms = set([v["nvr"] for k, v in module_data["tasks"]["rpms"].items()]) @property - def modulemd(self): + def mmd(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 + if not hasattr(self, "_mmd"): + self._mmd = ModuleMetadata() + self._mmd.loads(self.modulemd) + return self._mmd - def get_diff(self, diff_module, dist=False, reused=False): + def get_diff(self, dst_module): """ Makes a diff between 2 modules. Args: - diff_module (Module): Other Module object which we want to diff. + dst_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: + if self.name != dst_module.name and \ + self.stream != dst_module.stream: # 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)) + % (self.nsvc, dst_module.nsvc)) raise ValueError(message) - diff = {} - diff["stats"] = {} added_rpms = [] removed_rpms = [] upgraded_rpms = [] @@ -60,18 +67,19 @@ class Module(object): 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) + # first search for full matches, so we can remove reused rpms + # from previous builds + for src_rpm in self.rpms: + if src_rpm in dst_module.rpms: + reused_rpms.append(src_rpm) else: - removed_rpms.append(org_rpm) + removed_rpms.append(src_rpm) - added_rpms = list(diff_module.rpms_set - self.rpms_set) + added_rpms = list(dst_module.rpms - self.rpms) - # 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. + # 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 = [] @@ -83,48 +91,65 @@ class Module(object): 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: + for rpms in product(removed_rpm_md, added_rpm_md): + rem_rpm, add_rpm = rpms + # 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 not rem_rpm["name"] == add_rpm["name"]: + continue + + # we compare the versions of the rpms + result = compare_nvr(rem_rpm, add_rpm) + dist_only_changed = ( + rem_rpm["full_name"].rpartition(rem_rpm["dist_tag"])[0] == + add_rpm["full_name"].rpartition(add_rpm["dist_tag"])[0]) + + if dist_only_changed: + # 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"])) + elif result == -1: + upgraded_rpms.append((rem_rpm["full_name"], + add_rpm["full_name"])) + elif result == 1: + downgraded_rpms.append((rem_rpm["full_name"], + add_rpm["full_name"])) + else: + raise ValueError( + "Couldn't handle version comparision: %s -> %s" % ( + rem_rpm["full_name"], add_rpm["full_name"])) + + removed_rpms.remove(rem_rpm["full_name"]) + added_rpms.remove(add_rpm["full_name"]) + + diff = { + "stats": { + "num_added": len(added_rpms), + "num_removed": len(removed_rpms), + "num_upgraded": len(upgraded_rpms), + "num_downgraded": len(downgraded_rpms), + "src_module": { + "num_rpms": len(self.rpms), + "nsvc": self.nsvc + }, + "dst_module": { + "num_rpms": len(dst_module.rpms), + "nsvc": dst_module.nsvc + } + }, + "added_rpms": added_rpms, + "removed_rpms": removed_rpms, + "upgraded_rpms": upgraded_rpms, + "downgraded_rpms": downgraded_rpms + } + + if self.reused: diff["stats"]["num_reused"] = len(reused_rpms) diff["reused_rpms"] = reused_rpms - if dist: + if self.dist: diff["stats"]["num_changed_dist"] = len(changed_distag_rpms) diff["changed_distag_rpms"] = changed_distag_rpms @@ -138,20 +163,19 @@ class Module(object): Returns: (dict): metadata for a given rpm """ + name, epoch_version, release = rpm.rsplit("-", 2) + if not self.dist: + release = re.sub(DISTAG_PATTERN, "", release) + nvr = '-'.join((name, epoch_version, release)) 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) + # 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(DISTAG_PATTERN, rpm) md["dist_tag"] = match.group(1) - md["arch"] = nvr_md[2] return md def diff_modulemd(self): - pass + raise NotImplementedError diff --git a/module_diff/pdc.py b/module_diff/pdc.py deleted file mode 100644 index 9b6ad35..0000000 --- a/module_diff/pdc.py +++ /dev/null @@ -1,20 +0,0 @@ -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 index 939d0e4..371110b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ -modulemd==1.3.2 -pdc-client==1.7.0 +kobo +koji +modulemd +requests diff --git a/setup.py b/setup.py index caae62d..034bd4d 100644 --- a/setup.py +++ b/setup.py @@ -27,4 +27,3 @@ setup(name='module_diff', scripts=["bin/module_diff"], data_files=[], ) - diff --git a/test-requirements.txt b/test-requirements.txt index 43d12b4..a756528 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,3 @@ -mock==2.0.0 -pytest==3.2.5 -requests-mock==1.3.0 +mock +pytest +requests-mock diff --git a/tests/conftest.py b/tests/conftest.py index 6b00f45..104a0d2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,82 +1,214 @@ -import copy +import json import pytest @pytest.fixture -def pdc_json_res(): - """ Mock for module PDC response data """ +def mbs_json_res(): + """ Mock MBS response (JSON) """ - 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", - ] - } - ] + mbs_data_text = (r''' +{ + "items": [ + { + "build_context": null, + "component_builds": [ + 20692, + 20691, + 20693, + 20697, + 20696, + 20695, + 20698, + 20694, + 20699, + 20701, + 20688, + 20690, + 20687, + 20689 + ], + "context": "00000000", + "id": 476, + "koji_tag": "module-629c669e304b6950", + "modulemd": "data:\n api:\n rpms: [mariadb]\n components:\n rpms:\n checkpolicy: {buildorder: 4, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/checkpolicy',\n rationale: Dep of selinux-policy package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/checkpolicy'}\n compat-openssl10: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/compat-openssl10',\n rationale: A dependency of mariadb., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/compat-openssl10'}\n dbus-glib: {buildorder: 3, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/dbus-glib',\n rationale: Dep of policycoreutils package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/dbus-glib'}\n desktop-file-utils: {buildorder: 3, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/desktop-file-utils',\n rationale: Dep of policycoreutils package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/desktop-file-utils'}\n libaio: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/libaio',\n rationale: A dependency of mariadb., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/libaio'}\n libcgroup: {buildorder: 3, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/libcgroup',\n rationale: Dep of policycoreutils package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/libcgroup'}\n libedit: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/libedit',\n rationale: A dependency of mariadb., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/libedit'}\n libselinux: {buildorder: 3, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/libselinux',\n rationale: Dep of policycoreutils package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/libselinux'}\n mariadb: {buildorder: 10, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/mariadb',\n rationale: MariaDB package., ref: private-f26-modules-mariadb-notests, repository: 'git://pkgs.fedoraproject.org/rpms/mariadb'}\n policycoreutils: {buildorder: 4, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/policycoreutils',\n rationale: Dep of selinux-policy package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/policycoreutils'}\n selinux-policy: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/selinux-policy',\n rationale: A dependency of mariadb., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/selinux-policy'}\n systemtap: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/systemtap',\n rationale: MariaDB package., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/systemtap'}\n time: {buildorder: 5, cache: 'http://pkgs.fedoraproject.org/repo/pkgs/time',\n rationale: A dependency of mariadb., ref: f26, repository: 'git://pkgs.fedoraproject.org/rpms/time'}\n dependencies:\n buildrequires: {bootstrap: f26, common-build-dependencies: f26, perl: f26, shared-userspace: f26}\n requires: {base-runtime: f26, perl: f26, shared-userspace: f26}\n description: MariaDB is a community developed branch of MySQL. MariaDB is a multi-user,\n multi-threaded SQL database server. It is a client/server implementation consisting\n of a server daemon (mysqld) and many different client programs and libraries.\n The base package contains the standard MariaDB/MySQL client programs and generic\n MySQL files.\n license:\n module: [GPLv2 with exceptions and LGPLv2 and BSD]\n name: mariadb\n profiles:\n default:\n rpms: [mariadb]\n references: {community: 'https://fedoraproject.org/wiki/Modularity', documentation: 'https://fedoraproject.org/wiki/Fedora_Packaging_Guidelines_for_Modules',\n tracker: 'https://taiga.fedorainfracloud.org/project/modularity'}\n stream: f26\n summary: MariaDB Module\n version: 20170517122119\n xmd:\n mbs:\n buildrequires:\n bootstrap: {ref: ae993ba84f4bce554471382ccba917ef16265f11, stream: f26, version: '1'}\n common-build-dependencies: {ref: 2960891d23f52d4008b6722142331451b66d88cf,\n stream: f26, version: '20170516122017'}\n perl: {ref: 634417c4c8d86fd473056b3aeab29be91c23812f, stream: f26, version: '20170515072053'}\n shared-userspace: {ref: 8eb98a0a79acce4eca1e129fd6bf270257eede16, stream: f26,\n version: '20170514220210'}\n commit: 7723b4e3c3cd105b274a88c4bc15aea848090114\n rpms:\n checkpolicy: {ref: 269e7db87e9501371a78c6a7d8dcc84d86aa7fb0}\n compat-openssl10: {ref: d59ab7262d0937c4064e5e42e066e8cfa330c6ef}\n dbus-glib: {ref: 109eff38b1821950e70c3872e5d29ef70ad499d1}\n desktop-file-utils: {ref: 8b09dcec35eb34cc54b7c7a2dc78a33ccc3aaf6f}\n libaio: {ref: db11cf2785cee8d274c6640edf9a7078c2509012}\n libcgroup: {ref: f5d7f93633504ad8dde5bcbe55d6b7c12a435eda}\n libedit: {ref: 3858b5775f5a3eef75fdff5239a20782ad259f94}\n libselinux: {ref: ea9eee161ed07911c9c672b0e598509e39cac679}\n mariadb: {ref: 7b7238abd85d6f9c6737756b9de8639e8a710906}\n policycoreutils: {ref: b185f8151d518e94376a442b9609fc95b7213bf4}\n selinux-policy: {ref: 1501d1ef8cad25b51add67498e91a9c0cf9615f6}\n systemtap: {ref: 43d514b85622d4b7362e4f5e1b7937f924a65b3a}\n time: {ref: 0e9df1c2aa4fa7454bba05cfc33e2785baadc0ac}\n scmurl: git://pkgs.fedoraproject.org/modules/mariadb?#7723b4e3c3cd105b274a88c4bc15aea848090114\ndocument: modulemd\nversion: 1\n",''' # noqa: E501 +''' + "name": "mariadb", + "owner": "mkocka", + "rebuild_strategy": "changed-and-after", + "ref_build_context": "5f901835774db773d663641a6c55c2b6a272928d", + "runtime_context": null, + "scmurl": "git://pkgs.fedoraproject.org/modules/mariadb?#7723b4e3c3cd105b274a88c4bc15aea848090114",''' # noqa: E501 +''' + "siblings": [], + "state": 5, + "state_name": "ready", + "state_reason": null, + "state_trace": [ + { + "reason": null, + "state": 1, + "state_name": "wait", + "time": "2017-05-17T12:21:47Z" + }, + { + "reason": null, + "state": 1, + "state_name": "wait", + "time": "2017-05-17T12:22:19Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T12:22:19Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T13:42:28Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T13:43:57Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:03:42Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:04:17Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:13:41Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:14:20Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:42:57Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T14:44:29Z" + }, + { + "reason": null, + "state": 2, + "state_name": "build", + "time": "2017-05-17T15:37:53Z" + }, + { + "reason": null, + "state": 3, + "state_name": "done", + "time": "2017-05-17T15:39:00Z" + }, + { + "reason": null, + "state": 3, + "state_name": "done", + "time": "2017-05-17T15:39:00Z" + }, + { + "reason": null, + "state": 5, + "state_name": "ready", + "time": "2017-05-17T15:39:00Z" + }, + { + "reason": null, + "state": 5, + "state_name": "ready", + "time": "2017-05-17T15:39:01Z" + } + ], + "state_url": "/module-build-service/1/module-builds/476", + "stream": "f26", + "tasks": { + "rpms": { + "mariadb-debugsource": { + "nvr": "mariadb-debugsource-3:10.2.9-3.module_629c669e" + }, + "mariadb-connect-engine-debuginfo": { + "nvr": "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e" + }, + "mariadb-debuginfo": { + "nvr": "mariadb-debuginfo-3:10.2.9-3.module_629c669e" + }, + "mariadb": { + "nvr": "mariadb-3:10.2.9-3.module_629c669e" + }, + "mariadb-devel": { + "nvr": "mariadb-devel-3:10.2.9-3.module_629c669e" + }, + "mariadb-connect-engine": { + "nvr": "mariadb-connect-engine-3:10.2.9-3.module_629c669e" + } + } + }, + "time_completed": "2017-05-17T15:39:00Z", + "time_modified": "2017-05-17T15:39:00Z", + "time_submitted": "2017-05-17T12:21:44Z", + "version": "20170517122119" } + ], + "meta": { + "first": "http://mbs.fedoraproject.org/module-build-service/1/module-builds/?verbose=True&stream=f26&version=20170517122119&context=00000000&per_page=10&page=1&name=mariadb",''' # noqa: E501 +''' + "last": "http://mbs.fedoraproject.org/module-build-service/1/module-builds/?verbose=True&stream=f26&version=20170517122119&context=00000000&per_page=10&page=1&name=mariadb",''' # noqa: E501 +''' + "next": null, + "page": 1, + "pages": 1, + "per_page": 10, + "prev": null, + "total": 1 + } +} +''') + + return json.loads(mbs_data_text) + + +@pytest.fixture +def mbs_json_res_no_match(): + """ Mock MBS response (JSON) - no match """ - # 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) + mbs_data_text = (''' +{ + "items": [], + "meta": { + "first": "http://mbs.fedoraproject.org/module-build-service/1/module-builds/?verbose=True&stream=f26&version=20010101000000&context=00000000&per_page=10&page=1&name=mariadb",''' # noqa: E501 +''' + "last": "http://mbs.fedoraproject.org/module-build-service/1/module-builds/?verbose=True&stream=f26&version=20010101000000&context=00000000&per_page=10&page=0&name=mariadb",''' # noqa: E501 +''' + "next": null, + "page": 1, + "pages": 0, + "per_page": 10, + "prev": null, + "total": 0 + } +} +''') - return PDCDataFactory() + return json.loads(mbs_data_text) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5a90eb3..0bb29a3 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,47 +1,74 @@ +import copy import json import mock import imp # importing the bin script as source through imp imp.load_source("module_diff_bin", "bin/module_diff") # noqa import requests_mock + from module_diff_bin import main -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") - - -def generate_module_res(pdc_json_res): - 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" - ] + +module1_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=mariadb&stream=10.2&version=20171019133930&context=00000000") + +module2_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=mariadb&stream=10.2&version=20171103103655&context=00000000") + + +def generate_module_res(mbs_json_res): + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + del module1_res["items"][0]["tasks"]["rpms"]["mariadb-connect-engine"] + module2_res["items"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["items"][0]["tasks"]["rpms"] = { + "mariadb-debugsource": { + "nvr": "mariadb-debugsource-3:10.2.9-3.module_629c669e", + }, + "mariadb-connect-engine-debuginfo": { + "nvr": "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e", + }, + "mariadb-debuginfo": { + "nvr": "mariadb-debuginfo-3:11.2.9-3.module_15d35d06", + }, + "mariadb": { + "nvr": "mariadb-3:10.2.9-3.module_629c669e", + }, + "mariadb-devel": { + "nvr": "mariadb-devel-3:9.2.9-3.module_15d35d06", + }, + "mariadb-connect-engine": { + "nvr": "mariadb-connect-engine-3:10.2.9-3.module_15d35d06" + }, + } return module1_res, module2_res +def check_common_output(output): + assert "Compared modules" in output + assert "NSVC:" in output + assert "# of RPMs:" in output + assert "# of RPMs added:" in output + assert "# of RPMs removed:" in output + assert "# of RPMs upgraded:" in output + assert "# of RPMs downgraded:" in output + assert "RPMs Added" in output + assert "RPMs Added" in output + assert "RPMs Removed" in output + assert "RPMs Upgraded" in output + assert "RPMs Downgraded" in output + + class TestCli(object): """ Tests for the cli of the module_diff tool """ - def test_cli_required_options(self, pdc_json_res, capsys): + def test_cli_required_options(self, mbs_json_res, capsys): """ Testing output with minimum required options """ - module1_res, module2_res = generate_module_res(pdc_json_res) + module1_res, module2_res = generate_module_res(mbs_json_res) with requests_mock.mock() as mock_http: mock_http.register_uri("GET", module1_url, json=module1_res) @@ -49,35 +76,24 @@ class TestCli(object): cli_cmd = [ 'module_diff', - 'mariadb-10.2-20171019133930', - 'mariadb-10.2-20171103103655' + 'mariadb-10.2-20171019133930-00000000', + 'mariadb-10.2-20171103103655-00000000' ] with mock.patch("sys.argv", cli_cmd): main() output = capsys.readouterr()[0] - assert "Compared modules" in output - assert "NSV:" in output - assert "# of RPMs:" in output - assert "# of RPMs added:" in output - assert "# of RPMs removed:" in output - assert "# of RPMs upgraded:" in output - assert "# of RPMs downgraded:" in output - assert "RPMs Added" in output - assert "RPMs Added" in output - assert "RPMs Removed" in output - assert "RPMs Upgraded" in output - assert "RPMs Downgraded" in output + check_common_output(output) assert "RPMs which dist tag changed" not in output assert "RPMs Reused" not in output - def test_cli_dist_option(self, pdc_json_res, capsys): + def test_cli_dist_option(self, mbs_json_res, capsys): """ Testing option --dist which displays RPMs which changed their dist tag. """ - module1_res, module2_res = generate_module_res(pdc_json_res) + module1_res, module2_res = generate_module_res(mbs_json_res) with requests_mock.mock() as mock_http: mock_http.register_uri("GET", module1_url, json=module1_res) @@ -85,8 +101,8 @@ class TestCli(object): cli_cmd = [ 'module_diff', - 'mariadb-10.2-20171019133930', - 'mariadb-10.2-20171103103655', + 'mariadb-10.2-20171019133930-00000000', + 'mariadb-10.2-20171103103655-00000000', '--dist' ] @@ -94,26 +110,15 @@ class TestCli(object): main() output = capsys.readouterr()[0] - assert "Compared modules" in output - assert "NSV:" in output - assert "# of RPMs:" in output - assert "# of RPMs added:" in output - assert "# of RPMs removed:" in output - assert "# of RPMs upgraded:" in output - assert "# of RPMs downgraded:" in output - assert "RPMs Added" in output - assert "RPMs Added" in output - assert "RPMs Removed" in output - assert "RPMs Upgraded" in output - assert "RPMs Downgraded" in output + check_common_output(output) assert "RPMs which dist tag changed" in output assert "RPMs Reused" not in output - def test_cli_reused_option(self, pdc_json_res, capsys): + def test_cli_reused_option(self, mbs_json_res, capsys): """ Testing option --reused which displays RPMs which where reused from previous build. """ - module1_res, module2_res = generate_module_res(pdc_json_res) + module1_res, module2_res = generate_module_res(mbs_json_res) with requests_mock.mock() as mock_http: mock_http.register_uri("GET", module1_url, json=module1_res) @@ -121,8 +126,8 @@ class TestCli(object): cli_cmd = [ 'module_diff', - 'mariadb-10.2-20171019133930', - 'mariadb-10.2-20171103103655', + 'mariadb-10.2-20171019133930-00000000', + 'mariadb-10.2-20171103103655-00000000', '--reused' ] @@ -130,26 +135,15 @@ class TestCli(object): main() output = capsys.readouterr()[0] - assert "Compared modules" in output - assert "NSV:" in output - assert "# of RPMs:" in output - assert "# of RPMs added:" in output - assert "# of RPMs removed:" in output - assert "# of RPMs upgraded:" in output - assert "# of RPMs downgraded:" in output - assert "RPMs Added" in output - assert "RPMs Added" in output - assert "RPMs Removed" in output - assert "RPMs Upgraded" in output - assert "RPMs Downgraded" in output + check_common_output(output) assert "RPMs which dist tag changed" not in output assert "RPMs Reused" in output - def test_cli_json_option(self, pdc_json_res, capsys): + def test_cli_json_option(self, mbs_json_res, capsys): """ Testing option --json which displays the output as a json string. """ - module1_res, module2_res = generate_module_res(pdc_json_res) + module1_res, module2_res = generate_module_res(mbs_json_res) with requests_mock.mock() as mock_http: mock_http.register_uri("GET", module1_url, json=module1_res) @@ -157,8 +151,8 @@ class TestCli(object): cli_cmd = [ 'module_diff', - 'mariadb-10.2-20171019133930', - 'mariadb-10.2-20171103103655', + 'mariadb-10.2-20171019133930-00000000', + 'mariadb-10.2-20171103103655-00000000', '--json' ] diff --git a/tests/test_mbs.py b/tests/test_mbs.py new file mode 100644 index 0000000..fc67bc2 --- /dev/null +++ b/tests/test_mbs.py @@ -0,0 +1,31 @@ +import pytest +import requests_mock + +from module_diff.mbs import MBS + + +class TestMBS(object): + + def test_get_module(self, mbs_json_res): + api_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=mariadb&stream=f26&version=20170517122119&context=00000000") + + with requests_mock.mock() as mock_http: + mock_http.get(api_url, json=mbs_json_res) + mbs = MBS() + module = mbs.get_module("mariadb-f26-20170517122119-00000000") + + assert module == mbs_json_res["items"][0] + + def test_get_module_no_match(self, mbs_json_res_no_match): + api_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=True&name=mariadb&stream=f26&version=20010101000000&context=00000000") + + with requests_mock.mock() as mock_http: + mock_http.get(api_url, json=mbs_json_res_no_match) + with pytest.raises(RuntimeError) as ex: + mbs = MBS() + mbs.get_module("mariadb-f26-20010101000000-00000000") + + assert str(ex.value).startswith( + "We need exactly one module in response from MBS. Check the URL: ") diff --git a/tests/test_module.py b/tests/test_module.py index cc415a4..cbe4d90 100644 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -1,222 +1,258 @@ +import copy import pytest import requests_mock -from module_diff.pdc import PDC +from module_diff.mbs import MBS +from module_diff.module import Module -module1_url = ("https://pdc.fedoraproject.org/rest_api/v1" - "/unreleasedvariants/" - "?page_size=1&variant_uid=mariadb-10.2-20171019133930") +module1_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=mariadb&stream=10.2&version=20171019133930&context=00000000") -module2_url = ("https://pdc.fedoraproject.org/rest_api/v1" - "/unreleasedvariants/" - "?page_size=1&variant_uid=mariadb-10.2-20171103103655") +module2_url = ("https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=mariadb&stream=10.2&version=20171103103655&context=00000000") -module_diff_ns_url = ("https://pdc.fedoraproject.org/rest_api/v1" - "/unreleasedvariants/" - "?page_size=1&variant_uid=platform-f27-20171011150016") +module_diff_ns_url = ( + "https://mbs.fedoraproject.org/module-build-service/1/module-builds/" + "?verbose=true&name=platform&stream=f27&version=20171011150016&context=00000000") -@pytest.mark.usefixtures("pdc_json_res") +@pytest.mark.usefixtures("mbs_json_res") class TestModule(object): """ Tests for the Module Class """ - def test_get_diff_no_diff(self, pdc_json_res): + def test_get_diff_no_diff(self, mbs_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" + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + module2_res["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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("mariadb-10.2-20171103103655-00000000")) - diff = module1.get_diff(module2, reused=True) + module1.reused = True + diff = module1.get_diff(module2) assert diff["added_rpms"] == [] assert diff["removed_rpms"] == [] assert diff["upgraded_rpms"] == [] assert diff["downgraded_rpms"] == [] - assert len(diff["reused_rpms"]) == 7 + assert len(diff["reused_rpms"]) == 6 - def test_get_diff(self, pdc_json_res): + def test_get_diff(self, mbs_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" - ] + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + del module1_res["items"][0]["tasks"]["rpms"]["mariadb-connect-engine"] + module2_res["items"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["items"][0]["tasks"]["rpms"] = { + "mariadb-debugsource": { + "nvr": "mariadb-debugsource-3:10.2.9-3.module_629c669e", + }, + "mariadb-connect-engine-debuginfo": { + "nvr": "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e", + }, + "mariadb-debuginfo": { + "nvr": "mariadb-debuginfo-3:11.2.9-3.module_15d35d06", + }, + "mariadb-devel": { + "nvr": "mariadb-devel-3:9.2.9-3.module_15d35d06", + }, + "mariadb-connect-engine": { + "nvr": "mariadb-connect-engine-3:10.2.9-3.module_15d35d06", + }, + } 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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("mariadb-10.2-20171103103655-00000000")) - diff = module1.get_diff(module2, reused=True) + module1.reused = True + diff = module1.get_diff(module2) 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"] + "mariadb-connect-engine-3:10.2.9-3.module_15d35d06"] + assert diff["removed_rpms"] == ["mariadb-3:10.2.9-3.module_629c669e"] 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')] + ('mariadb-debuginfo-3:10.2.9-3.module_629c669e', + 'mariadb-debuginfo-3:11.2.9-3.module_15d35d06')] 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 + ('mariadb-devel-3:10.2.9-3.module_629c669e', + 'mariadb-devel-3:9.2.9-3.module_15d35d06')] + assert len(diff["reused_rpms"]) == 2 - def test_get_diff_rpm_version_change(self, pdc_json_res): + def test_get_diff_rpm_version_change(self, mbs_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" - ] + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + module2_res["items"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["items"][0]["tasks"]["rpms"] = { + "mariadb": { + "nvr": "mariadb-3:10.2.9-3.module_629c669e", + }, + "mariadb-debugsource": { + "nvr": "mariadb-debugsource-3:11.2.9-3.module_15d35d06", + }, + "mariadb-connect-engine-debuginfo": { + "nvr": "mariadb-connect-engine-debuginfo-3:10.2.8-3.module_15d35d06", + }, + "mariadb-debuginfo": { + "nvr": "mariadb-debuginfo-3:10.2.9-3.module_629c669e", + }, + "mariadb-devel": { + "nvr": "mariadb-devel-3:10.2.9-3.module_629c669e", + }, + "mariadb-connect-engine": { + "nvr": "mariadb-connect-engine-3:10.2.9-3.module_629c669e" + }, + } 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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("mariadb-10.2-20171103103655-00000000")) - diff = module1.get_diff(module2, reused=True) + module1.reused = True + diff = module1.get_diff(module2) 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')] + ('mariadb-debugsource-3:10.2.9-3.module_629c669e', + 'mariadb-debugsource-3:11.2.9-3.module_15d35d06')] 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 + ('mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e', + 'mariadb-connect-engine-debuginfo-3:10.2.8-3.module_15d35d06')] + assert len(diff["reused_rpms"]) == 4 - def test_get_diff_rpm_removed(self, pdc_json_res): + def test_get_diff_rpm_removed(self, mbs_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") + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + module2_res["items"][0]["koji_tag"] = "module-15d35d06c29b1848" + del module2_res["items"][0]["tasks"]["rpms"]["mariadb"] 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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("mariadb-10.2-20171103103655-00000000")) - diff = module1.get_diff(module2, reused=True) + module1.reused = True + diff = module1.get_diff(module2) assert diff["added_rpms"] == [] - assert diff["removed_rpms"] == ["mariadb-3:10.2.9-3.module_629c669e.src.rpm"] + assert diff["removed_rpms"] == ["mariadb-3:10.2.9-3.module_629c669e"] assert diff["upgraded_rpms"] == [] assert diff["downgraded_rpms"] == [] - assert len(diff["reused_rpms"]) == 6 + assert len(diff["reused_rpms"]) == 5 - def test_get_diff_different_ns(self, pdc_json_res): + def test_get_diff_different_ns(self, mbs_json_res): """ - If we have different name and stream between compared modules an error should be raised + 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" + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + module2_res["items"][0]["nsvc"] = "platform-f27-20171011150016" + module2_res["items"][0]["name"] = "platform" + module2_res["items"][0]["stream"] = "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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("platform-f27-20171011150016-00000000")) with pytest.raises(ValueError): module1.get_diff(module2) - def test_get_diff_change_dist_tag(self, pdc_json_res): + def test_get_diff_change_dist_tag(self, mbs_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" - ] + module1_res = copy.deepcopy(mbs_json_res) + module2_res = copy.deepcopy(mbs_json_res) + module2_res["items"][0]["koji_tag"] = "module-15d35d06c29b1848" + module2_res["items"][0]["tasks"]["rpms"] = { + "mariadb": { + "nvr": "mariadb-3:10.2.9-3.module_629c669e", + }, + "mariadb-debugsource": { + "nvr": "mariadb-debugsource-3:10.2.9-3.module_15d35d06", + }, + "mariadb-connect-engine-debuginfo": { + "nvr": "mariadb-connect-engine-debuginfo-3:10.2.9-3.module_629c669e", + }, + "mariadb-debuginfo": { + "nvr": "mariadb-debuginfo-3:10.2.9-3.module_629c669e", + }, + "mariadb-devel": { + "nvr": "mariadb-devel-3:10.2.9-3.module_629c669e", + }, + "mariadb-connect-engine": { + "nvr": "mariadb-connect-engine-3:10.2.9-3.module_629c669e" + }, + } 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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) + module2 = Module(mbs.get_module("mariadb-10.2-20171103103655-00000000")) - diff = module1.get_diff(module2, reused=True, dist=True) + module1.reused = True + module1.dist = True + diff = module1.get_diff(module2) assert diff["added_rpms"] == [] assert diff["removed_rpms"] == [] assert diff["upgraded_rpms"] == [] assert diff["downgraded_rpms"] == [] - assert len(diff["reused_rpms"]) == 6 + assert len(diff["reused_rpms"]) == 5 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")] + ("mariadb-debugsource-3:10.2.9-3.module_629c669e", + "mariadb-debugsource-3:10.2.9-3.module_15d35d06")] - def test_get_rpm_md(self, pdc_json_res): + def test_get_rpm_md(self, mbs_json_res): """ Testing to get correct metadata from name of a rpm file. """ - module1_res = pdc_json_res.get() + module1_res = copy.deepcopy(mbs_json_res) 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") + mbs = MBS() + module1 = Module(mbs.get_module("mariadb-10.2-20171019133930-00000000")) - rpm = "python3-hawkey-debuginfo-0:0.10.1-2.module_80d712e7.modularity.1.x86_64.rpm" + rpm = "python3-hawkey-debuginfo-0:0.10.1-2.module_80d712e7" md = module1.get_rpm_md(rpm) - expected_md = {'arch': 'x86_64', - 'dist_tag': 'module_80d712e7', + expected_md = {'dist_tag': 'module_80d712e7', 'epoch': '0', 'full_name': ('python3-hawkey-debuginfo-0:0.10.1-2' - '.module_80d712e7.modularity.1.x86_64.rpm'), + '.module_80d712e7'), 'name': 'python3-hawkey-debuginfo', - 'release': '2.module_80d712e7.modularityx86_64rpm', + 'release': '2', 'version': '0.10.1'} assert md == expected_md diff --git a/tests/test_pdc.py b/tests/test_pdc.py deleted file mode 100644 index 80f5061..0000000 --- a/tests/test_pdc.py +++ /dev/null @@ -1,43 +0,0 @@ -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") diff --git a/tox.ini b/tox.ini index 128ee54..5c39d27 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ envlist = py27, py36, flake8 max-line-length = 100 [testenv] -sitepackages = True +usedevelop = true deps = -r{toxinidir}/test-requirements.txt commands = py.test {posargs} @@ -15,4 +15,3 @@ skip_install = true deps = flake8 commands = flake8 --ignore E731 --exclude .tox,.git module_diff/ tests/ ignore_outcome = True -