mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-30 05:42:05 +00:00
95b12167fa
When sorting two packages by their {Name Value Release} triplet to select the latest one, just doing a string comparison of the NVRs is wrong. Take for example the packages foo-0.10-1.fc25 and foo-0.2-1.fc25. A basic string comparison will result in the string "foo-0.10-1.fc25" being less than "foo-0.2-1.fc25", and thus foo-0.2-1.fc25 will be selected as the latest package. And that is wrong, because the latest one is obviously foo-0.10-1.fc25. So, after some research on this, I figured rpm.labelCompare is a better choice to appropriately compare two NVRs. Another reason why I chose rpm.labelCompare is because the latest build in fedabipkgdiff means a build with the latest version.release within a specific Fedora distribution such as fc23 or fc25. * configure.ac: Add new dependency. * tests/runtestfedabipkgdiff.py.in (builds): Add new builds for running tests to test selecting latest build from a package. (packages): Add new package gnutls. (GetPackageLatestBuildTest.{test_get_latest_one, test_cannot_find_a_latest_build_with_invalid_distro}): Use new builds of package gnutls to run tests. * tools/fedabipkgdiff (cmp_nvr): New function used to compare nvrs by Python built-in function sorted. (Brew.listBuilds): Use the new cmp_nvr function. Signed-off-by: Chenxiong Qi <cqi@redhat.com> Signed-off-by: Dodji Seketeli <dodji@redhat.com>
1236 lines
48 KiB
Python
Executable File
1236 lines
48 KiB
Python
Executable File
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
# -*- Mode: Python
|
|
#
|
|
# This file is part of the GNU Application Binary Interface Generic
|
|
# Analysis and Instrumentation Library (libabigail). This library is
|
|
# free software; you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the
|
|
# Free Software Foundation; either version 3, or (at your option) any
|
|
# later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public
|
|
# License along with this program; see the file COPYING-GPLV3. If
|
|
# not, see <http:#www.gnu.org/licenses/>.
|
|
#
|
|
# Author: Chenxiong Qi
|
|
|
|
import re
|
|
import os
|
|
import itertools
|
|
import unittest
|
|
import tempfile
|
|
from StringIO import StringIO
|
|
|
|
import koji
|
|
|
|
"""
|
|
This test harness tests various global methods and classes within
|
|
tools/fedabipkgdiff.
|
|
"""
|
|
|
|
try:
|
|
from mock import patch
|
|
except ImportError:
|
|
import sys
|
|
print >>sys.stderr, \
|
|
'mock is required to run tests. Please install before running tests.'
|
|
sys.exit(1)
|
|
|
|
import imp
|
|
# Import the fedabipkgdiff program file from the source directory.
|
|
fedabipkgdiff_mod = imp.load_source('fedabipkgdiff',
|
|
'@top_srcdir@/tools/fedabipkgdiff')
|
|
|
|
# Used to generate integer values (greater or equal to zero) in
|
|
# RunAbipkgdiffTest.test_partial_failure, those values simulate return code
|
|
# from run_abipkgdiff. To represent partial failure, counter must start from 0.
|
|
counter = itertools.count(0)
|
|
|
|
# prefix for creating a temporary file or directory. The name would be
|
|
# fedabipkgdiff-test-slkw3ksox
|
|
temp_file_or_dir_prefix = 'fedabipkgdiff-test-'
|
|
|
|
# Directory holding data used by following tests
|
|
TEST_DATA_DIR = os.path.abspath(
|
|
os.path.join('@top_srcdir@', 'tests', 'data', 'test-fedabipkgdiff'))
|
|
|
|
# topdir for tests from where to find and be treated as remote rpms to
|
|
# download.
|
|
TEST_TOPDIR = 'file://{0}'.format(TEST_DATA_DIR)
|
|
|
|
# download cache directory for tests to avoid touch the real xdg_cache_home and
|
|
# break any normal usage with fedabipkgdiff.
|
|
# Note, as `tempfile.mkdtemp` is called, each time to run tests from this
|
|
# module, this cache directory will be created at once.
|
|
TEST_DOWNLOAD_CACHE_DIR = tempfile.mkdtemp(
|
|
prefix='libabigail-test-fedabipkgdiff-download-cache-')
|
|
|
|
# Reference to built abipkgdiff command
|
|
BUILT_ABIPKGDIFF = '@top_builddir@/tools/abipkgdiff'
|
|
|
|
|
|
# ----------------- Koji resource storage begins ------------------
|
|
#
|
|
# List all necessary Koji resources for running tests within this test
|
|
# module. Currently, packages, builds, and rpms are listed here, and their
|
|
# relationship is maintained well. At the same time, all information including
|
|
# the ID for each package, build and rpm is real and can be queried from Koji,
|
|
# that is for convenience once developers need this.
|
|
#
|
|
# When additional packages, builds and rpms are required for test cases, here
|
|
# is the right place to add them. Just think them as a super simple in-memory
|
|
# database, and methods of MockClientSession knows well how to read them.
|
|
|
|
packages = [
|
|
{'id': 286, 'name': 'gnutls'},
|
|
{'id': 612, 'name': 'dbus-glib'},
|
|
{'id': 9041, 'name': 'nss-util'},
|
|
]
|
|
|
|
builds = [
|
|
{'build_id': 428835, 'nvr': 'dbus-glib-0.100-4.fc20',
|
|
'name': 'dbus-glib', 'release': '4.fc20', 'version': '0.100',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
{'build_id': 430720, 'nvr': 'dbus-glib-0.100.2-1.fc20',
|
|
'name': 'dbus-glib', 'release': '1.fc20', 'version': '0.100.2',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
{'build_id': 442366, 'nvr': 'dbus-glib-0.100.2-2.fc20',
|
|
'name': 'dbus-glib', 'release': '2.fc20', 'version': '0.100.2',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
{'build_id': 715478, 'nvr': 'dbus-glib-0.106-1.fc23',
|
|
'name': 'dbus-glib', 'release': '1.fc23', 'version': '0.106',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
{'build_id': 648058, 'nvr': 'dbus-glib-0.104-3.fc23',
|
|
'name': 'dbus-glib', 'release': '3.fc23', 'version': '0.104',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
{'build_id': 613769, 'nvr': 'dbus-glib-0.104-2.fc23',
|
|
'name': 'dbus-glib', 'release': '2.fc23', 'version': '0.104',
|
|
'package_id': 612, 'package_name': 'dbus-glib', 'state': 1,
|
|
},
|
|
|
|
{'build_id': 160295, 'nvr': 'nss-util-3.12.6-1.fc14',
|
|
'name': 'nss-util', 'version': '3.12.6', 'release': '1.fc14',
|
|
'package_id': 9041, 'package_name': 'nss-util', 'state': 1,
|
|
},
|
|
{'build_id': 767978, 'nvr': 'nss-util-3.24.0-2.0.fc25',
|
|
'name': 'nss-util', 'version': '3.24.0', 'release': '2.0.fc25',
|
|
'package_id': 9041, 'package_name': 'nss-util', 'state': 1,
|
|
},
|
|
|
|
# builds of package gnutls
|
|
{'build_id': 767306, 'nvr': 'gnutls-3.4.12-1.fc23',
|
|
'name': 'gnutls', 'release': '1.fc23', 'version': '3.4.12',
|
|
'package_id': 286, 'package_name': 'gnutls', 'state': 1,
|
|
},
|
|
{'build_id': 770965, 'nvr': 'gnutls-3.4.13-1.fc23',
|
|
'name': 'gnutls', 'release': '1.fc23', 'version': '3.4.13',
|
|
'package_id': 286, 'package_name': 'gnutls', 'state': 1,
|
|
},
|
|
{'build_id': 649701, 'nvr': 'gnutls-3.4.2-1.fc23',
|
|
'name': 'gnutls', 'release': '1.fc23', 'version': '3.4.2',
|
|
'package_id': 286, 'package_name': 'gnutls', 'state': 1,
|
|
},
|
|
]
|
|
|
|
rpms = [
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib', 'release': '2.fc20', 'version': '0.100.2',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-0.100.2-2.fc20',
|
|
},
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib-devel', 'release': '2.fc20', 'version': '0.100.2',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-devel-0.100.2-2.fc20',
|
|
},
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib-debuginfo', 'release': '2.fc20', 'version': '0.100.2',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-debuginfo-0.100.2-2.fc20',
|
|
},
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib-devel', 'release': '2.fc20', 'version': '0.100.2',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-devel-0.100.2-2.fc20',
|
|
},
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib-debuginfo', 'release': '2.fc20', 'version': '0.100.2',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-debuginfo-0.100.2-2.fc20',
|
|
},
|
|
{'build_id': 442366,
|
|
'name': 'dbus-glib', 'version': '0.100.2', 'release': '2.fc20',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-0.100.2-2.fc20',
|
|
},
|
|
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib-debuginfo', 'version': '0.106', 'release': '1.fc23',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-debuginfo-0.106-1.fc23',
|
|
},
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib', 'version': '0.106', 'release': '1.fc23',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-0.106-1.fc23',
|
|
},
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib-devel', 'version': '0.106', 'release': '1.fc23',
|
|
'arch': 'i686', 'nvr': 'dbus-glib-devel-0.106-1.fc23',
|
|
},
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib', 'version': '0.106', 'release': '1.fc23',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-0.106-1.fc23',
|
|
},
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib-debuginfo', 'version': '0.106', 'release': '1.fc23',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-debuginfo-0.106-1.fc23',
|
|
},
|
|
{'build_id': 715478,
|
|
'name': 'dbus-glib-devel', 'release': '1.fc23', 'version': '0.106',
|
|
'arch': 'x86_64', 'nvr': 'dbus-glib-devel-0.106-1.fc23',
|
|
},
|
|
|
|
# RPMs of build nss-util-3.12.6-1.fc14
|
|
{'build_id': 160295,
|
|
'name': 'nss-util', 'release': '1.fc14', 'version': '3.12.6',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-3.12.6-1.fc14',
|
|
},
|
|
{'build_id': 160295,
|
|
'name': 'nss-util-devel', 'release': '1.fc14', 'version': '3.12.6',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-devel-3.12.6-1.fc14',
|
|
},
|
|
{'build_id': 160295,
|
|
'name': 'nss-util-debuginfo', 'release': '1.fc14', 'version': '3.12.6',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-debuginfo-3.12.6-1.fc14',
|
|
},
|
|
|
|
# RPMs of build nss-util-3.24.0-2.0.fc25
|
|
{'build_id': 767978,
|
|
'name': 'nss-util-debuginfo', 'release': '2.0.fc25', 'version': '3.24.0',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-debuginfo-3.24.0-2.0.fc25',
|
|
},
|
|
{'build_id': 767978,
|
|
'name': 'nss-util', 'release': '2.0.fc25', 'version': '3.24.0',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-3.24.0-2.0.fc25',
|
|
},
|
|
{'build_id': 767978,
|
|
'name': 'nss-util-devel', 'release': '2.0.fc25', 'version': '3.24.0',
|
|
'arch': 'x86_64', 'nvr': 'nss-util-devel-3.24.0-2.0.fc25',
|
|
},
|
|
]
|
|
|
|
# ----------------- End of Koji resource storage ------------------
|
|
|
|
|
|
class AssertionHelper(object):
|
|
"""A helper class providing methods to assert output of abipkgdiff"""
|
|
|
|
def assert_compared_binaries(self, output, expected_binaries):
|
|
"""Assert specific binaries are already compared as expected
|
|
|
|
Caller doesn't need to care about the order of elements of
|
|
expected_binaries, it will be sorted by `list.sort` before assertion.
|
|
|
|
:param str output: output from abipkgdiff that is used to parse and
|
|
assert whether it contains expected binaries.
|
|
:param list expected_binaries: which binaries are expected to be
|
|
compared. Each of the binaries is a rpm filename, for example, foo.so.
|
|
"""
|
|
assert isinstance(expected_binaries, (tuple, list))
|
|
|
|
binaries = re.findall(r"=+\s?changes of '(.+)'\s*=+",
|
|
output,
|
|
re.MULTILINE)
|
|
binaries = list(set(binaries))
|
|
binaries.sort()
|
|
expected_binaries.sort()
|
|
self.assertEquals(expected_binaries, binaries)
|
|
|
|
def assert_compared_rpms(self, output, expected_rpms):
|
|
"""Assert specific rpms are already compared as expected
|
|
|
|
Caller doesn't need to care about the order of elements of
|
|
expected_rpms, but the order of each element, that is ('foo-0.1.rpm',
|
|
'foo-0.2.rpm') is different from ('foo-0.2.rpm', 'foo-0.1.rpm').
|
|
expected_rpms will be sorted properly.
|
|
|
|
:param str output: output from abipkgdiff that is used to parse and
|
|
assert whether it contains expected rpms.
|
|
:param list expected_rpms: which rpms are expected to be compared.
|
|
"""
|
|
assert isinstance(expected_rpms, (tuple, list))
|
|
|
|
compared_rpms = re.findall(
|
|
r'Comparing the ABI of binaries between ([^\s]+) and ([^\s]+):',
|
|
output,
|
|
re.MULTILINE)
|
|
|
|
sort_key_func = lambda rpm_pair: ' '.join(rpm_pair)
|
|
compared_rpms = sorted(compared_rpms, key=sort_key_func)
|
|
expected_rpms = sorted(expected_rpms, key=sort_key_func)
|
|
self.assertEquals(expected_rpms, compared_rpms)
|
|
|
|
def assert_functions_changes_summary(self, output,
|
|
expected_func_change_summary):
|
|
"""Assert functions changes summary is the expected result
|
|
|
|
:param str output: output from abipkgdiff that is used to parse and
|
|
assert whether "Functions changes summary:" contains expected changes.
|
|
:param dict expected_func_change_summary: a mapping containing
|
|
expected functions changes summary information, where keys must
|
|
contain removed, changed, changed_filtered_out, functions_added.
|
|
"""
|
|
assert isinstance(expected_func_change_summary, dict)
|
|
|
|
pattern = r'Functions changes summary: (\d+) Removed, (\d+) Changed \((\d+) filtered out\), (\d+) Added functions' # noqa
|
|
match = re.search(pattern, output)
|
|
if match is None:
|
|
raise ValueError(
|
|
'ABI changes does not contain functions changes summary.')
|
|
else:
|
|
groups = match.groups()
|
|
removed = int(groups[0])
|
|
changed = int(groups[1])
|
|
changed_filtered_out = int(groups[2])
|
|
functions_added = int(groups[3])
|
|
|
|
self.assertEquals(expected_func_change_summary['removed'], removed)
|
|
self.assertEquals(expected_func_change_summary['changed'], changed)
|
|
self.assertEquals(
|
|
expected_func_change_summary['changed_filtered_out'],
|
|
changed_filtered_out)
|
|
self.assertEquals(expected_func_change_summary['functions_added'],
|
|
functions_added)
|
|
|
|
def assert_abi_comparison_result(self,
|
|
output,
|
|
expected_binaries=None,
|
|
expected_rpms=None,
|
|
expected_func_change_summary=None):
|
|
"""A convenient way to assert expected values
|
|
|
|
Parameters will be passed to corresponding methods. Each assertio
|
|
method called within this method could be invoked individually. This
|
|
method exists as a convenient way to assert all expected values within
|
|
only one method call.
|
|
"""
|
|
if expected_rpms:
|
|
self.assert_compared_rpms(output, expected_rpms)
|
|
if expected_binaries:
|
|
self.assert_compared_binaries(output, expected_binaries)
|
|
if expected_func_change_summary:
|
|
self.assert_functions_changes_summary(output,
|
|
expected_func_change_summary)
|
|
|
|
|
|
class MockClientSession(object):
|
|
"""Mock koji.ClientSession
|
|
|
|
This mock ClientSession aims to avoid touching a real Koji instance to
|
|
interact with XMLRPC APIs required by fedabipkgdiff.
|
|
|
|
For the tests within this module, methods do not necessarily to return
|
|
complete RPM and build information. So, if you need more additional
|
|
information, here is the right place to add them.
|
|
"""
|
|
|
|
def __init__(self, baseurl):
|
|
"""Initialize a mock ClientSession
|
|
|
|
:param str baseurl: the URL to remote kojihub service. As of writing
|
|
this mock class, `baseurl` is not used at all, just keep it here if
|
|
it's useful in the future.
|
|
|
|
All mock methods have same signature as corresponding kojihub.*
|
|
methods, and type of parameters may be different and only satify
|
|
fedabipkgdiff requirement.
|
|
"""
|
|
self.baseurl = baseurl
|
|
|
|
def getPackage(self, name):
|
|
"""Mock kojihub.getPackage
|
|
|
|
:param str name: name of package to find and return
|
|
:return: the found package
|
|
:rtype: dict
|
|
"""
|
|
assert isinstance(name, basestring)
|
|
|
|
def selector(package):
|
|
return package['name'] == name
|
|
|
|
return filter(selector, packages)[0]
|
|
|
|
def getBuild(self, build_id):
|
|
"""Mock kojihub.getBuild
|
|
|
|
:param int build_id: ID of build to find and return
|
|
:return: the found build
|
|
:rtype: dict
|
|
"""
|
|
assert isinstance(build_id, int)
|
|
|
|
def selector(build):
|
|
return build['build_id'] == build_id
|
|
|
|
return filter(selector, builds)[0]
|
|
|
|
def listBuilds(self, packageID, state=None):
|
|
"""Mock kojihub.listBuilds
|
|
|
|
:param int packageID: ID of package whose builds is found and returned
|
|
:param state: build state. If state is omitted, all builds of a package
|
|
are returned
|
|
:type state: int or None
|
|
"""
|
|
assert isinstance(packageID, int)
|
|
if state is not None:
|
|
assert isinstance(state, int)
|
|
|
|
def selector(build):
|
|
selected = build['package_id'] == packageID
|
|
if state is not None:
|
|
selected = selected and build['state'] == state
|
|
return selected
|
|
|
|
return filter(selector, builds)
|
|
|
|
def getRPM(self, rpminfo):
|
|
"""Mock kojihub.getRPM
|
|
|
|
:param dict rpminfo: a mapping containing rpm information, at least,
|
|
it contains name, version, release, and arch.
|
|
"""
|
|
assert isinstance(rpminfo, dict)
|
|
|
|
def selector(rpm):
|
|
return rpm['name'] == rpminfo['name'] and \
|
|
rpm['version'] == rpminfo['version'] and \
|
|
rpm['release'] == rpminfo['release'] and \
|
|
rpm['arch'] == rpminfo['arch']
|
|
|
|
return filter(selector, rpms)[0]
|
|
|
|
def listRPMs(self, buildID, arches=None):
|
|
"""Mock kojihub.listRPMs
|
|
|
|
:param int buildID: ID of build from which to list rpms
|
|
:param arches: to list rpms built for specific arches. If arches is
|
|
omitted, rpms of all arches will be listed.
|
|
:type arches: list, tuple, str, or None
|
|
:return: list of rpms
|
|
:rtype: list
|
|
"""
|
|
assert isinstance(buildID, int)
|
|
if arches is not None:
|
|
assert isinstance(arches, (tuple, list, basestring))
|
|
|
|
if arches is not None and isinstance(arches, basestring):
|
|
arches = [arches]
|
|
|
|
def selector(rpm):
|
|
selected = rpm['build_id'] == buildID
|
|
if arches is not None:
|
|
selected = selected and rpm['arch'] in arches
|
|
return selected
|
|
|
|
return filter(selector, rpms)
|
|
|
|
|
|
class MockGlobalConfig(object):
|
|
"""Used to mock global_config
|
|
|
|
Since tests do not parse options from command line, so this class is
|
|
helpful for tests to contain all potential parsed (simulated)
|
|
options.
|
|
|
|
Currently, only koji_server and dry_run are required for running
|
|
tests. If any new test cases need others, please add them add as
|
|
class attribute directly.
|
|
"""
|
|
koji_server = fedabipkgdiff_mod.DEFAULT_KOJI_SERVER
|
|
koji_topdir = fedabipkgdiff_mod.DEFAULT_KOJI_TOPDIR
|
|
dry_run = False
|
|
dso_only = True
|
|
abipkgdiff = BUILT_ABIPKGDIFF
|
|
no_default_suppr = True
|
|
no_devel_pkg = None
|
|
check_all_subpackages = None
|
|
|
|
|
|
# Test Cases go here
|
|
|
|
|
|
class UtilsTest(unittest.TestCase):
|
|
|
|
def test_is_distro_valid(self):
|
|
"""Test is_fedora_distro method
|
|
|
|
is_fedora_distro aims to test if a string is a valid Fedora distro. I
|
|
don't see there is a general rule or format definition for such a
|
|
Fedora distro. I refer to second part of %{dist} splited by dot as the
|
|
reference. Generally, fc4, fc19, fc23 are valid ones, and el6, el7 are
|
|
also valid one currently.
|
|
"""
|
|
distro = 'fc5'
|
|
self.assertTrue(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'f5'
|
|
self.assertFalse(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'fc23'
|
|
self.assertTrue(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'fc'
|
|
self.assertFalse(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'fc234'
|
|
self.assertFalse(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'el7'
|
|
self.assertTrue(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
distro = 'el7_2'
|
|
self.assertFalse(fedabipkgdiff_mod.is_distro_valid(distro))
|
|
|
|
|
|
class RPMTest(unittest.TestCase):
|
|
"""Test case for RPM class
|
|
|
|
RPM class is a class wrapping a underlying dict object represeting a RPM
|
|
information, that is returned from Koji XMLRPC APIs.
|
|
|
|
This test aims to test the class to see if RPM attributes is accessible in
|
|
Python class attribute way, and if a RPM is specific type of RPM, for
|
|
example, if it's a debuginfo.
|
|
"""
|
|
|
|
def setUp(self):
|
|
"""Setup test data for testing RPM class
|
|
|
|
According to the tests, it's unnecessary to contruct a complete dict
|
|
containing full RPM information. So, only part of of them is
|
|
enough. This test case only need name, version, release, and arch.
|
|
|
|
In case Koji changes the name of name, version, release or arch in the
|
|
future to express same meaning individually, (I don't think it could
|
|
happen), please update there also.
|
|
"""
|
|
|
|
# Argument passed to RPM.__init__ to construct a RPM class object, that
|
|
# represents a debuginfo RPM.
|
|
self.debuginfo_rpm_info = {
|
|
'arch': 'i686',
|
|
'name': 'httpd-debuginfo',
|
|
'release': '1.fc22',
|
|
'version': '2.4.18'
|
|
}
|
|
|
|
# Argument passed to RPM.__init__ to construct a RPM class object, that
|
|
# represents a RPM.
|
|
self.rpm_info = {
|
|
'arch': 'x86_64',
|
|
'name': 'httpd',
|
|
'release': '1.fc22',
|
|
'version': '2.4.18'
|
|
}
|
|
|
|
self.devel_rpm_info = {
|
|
'arch': 'x86_64',
|
|
'name': 'httpd-devel',
|
|
'release': '1.fc22',
|
|
'version': '2.4.18'
|
|
}
|
|
|
|
def test_attribute_access(self):
|
|
"""Ensure wrapped RPM information is accessible via attribute"""
|
|
rpm = fedabipkgdiff_mod.RPM(self.debuginfo_rpm_info)
|
|
self.assertEquals(self.debuginfo_rpm_info['arch'], rpm.arch)
|
|
self.assertEquals(self.debuginfo_rpm_info['name'], rpm.name)
|
|
self.assertEquals(self.debuginfo_rpm_info['release'], rpm.release)
|
|
self.assertEquals(self.debuginfo_rpm_info['version'], rpm.version)
|
|
|
|
def test_raise_error_if_name_not_exist(self):
|
|
"""
|
|
Ensure AttributeError should be raised when accessing a non-existent
|
|
attribute
|
|
"""
|
|
rpm = fedabipkgdiff_mod.RPM({})
|
|
try:
|
|
rpm.xxxxx
|
|
except AttributeError:
|
|
# Succeed, exit normally
|
|
return
|
|
self.fail('AttributeError should be raised, but not.')
|
|
|
|
def test_is_debuginfo(self):
|
|
"""Ensure to return True if a RPM's name contains -debuginfo"""
|
|
rpm = fedabipkgdiff_mod.RPM(self.debuginfo_rpm_info)
|
|
self.assertTrue(rpm.is_debuginfo)
|
|
|
|
rpm = fedabipkgdiff_mod.RPM(self.rpm_info)
|
|
self.assertFalse(rpm.is_debuginfo)
|
|
|
|
def test_is_devel(self):
|
|
"""Ensure return True if a package is a development package"""
|
|
rpm = fedabipkgdiff_mod.RPM(self.debuginfo_rpm_info)
|
|
self.assertFalse(rpm.is_devel)
|
|
|
|
rpm = fedabipkgdiff_mod.RPM(self.rpm_info)
|
|
self.assertFalse(rpm.is_devel)
|
|
|
|
rpm = fedabipkgdiff_mod.RPM(self.devel_rpm_info)
|
|
self.assertTrue(rpm.is_devel)
|
|
|
|
def test_nvra(self):
|
|
"""
|
|
Ensure value from RPM.nvra is parsable and contains correct value from
|
|
underlying RPM information
|
|
"""
|
|
rpm = fedabipkgdiff_mod.RPM(self.rpm_info)
|
|
nvra = koji.parse_NVRA(rpm.nvra)
|
|
self.assertEquals(nvra['name'], rpm.name)
|
|
self.assertEquals(nvra['version'], rpm.version)
|
|
self.assertEquals(nvra['release'], rpm.release)
|
|
self.assertEquals(nvra['arch'], rpm.arch)
|
|
|
|
def test_str_representation(self):
|
|
"""
|
|
Enforce a RPM object has same string represetation as underlying
|
|
wrapped rpm information that is a dict object.
|
|
"""
|
|
rpm = fedabipkgdiff_mod.RPM(self.rpm_info)
|
|
self.assertEquals(str(self.rpm_info), str(rpm))
|
|
|
|
|
|
class LocalRPMTest(unittest.TestCase):
|
|
"""Test case for LocalRPM class
|
|
|
|
Because LocalRPM inherits from RPM, all tests against RPM class are also
|
|
applied to LocalRPM, so I don't repeat them again here. This test case
|
|
mainly focus on the abilities against files on the local disk.
|
|
"""
|
|
|
|
def setUp(self):
|
|
# A RPM filename that simulates a RPM file that is stored somewhere on
|
|
# the disk.
|
|
# This is the only argument passed to LocalRPM.__init__ to initialize
|
|
# an object.
|
|
self.filename = 'httpd-2.4.18-1.fc22.x86_64.rpm'
|
|
|
|
def test_file_parser_without_path(self):
|
|
"""Ensure LocalRPM can get RPM information from a filename
|
|
|
|
LocalRPM gets name, version, release, and arch of a RPM by parsing the
|
|
passed filename to __init__ method. Then, all these information is
|
|
accessible via LocalRPM name, version, release, and arch attribute.
|
|
|
|
A filename either with an absolute path, relative path, or without a
|
|
path, LocalRPM should be able to find these files and get correct
|
|
information by removing the potential present path. For example, by
|
|
giving following filenames,
|
|
|
|
- httpd-2.4.18-1.fc22.x86_64.rpm
|
|
- artifacts/httpd-2.4.18-1.fc22.x86_64.rpm
|
|
- /mnt/koji/packages/httpd/2.4.18/1.fc22/httpd-2.4.18-1.fc22.x86_64.rpm
|
|
|
|
LocalRPM has to determine the necessary RPM information from
|
|
httpd-2.4.18-1.fc22.x86_64.rpm
|
|
|
|
Without specifying path in the filename, it usually means LocalRPM
|
|
should find the RPM file relative to current working directory. So, no
|
|
need of additional test against a filename with a relative path.
|
|
"""
|
|
rpm = fedabipkgdiff_mod.LocalRPM(self.filename)
|
|
nvra = koji.parse_NVRA(self.filename)
|
|
self.assertEquals(nvra['name'], rpm.name)
|
|
self.assertEquals(nvra['version'], rpm.version)
|
|
self.assertEquals(nvra['release'], rpm.release)
|
|
self.assertEquals(nvra['arch'], rpm.arch)
|
|
|
|
full_filename = os.path.join('/', 'tmp', self.filename)
|
|
rpm = fedabipkgdiff_mod.LocalRPM(full_filename)
|
|
nvra = koji.parse_NVRA(self.filename)
|
|
self.assertEquals(nvra['name'], rpm.name)
|
|
self.assertEquals(nvra['version'], rpm.version)
|
|
self.assertEquals(nvra['release'], rpm.release)
|
|
self.assertEquals(nvra['arch'], rpm.arch)
|
|
self.assertEquals(full_filename, rpm.downloaded_file)
|
|
|
|
@patch('os.path.exists')
|
|
def test_find_existent_debuginfo(self, mock_exists):
|
|
"""Ensure LocalRPM can find an associated existent debuginfo RPM
|
|
|
|
Currently, find_debuginfo is only able to find associated debuginfo RPM
|
|
from the directory where local RPM resides. This test works for this
|
|
case at this moment. If there is a requirement to allow find debuginfo
|
|
RPM from somewhere else, any level of subdirectory for instance, add
|
|
new test case for that, and update these words you are reading :)
|
|
"""
|
|
mock_exists.return_value = True
|
|
|
|
rpm = fedabipkgdiff_mod.LocalRPM(self.filename)
|
|
self.assertTrue(isinstance(rpm, fedabipkgdiff_mod.LocalRPM))
|
|
|
|
nvra = koji.parse_NVRA(self.filename)
|
|
expected_debuginfo = fedabipkgdiff_mod.LocalRPM(
|
|
'%(name)s-debuginfo-%(version)s-%(release)s.%(arch)s.rpm' % nvra)
|
|
debuginfo = rpm.find_debuginfo()
|
|
self.assertEquals(expected_debuginfo.name, debuginfo.name)
|
|
self.assertEquals(expected_debuginfo.version, debuginfo.version)
|
|
self.assertEquals(expected_debuginfo.release, debuginfo.release)
|
|
|
|
def test_find_non_existent_debuginfo(self):
|
|
"""Ensure to return None if cannot find associated debuginfo RPM
|
|
|
|
os.path.exists is not mocked, that is because the associated debuginfo
|
|
RPM of httpd-2.4.18-1.fc22.x86_64.rpm given in setUp must be
|
|
non-existed during this test's run.
|
|
"""
|
|
rpm = fedabipkgdiff_mod.LocalRPM(self.filename)
|
|
self.assertEquals(None, rpm.find_debuginfo())
|
|
|
|
|
|
class RunAbipkgdiffTest(unittest.TestCase):
|
|
"""Test case for method run_abipkgdiff
|
|
|
|
Method run_abipkgdiff accepts package informations and passes them to and
|
|
run abipkgdiff command line utility. Since run_abipkgdiff does not catch
|
|
output to either standard output or standard error, and only returns the
|
|
return code that is returned from underlying abipkgdiff, these various test
|
|
cases test whether run_abipkgdiff is able to return the return code
|
|
correctly.
|
|
"""
|
|
|
|
def setUp(self):
|
|
"""Define packages information for calling run_abipkgdiff method
|
|
|
|
Due to the tests just care about the return code from underlying
|
|
abipkgdiff, only partial attributes of a RPM is required. That means,
|
|
it's unnecessary to give a full dict representing a complete RPM, just
|
|
build_id, name, version, release, and arch.
|
|
|
|
Full RPM information is not required. For this test case, only partial
|
|
information arch, build_id, name, release, and version are enough.
|
|
"""
|
|
|
|
# Used for testing the case of running abipkgdiff against one RPM
|
|
self.pkg1_single_info = {
|
|
'i686': [
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd-debuginfo',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd-devel',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
})
|
|
],
|
|
}
|
|
|
|
# Whatever the concrete content of pkg2_infos is, so just make a copy
|
|
# from self.pkg1_infos
|
|
self.pkg2_single_info = self.pkg1_single_info.copy()
|
|
|
|
# Used for testing the case of running abipkgdiff against multiple RPMs
|
|
self.pkg1_infos = {
|
|
'i686': [
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd-debuginfo',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'i686',
|
|
'build_id': 720222,
|
|
'name': 'httpd-devel',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
],
|
|
'x86_64': [
|
|
fedabipkgdiff_mod.RPM({'arch': 'x86_64',
|
|
'build_id': 720222,
|
|
'name': 'httpd',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'x86_64',
|
|
'build_id': 720222,
|
|
'name': 'httpd-debuginfo',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'x86_64',
|
|
'build_id': 720222,
|
|
'name': 'httpd-devel',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
],
|
|
'armv7hl': [
|
|
fedabipkgdiff_mod.RPM({'arch': 'armv7hl',
|
|
'build_id': 720222,
|
|
'name': 'httpd',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'armv7hl',
|
|
'build_id': 720222,
|
|
'name': 'httpd-debuginfo',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
fedabipkgdiff_mod.RPM({'arch': 'armv7hl',
|
|
'build_id': 720222,
|
|
'name': 'httpd-devel',
|
|
'release': '2.fc24',
|
|
'version': '2.4.18',
|
|
}),
|
|
],
|
|
}
|
|
|
|
# Whatever the concrete content of pkg2_infos is, so just make a copy
|
|
# from self.pkg1_infos
|
|
self.pkg2_infos = self.pkg1_infos.copy()
|
|
|
|
@patch('fedabipkgdiff.abipkgdiff')
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
def test_all_success(self, mock_abipkgdiff):
|
|
"""
|
|
Ensure run_abipkgdiff returns 0 when it succeeds to run against one or
|
|
more packages.
|
|
"""
|
|
mock_abipkgdiff.return_value = 0
|
|
|
|
result = fedabipkgdiff_mod.run_abipkgdiff(self.pkg1_single_info,
|
|
self.pkg2_single_info)
|
|
self.assertEquals(0, result)
|
|
|
|
result = fedabipkgdiff_mod.run_abipkgdiff(self.pkg1_infos,
|
|
self.pkg2_infos)
|
|
self.assertEquals(0, result)
|
|
|
|
@patch('fedabipkgdiff.abipkgdiff')
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
def test_all_failure(self, mock_abipkgdiff):
|
|
"""
|
|
Ensure run_abipkgdiff returns the return code from underlying
|
|
abipkgdiff when all calls to abipkgdiff fails against one or more
|
|
packages.
|
|
"""
|
|
mock_abipkgdiff.return_value = 4
|
|
|
|
result = fedabipkgdiff_mod.run_abipkgdiff(self.pkg1_single_info,
|
|
self.pkg2_single_info)
|
|
self.assertEquals(4, result)
|
|
|
|
result = fedabipkgdiff_mod.run_abipkgdiff(self.pkg1_infos,
|
|
self.pkg2_infos)
|
|
self.assertEquals(4, result)
|
|
|
|
@patch('fedabipkgdiff.abipkgdiff',
|
|
new=lambda param1, param2: counter.next())
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
def test_partial_failure(self):
|
|
"""
|
|
Ensure run_abipkgdiff returns non-zero when partial calls to
|
|
run_abipkgdiff succeed
|
|
|
|
abipkgdiff is mocked in order to simulte the partial success
|
|
calls. Why? That is because, counter starts from 0. So, it will
|
|
generate 0, 1, 2, ...
|
|
"""
|
|
result = fedabipkgdiff_mod.run_abipkgdiff(self.pkg1_infos,
|
|
self.pkg2_infos)
|
|
self.assertTrue(result > 0)
|
|
|
|
|
|
class GetPackageLatestBuildTest(unittest.TestCase):
|
|
"""Test case for get_package_latest_build"""
|
|
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
@patch('koji.ClientSession', new=MockClientSession)
|
|
def test_get_latest_one(self):
|
|
"""Ensure to get latest build of a package"""
|
|
session = fedabipkgdiff_mod.get_session()
|
|
build = session.get_package_latest_build('gnutls', 'fc23')
|
|
self.assertEquals('gnutls-3.4.13-1.fc23', build['nvr'])
|
|
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
@patch('koji.ClientSession', new=MockClientSession)
|
|
def test_cannot_find_a_latest_build_with_invalid_distro(self):
|
|
"""
|
|
Ensure NoCompleteBuilds is raised when trying to find a latest build of
|
|
a package for unknown Fedora distribution.
|
|
"""
|
|
session = fedabipkgdiff_mod.get_session()
|
|
self.assertRaises(fedabipkgdiff_mod.NoCompleteBuilds,
|
|
session.get_package_latest_build,
|
|
'gnutls', 'xxxx')
|
|
|
|
|
|
class DownloadRPMTest(unittest.TestCase):
|
|
"""Test case for download_rpm
|
|
|
|
Download a remote file, which is a local file simulating a remote file with
|
|
scheme file://, for example file:///tmp/a.txt, to download directory.
|
|
"""
|
|
|
|
def setUp(self):
|
|
# Create a remote file for testing download of this file
|
|
self.fd, self.remote_filename = tempfile.mkstemp(
|
|
prefix=temp_file_or_dir_prefix)
|
|
# Whatever the content is, this case does not care about. Close it
|
|
# immediately.
|
|
os.close(self.fd)
|
|
|
|
def tearDown(self):
|
|
os.remove(self.remote_filename)
|
|
|
|
def make_remote_file_url(self):
|
|
"""Make URL of remote file that is used for downloading this file"""
|
|
return 'file://{0}'.format(self.remote_filename)
|
|
|
|
def make_nonexistent_remote_file_url(self):
|
|
"""Return URL to a non-existent remote file"""
|
|
return os.path.join(self.make_remote_file_url(), 'nonexistent-file')
|
|
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
@patch('fedabipkgdiff.get_download_dir',
|
|
return_value=TEST_DOWNLOAD_CACHE_DIR)
|
|
def test_succeed_to_download_a_rpm(self, mock_get_download_dir):
|
|
"""Enusre True is returned if curl succeeds to download remote file
|
|
|
|
Download remote file to a fake download directory. Ensure everything is
|
|
okay, and return value from download_rpm should be truth.
|
|
"""
|
|
url = self.make_remote_file_url()
|
|
ret = fedabipkgdiff_mod.download_rpm(url)
|
|
self.assertTrue(ret)
|
|
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
@patch('fedabipkgdiff.get_download_dir',
|
|
return_value=TEST_DOWNLOAD_CACHE_DIR)
|
|
def test_failed_to_download_a_rpm(self, mock_get_download_dir):
|
|
"""Ensure False is returned if curl fails to download remote file
|
|
|
|
Download remote file to a fake download directory. But, making
|
|
something wrong to cause download_rpm returns false.
|
|
"""
|
|
url = self.make_nonexistent_remote_file_url()
|
|
ret = fedabipkgdiff_mod.download_rpm(url)
|
|
self.assertFalse(ret)
|
|
|
|
|
|
class BrewListRPMsTest(unittest.TestCase):
|
|
"""Test case for Brew.listRPMs"""
|
|
|
|
@patch('fedabipkgdiff.global_config', new=MockGlobalConfig)
|
|
@patch('koji.ClientSession', new=MockClientSession)
|
|
def test_select_specific_rpms(self):
|
|
"""Ensure Brew.listRPMs can select RPMs by a specific selector
|
|
|
|
This test will select RPMs whose name starts with httpd, that is only
|
|
httpd and httpd-debuginfo RPMs are selected and returned.
|
|
"""
|
|
def selector(rpm):
|
|
return rpm['name'] == 'dbus-glib-debuginfo' and \
|
|
rpm['arch'] == 'x86_64' and \
|
|
rpm['release'].endswith('fc20')
|
|
|
|
session = fedabipkgdiff_mod.get_session()
|
|
rpms = session.listRPMs(buildID=442366, selector=selector)
|
|
expected_rpms = [{
|
|
'build_id': 442366,
|
|
'name': 'dbus-glib-debuginfo',
|
|
'release': '2.fc20',
|
|
'version': '0.100.2',
|
|
'arch': 'x86_64',
|
|
'nvr': 'dbus-glib-debuginfo-0.100.2-2.fc20',
|
|
}]
|
|
self.assertEquals(expected_rpms, rpms)
|
|
|
|
|
|
# Integration tests
|
|
#
|
|
# Following integration tests aim to test execution of fedabipkgdiff from
|
|
# command line options to the expected ABI comparison result.
|
|
|
|
|
|
class CompareABIFromCommandLineTest(AssertionHelper, unittest.TestCase):
|
|
"""Test case for testing various use cases
|
|
|
|
All these tests aim to test fedabipkgdiff by executing against command line
|
|
options, that is to execute underlying abipkgdiff command. Output of
|
|
fedabipkgdiff is checked to see if it contains proper compared rpms and
|
|
binaries.
|
|
|
|
Following are mocked when run each test
|
|
|
|
* koji.ClientSession: avoid calling to the real Koji instance.
|
|
|
|
* --topdir option: let fedabipkgdiff download rpms from fedabipkgdiff's
|
|
test data directory instead of the remote Koji server.
|
|
|
|
* global method get_download_dir: use the fake directory to hold downloaded
|
|
rpm packages instead of .cache/fedabipkgdiff to break anything.
|
|
|
|
* sys.argv: to provide fedabipkgdiff command line options for each test.
|
|
"""
|
|
|
|
@patch('koji.ClientSession', new=MockClientSession)
|
|
@patch('sys.stdout', new_callable=StringIO)
|
|
@patch('fedabipkgdiff.get_download_dir',
|
|
return_value=TEST_DOWNLOAD_CACHE_DIR)
|
|
def run_abipkgdiff(self, mock_get_download_dir, mock_stdout):
|
|
fedabipkgdiff_mod.main()
|
|
return mock_stdout.getvalue()
|
|
|
|
@patch('sys.argv', new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'--from', 'fc20', '--to', 'fc23', 'dbus-glib'])
|
|
def test_compare_against_latest_build_of_package(self):
|
|
"""Test compare all arches of a package's latest build
|
|
|
|
Use case to test::
|
|
|
|
fedabipkgdiff --from fc20 --to fc23 dbus-glib
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-0.106-1.fc23.i686.rpm'),
|
|
('dbus-glib-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm'),
|
|
]
|
|
expected_binaries = ['dbus-binding-tool', 'libdbus-glib-1.so.2.2.2']
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
@patch('sys.argv',
|
|
new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'--from', 'fc20',
|
|
os.path.join(TEST_DATA_DIR,
|
|
'packages/dbus-glib/0.106/1.fc23/x86_64/'
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm')])
|
|
def test_compare_local_rpms_with_koji_rpms(self):
|
|
"""Test compare local rpm with remote associated one from Koji
|
|
|
|
Use case to test::
|
|
|
|
fedabipkgdiff --from fc20 path/to/local/rpm
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm'),
|
|
]
|
|
expected_binaries = ['dbus-binding-tool', 'libdbus-glib-1.so.2.2.2']
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
@patch('sys.argv', new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'dbus-glib-0.100.2-2.fc20',
|
|
'dbus-glib-0.106-1.fc23'])
|
|
def test_compare_rpm_packages(self):
|
|
"""Test compare rpms of packages specified by N-V-R
|
|
|
|
Use case to test::
|
|
|
|
fedabipkgdiff dbus-glib-0.100.2-2.fc20 dbus-glib-0.106-1.fc23
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-0.106-1.fc23.i686.rpm'),
|
|
('dbus-glib-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm'),
|
|
]
|
|
expected_binaries = ['dbus-binding-tool', 'libdbus-glib-1.so.2.2.2']
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
@patch('sys.argv', new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'dbus-glib-0.100.2-2.fc20.i686',
|
|
'dbus-glib-0.106-1.fc23.i686'])
|
|
def test_compare_rpm_packages_with_specific_arch(self):
|
|
"""Test compare rpms of packages specified by N-V-R-A
|
|
|
|
Use case to test::
|
|
|
|
fedabipkgdiff \
|
|
dbus-glib-0.100.2-2.fc20.i686 dbus-glib-0.106-1.fc23.i686
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-0.106-1.fc23.i686.rpm'),
|
|
]
|
|
expected_binaries = ['dbus-binding-tool', 'libdbus-glib-1.so.2.2.2']
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
@patch('sys.argv', new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'--all-subpackages',
|
|
'dbus-glib-0.100.2-2.fc20',
|
|
'dbus-glib-0.106-1.fc23'])
|
|
def test_compare_rpm_packages_all_subpackages(self):
|
|
"""Test compare all rpms instead of the main rpm only
|
|
|
|
Use case to test:
|
|
|
|
fedabipkgdiff --all-subpackages \
|
|
dbus-glib-0.100.2-2.fc20.i686 dbus-glib-0.106-1.fc23.i686
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-devel-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-devel-0.106-1.fc23.i686.rpm'),
|
|
('dbus-glib-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-0.106-1.fc23.i686.rpm'),
|
|
('dbus-glib-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm'),
|
|
('dbus-glib-devel-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-devel-0.106-1.fc23.x86_64.rpm')
|
|
]
|
|
expected_binaries = [
|
|
'dbus-bash-completion-helper',
|
|
'dbus-binding-tool',
|
|
'libdbus-glib-1.so.2.2.2',
|
|
]
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
@patch('sys.argv', new=['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'--dso-only',
|
|
'--from', 'fc20', '--to', 'fc23', 'dbus-glib'])
|
|
def test_compare_dso_only(self):
|
|
"""Test only compare shared libraries with --dso-only
|
|
|
|
Use case to test:
|
|
|
|
fedabipkgdiff --dso-only --from fc20 --to fc23 dbus-glib
|
|
"""
|
|
output = self.run_abipkgdiff()
|
|
|
|
expected_rpms = [
|
|
('dbus-glib-0.100.2-2.fc20.i686.rpm',
|
|
'dbus-glib-0.106-1.fc23.i686.rpm'),
|
|
('dbus-glib-0.100.2-2.fc20.x86_64.rpm',
|
|
'dbus-glib-0.106-1.fc23.x86_64.rpm'),
|
|
]
|
|
expected_binaries = ['libdbus-glib-1.so.2.2.2']
|
|
|
|
self.assert_abi_comparison_result(output,
|
|
expected_binaries=expected_binaries,
|
|
expected_rpms=expected_rpms)
|
|
|
|
def test_compare_with_no_devel_pkg(self):
|
|
"""Test compare ABI with and without --no-devel-pkg
|
|
|
|
Use case to test::
|
|
|
|
fedabipkgdiff --no-devel-pkg \
|
|
nss-util-3.12.6-1.fc14 nss-util-3.24.0-2.0.fc25
|
|
|
|
and
|
|
|
|
fedabipkgdiff nss-util-3.12.6-1.fc14 nss-util-3.24.0-2.0.fc25
|
|
"""
|
|
|
|
compared_rpms = [('nss-util-3.12.6-1.fc14.x86_64.rpm',
|
|
'nss-util-3.24.0-2.0.fc25.x86_64.rpm')]
|
|
compared_binaries = ['libnssutil3.so']
|
|
|
|
# Without --no-devel-pkg, abipkgdiff is run with development packages
|
|
# by default. In this case, expected changed will be 5 and expected
|
|
# changed_filtered_out will be 17. Otherwise, with --no-devel-pkg,
|
|
# changed will be 6 and changed_filtered_out will be 16.
|
|
abipkgdiff_cmd_results = (
|
|
(['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'nss-util-3.12.6-1.fc14.x86_64',
|
|
'nss-util-3.24.0-2.0.fc25.x86_64',
|
|
],
|
|
{'compared_rpms': compared_rpms,
|
|
'compared_binaries': compared_binaries,
|
|
'result': {
|
|
'removed': 0,
|
|
'changed': 5,
|
|
'changed_filtered_out': 17,
|
|
'functions_added': 37,
|
|
}
|
|
},
|
|
),
|
|
(['fedabipkgdiff', '--topdir', TEST_TOPDIR,
|
|
'--abipkgdiff', BUILT_ABIPKGDIFF,
|
|
'--no-devel-pkg',
|
|
'nss-util-3.12.6-1.fc14.x86_64',
|
|
'nss-util-3.24.0-2.0.fc25.x86_64',
|
|
],
|
|
{'compared_rpms': compared_rpms,
|
|
'compared_binaries': compared_binaries,
|
|
'result': {
|
|
'removed': 0,
|
|
'changed': 6,
|
|
'changed_filtered_out': 16,
|
|
'functions_added': 37,
|
|
}
|
|
})
|
|
)
|
|
|
|
for abipkgdiff_cmd, compare_result in abipkgdiff_cmd_results:
|
|
with patch('sys.argv', new=abipkgdiff_cmd):
|
|
output = self.run_abipkgdiff()
|
|
|
|
self.assert_abi_comparison_result(
|
|
output,
|
|
expected_rpms=compare_result['compared_rpms'],
|
|
expected_binaries=compare_result['compared_binaries'],
|
|
expected_func_change_summary=compare_result['result'])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|