[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: a new tool fedabipkgdiff



Hello,

Dodji Seketeli <dodji@redhat.com> a Ãcrit:

[...]

>> --- /dev/null
>> +++ b/tests/runtestfedabipkgdiff.sh

[...]

>> @@ -0,0 +1,5 @@
>> +#!/usr/bin/bash
>> +
>> +export FEDABIPKGDIFF_TESTS=1
>> +
>> +../../tools/fedabipkgdiff
>
> Actually, I think the runtestfedabipkgdiff.sh could be a proper python
> script that contains the actual unit tests of fedabipkgdiff, rather than
> having the unit tests be in the fedabipkgdiff file itself.
>
> That file would then load (using the imp.load_source() function from the
> python standard library) by specifying the path to the the fedabipkgdiff
> from the source, so that "make check" uses the fedabipkgdiff from the
> sources and not the one that might already be installed on the
> system. There is a potentially a little bit of autoconf magic to do
> here, but I can help you here for the details.

I finally did it.  I am attaching the patch at the end of this message.
The patch is also available in my "dodji/fedabipkgdiff" branch at https://sourceware.org/git/gitweb.cgi?p=libabigail.git;a=commitdiff;h=246f4f3280d8b96911d4ef2676f0d46ff66b0681

What do you think?

>From 246f4f3280d8b96911d4ef2676f0d46ff66b0681 Mon Sep 17 00:00:00 2001
From: Dodji Seketeli <dodji@redhat.com>
Date: Sat, 20 Feb 2016 12:42:04 +0100
Subject: [PATCH 3/3] Move unit tests from fedabipkgdiff to
 runtestfedabipkgdiff.py

The fedabipkgdiff program used to contain unit tests for many of its
functions.  This patch moves these unit tests out of the
tools/fedabipkgdiff program file, to the IMHO more appropriate
location tests/runtestfedabipkgdiff.py.  The later file starts by
loading the tools/fedabipkgdiff program.  The unit test code it
contains then tests the functions of the program that has just been
loaded.  I believe this separation decreases the clutter of
fedabipkgdiff and thus increases its maintainability.

Note that tests/runtestfedabipkgdiff.py is now generated by autoconf
inside the build directory.  To do that, autoconf takes the pattern
file tests/runtestfedabipkgdiff.py.in from the source directory and
replaces variables like @top_srcdir@ by their actual value.  The
result is a tests/runtestfedabipkgdiff.py file which is a proper
executable python program that is executed when the user invokes the
standard "make check" command from the build directory.  Of course,
parallel checking still works too, by doing "make -j8 check" if your
system has eight cores, for instance.

The patch passes "make distcheck" too.

	* configure.ac: Add check for prerequisite python modules
	itertools, shutil, unittest and mock.  These are necessary for the
	unit test of fedabipkgdiff.  Generate
	tests/runtestfedabipkgdiff.py into the build directory, from the
	tests/runtestfedabipkgdiff.py.in input file.
	* tests/Makefile.am: Rename runtestfedabipkgdiff.sh into
	runtestfedabipkgdiff.py.  Add the new runtestfedabipkgdiff.py.in
	autoconf template file in here.
	* tests/runtestfedabipkgdiff.py.in: New unit test file.
	* tests/runtestfedabipkgdiff.sh: Remove.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 configure.ac                     |   9 +-
 tests/Makefile.am                |   8 +-
 tests/runtestfedabipkgdiff.py.in | 335 +++++++++++++++++++++++++++++++++++++++
 tests/runtestfedabipkgdiff.sh    |   5 -
 4 files changed, 347 insertions(+), 10 deletions(-)
 create mode 100755 tests/runtestfedabipkgdiff.py.in
 delete mode 100755 tests/runtestfedabipkgdiff.sh

diff --git a/configure.ac b/configure.ac
index 687a2ca..17bfe30 100644
--- a/configure.ac
+++ b/configure.ac
@@ -285,7 +285,11 @@ if test x$CHECK_DEPS_FOR_FEDABIPKGDIFF = xyes; then
   AX_PYTHON_MODULE(sys, $FATAL, python2)
   AX_PYTHON_MODULE(itertools, $FATAL, python2)
   AX_PYTHON_MODULE(urlparse, $FATAL, python2)
+  AX_PYTHON_MODULE(itertools, $FATAL, python2)
+  AX_PYTHON_MODULE(shutil, $FATAL, python2)
+  AX_PYTHON_MODULE(unittest, $FATAL, python2)
   AX_PYTHON_MODULE(koji, $FATAL, python2)
+  AX_PYTHON_MODULE(mock, $FATAL, python2)
   ENABLE_FEDABIPKGDIFF=yes
 
   if test x$ENABLE_FEDABIPKGDIFF != xyes; then
@@ -437,7 +441,10 @@ libabigail.pc
     bash-completion/Makefile])
 
 dnl Some test scripts are generated by autofoo.
-AC_CONFIG_FILES([tests/runtestcanonicalizetypes.sh], [chmod +x tests/runtestcanonicalizetypes.sh])
+AC_CONFIG_FILES([tests/runtestcanonicalizetypes.sh],
+		[chmod +x tests/runtestcanonicalizetypes.sh])
+AC_CONFIG_FILES([tests/runtestfedabipkgdiff.py],
+		[chmod +x tests/runtestfedabipkgdiff.py])
 
 AC_OUTPUT
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 958995c..953dfef 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -31,10 +31,10 @@ runtestlookupsyms		\
 runtestaltdwarf			\
 runtestcorediff			\
 runtestabidiffexit		\
-runtestfedabipkgdiff.sh		\
+runtestfedabipkgdiff.py		\
 $(CXX11_TESTS)
 
-EXTRA_DIST = runtestcanonicalizetypes.sh.in
+EXTRA_DIST = runtestcanonicalizetypes.sh.in runtestfedabipkgdiff.py.in
 CLEANFILES = \
  runtestcanonicalizetypes.output.txt \
  runtestcanonicalizetypes.output.final.txt
@@ -115,8 +115,8 @@ printdifftree_LDADD = $(top_builddir)/src/libabigail.la
 runtestcanonicalizetypes_sh_SOURCES =
 runtestcanonicalizetypes.sh$(EXEEXT):
 
-runtestfedabipkgdiff_sh_SOURCES =
-runtestfedabipkgdiff.sh$(EXEEXT):
+runtestfedabipkgdiff_py_SOURCES =
+runtestfedabipkgdiff.py$(EXEEXT):
 
 AM_CPPFLAGS=-I${abs_top_srcdir}/include \
 -I${abs_top_builddir}/include -I${abs_top_srcdir}/tools -fPIC
diff --git a/tests/runtestfedabipkgdiff.py.in b/tests/runtestfedabipkgdiff.py.in
new file mode 100755
index 0000000..7842cc9
--- /dev/null
+++ b/tests/runtestfedabipkgdiff.py.in
@@ -0,0 +1,335 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# -*- Mode: Python
+#
+# This file is part of the GNU Application Binary Interface Generic
+# Analysis and Instrumentation Library.  This program 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 program 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 Lesser Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; see the file COPYING-LGPLV3.  If
+# not, see <http://www.gnu.org/licenses/>.
+# 
+# Author: Chenxiong Qi
+
+import os
+import itertools
+import shutil
+import unittest
+
+try:
+    from mock import patch
+except ImportError:
+    print >>sys.stderr, \
+        'mock is not installed. Please install it before running tests.'
+    sys.exit(1)
+
+import imp
+# Import the fedabipkgdiff program file from the source directory.
+fedabidiff_mod = imp.load_source('fedabidiff',
+                                 '@top_srcdir@/tools/fedabipkgdiff')
+
+counter = itertools.count(0)
+
+class UtilsTest(unittest.TestCase):
+
+    def test_is_fedora_distro(self):
+        distro = 'fc5'
+        self.assertTrue(fedabidiff_mod.is_fedora_distro(distro))
+
+        distro = 'f5'
+        self.assertFalse(fedabidiff_mod.is_fedora_distro(distro))
+
+        distro = 'fc23'
+        self.assertTrue(fedabidiff_mod.is_fedora_distro(distro))
+
+        distro = 'fc'
+        self.assertFalse(fedabidiff_mod.is_fedora_distro(distro))
+
+        distro = 'fc234'
+        self.assertFalse(fedabidiff_mod.is_fedora_distro(distro))
+
+
+class RunAbipkgdiffTest(unittest.TestCase):
+    """Test case for method run_abipkgdiff"""
+
+    def setUp(self):
+        self.pkg1_single_info = {
+            'i686': [{'downloaded_rpm_file': 'dummy file path'},
+                     {'downloaded_rpm_file': 'dummy file path'}],
+            }
+
+        self.pkg2_single_info = {
+            'i686': [{'downloaded_rpm_file': 'dummy file path'},
+                     {'downloaded_rpm_file': 'dummy file path'}],
+            }
+
+        self.pkg1_infos = {
+            'i686': [{'downloaded_rpm_file': 'dummy file path'},
+                     {'downloaded_rpm_file': 'dummy file path'}],
+            'x86_64': [{'downloaded_rpm_file': 'dummy file path'},
+                       {'downloaded_rpm_file': 'dummy file path'}],
+            'armv7hl': [{'downloaded_rpm_file': 'dummy file path'},
+                        {'downloaded_rpm_file': 'dummy file path'}],
+            }
+
+        self.pkg2_infos = {
+            'i686': [{'downloaded_rpm_file': 'dummy file path'},
+                     {'downloaded_rpm_file': 'dummy file path'}],
+            'x86_64': [{'downloaded_rpm_file': 'dummy file path'},
+                       {'downloaded_rpm_file': 'dummy file path'}],
+            'armv7hl': [{'downloaded_rpm_file': 'dummy file path'},
+                        {'downloaded_rpm_file': 'dummy file path'}],
+            }
+
+    @patch('fedabidiff.abipkgdiff')
+    def test_all_success(self, mock_abipkgdiff):
+        mock_abipkgdiff.return_value = 0
+
+        result = fedabidiff_mod.run_abipkgdiff(self.pkg1_single_info,
+                                       self.pkg2_single_info)
+        self.assertEquals(0, result)
+
+        result = fedabidiff_mod.run_abipkgdiff(self.pkg1_infos, self.pkg2_infos)
+        self.assertEquals(0, result)
+
+    @patch('fedabidiff.abipkgdiff')
+    def test_all_failure(self, mock_abipkgdiff):
+        mock_abipkgdiff.return_value = 4
+
+        result = fedabidiff_mod.run_abipkgdiff(self.pkg1_single_info,
+                                       self.pkg2_single_info)
+        self.assertEquals(4, result)
+
+        result = fedabidiff_mod.run_abipkgdiff(self.pkg1_infos, self.pkg2_infos)
+        self.assertEquals(4, result)
+
+    @patch('fedabidiff.abipkgdiff', new=lambda param1, param2: counter.next())
+    def test_partial_failure(self):
+        result = fedabidiff_mod.run_abipkgdiff(self.pkg1_infos, self.pkg2_infos)
+        self.assertTrue(result > 0)
+
+
+fake_rpm_file = 'foo-0.1-1.fc24.x86_64.rpm'
+fake_debuginfo_rpm_file = 'foo-debuginfo-0.1-1.fc24.x86_64.rpm'
+
+
+class MockGlobalConfig(object):
+    koji_server = fedabidiff_mod.DEFAULT_KOJI_SERVER
+
+
+def mock_get_session():
+    return MockKojiClientSession(baseurl=fedabidiff_mod.DEFAULT_KOJI_SERVER)
+
+
+class MockKojiClientSession(object):
+
+    def __init__(self, *args, **kwargs):
+        """Accept arbitrary parameters but do nothing for this mock"""
+        self.args = args
+        self.kwargs = kwargs
+
+    def getPackage(self, *args, **kwargs):
+        return {
+            'id': 1,
+            'name': 'whatever a name of a package',
+        }
+
+    def listRPMs(self, *args, **kwargs):
+        return [{'arch': 'i686',
+                 'name': 'httpd-debuginfo',
+                 'nvr': 'httpd-debuginfo-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'},
+                {'arch': 'i686',
+                 'name': 'mod_session',
+                 'nvr': 'mod_session-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'},
+                {'arch': 'i686',
+                 'name': 'httpd',
+                 'nvr': 'httpd-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'},
+                {'arch': 'i686',
+                 'name': 'mod_proxy_html',
+                 'nvr': 'mod_proxy_html-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'},
+                {'arch': 'i686',
+                 'name': 'mod_ldap',
+                 'nvr': 'mod_ldap-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'},
+                {'arch': 'i686',
+                 'name': 'mod_ssl',
+                 'nvr': 'mod_ssl-2.4.18-1.fc22',
+                 'release': '1.fc22',
+                 'version': '2.4.18'}]
+
+    def listBuilds(self, *args, **kwargs):
+        return [
+            {'build_id': 720222,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.18-2.fc24',
+             'release': '2.fc24',
+             'version': '2.4.18'},
+            {'build_id': 708769,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.18-1.fc22',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            {'build_id': 708711,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.18-1.fc23',
+             'release': '1.fc23',
+             'version': '2.4.18'},
+            {'build_id': 705335,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.18-1.fc24',
+             'release': '1.fc24',
+             'version': '2.4.18'},
+            {'build_id': 704434,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.17-4.fc24',
+             'release': '4.fc24',
+             'version': '2.4.17'},
+            {'build_id': 704433,
+             'name': 'httpd',
+             'nvr': 'httpd-2.4.17-4.fc23',
+             'release': '4.fc23',
+             'version': '2.4.17'},
+        ]
+
+
+class SelectRpmsFromABuildTest(unittest.TestCase):
+    """Test case for select_rpms_from_a_build"""
+
+    def assert_rpms(self, rpms):
+        for item in rpms:
+            self.assertTrue(item['arch'] in ['i686', 'x86_64'])
+            self.assertTrue(item['name'] in ('httpd', 'httpd-debuginfo'))
+
+    @patch('fedabidiff.Brew.listRPMs')
+    @patch('fedabidiff.global_config', new=MockGlobalConfig)
+    def test_select_rpms_from_all_arches(self, mock_listRPMs):
+        mock_listRPMs.return_value = [
+            {'arch': 'i686',
+             'name': 'httpd-debuginfo',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            {'arch': 'i686',
+             'name': 'httpd',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            {'arch': 'x86_64',
+             'name': 'httpd-debuginfo',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            {'arch': 'x86_64',
+             'name': 'httpd',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            ]
+
+        session = fedabidiff_mod.get_session()
+        rpms = session.select_rpms_from_a_build(1, 'httpd')
+        self.assert_rpms(rpms)
+
+    @patch('fedabidiff.Brew.listRPMs')
+    @patch('fedabidiff.global_config', new=MockGlobalConfig)
+    def test_select_rpms_from_one_arch(self, mock_listRPMs):
+        mock_listRPMs.return_value = [
+            {'arch': 'i686',
+             'name': 'httpd-debuginfo',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            {'arch': 'i686',
+             'name': 'httpd',
+             'release': '1.fc22',
+             'version': '2.4.18'},
+            ]
+
+        session = fedabidiff_mod.get_session()
+        rpms = session.select_rpms_from_a_build(1, 'httpd')
+        self.assert_rpms(rpms)
+
+
+class GetPackageLatestBuildTest(unittest.TestCase):
+    """Test case for get_package_latest_build"""
+
+    @patch('fedabidiff.global_config', new=MockGlobalConfig)
+    @patch('koji.ClientSession', new=MockKojiClientSession)
+    def test_get_latest_one(self):
+        session = fedabidiff_mod.get_session()
+        build = session.get_package_latest_build('httpd', 'fc23')
+        self.assertEquals('httpd-2.4.18-1.fc23', build['nvr'])
+
+    @patch('fedabidiff.global_config', new=MockGlobalConfig)
+    @patch('koji.ClientSession', new=MockKojiClientSession)
+    def test_fail_to_find_latest_build(self):
+        session = fedabidiff_mod.get_session()
+        latest_build = session.get_package_latest_build('httpd', 'xxxx')
+        self.assertEquals(None, latest_build)
+
+
+class BrewListRPMsTest(unittest.TestCase):
+    """Test case for Brew.listRPMs"""
+
+    @patch('fedabidiff.global_config', new=MockGlobalConfig)
+    @patch('fedabidiff.koji.ClientSession', new=MockKojiClientSession)
+    def test_select_specific_rpms(self):
+        session = fedabidiff_mod.get_session()
+        selector = lambda rpm: rpm['name'].startswith('httpd')
+        rpms = session.listRPMs(buildID=1000, selector=selector)
+        self.assertTrue(
+            len(rpms) > 0,
+            'More than one rpms should be selected. But, it\'s empty.')
+        for rpm in rpms:
+            self.assertTrue(rpm['name'] in ('httpd', 'httpd-debuginfo'),
+                            '{0} should not be selected'.format(rpm['name']))
+
+
+class FindLocalDebuginfoRPMTest(unittest.TestCase):
+    """Test case for find_local_debuginfo_rpm"""
+
+    def setUp(self):
+        # FIXME: is it possible to patch glob or the underlying methods glob
+        # depends on
+        self.test_dir = './test_dir'
+        os.makedirs(self.test_dir)
+        os.system('touch {0}'.format(
+            os.path.join(self.test_dir, fake_debuginfo_rpm_file)))
+        os.system('touch {0}'.format(
+            os.path.join(self.test_dir,
+                         fake_debuginfo_rpm_file.replace('foo', 'another'))))
+
+    def tearDown(self):
+        shutil.rmtree(self.test_dir)
+
+    def test_find_debuginfo_rpm(self):
+        debuginfo_rpm = fedabidiff_mod.find_local_debuginfo_rpm(
+            os.path.join(self.test_dir, fake_rpm_file))
+
+        expected_debuginfo_rpm_file = os.path.abspath(
+            os.path.join(self.test_dir,
+                         fake_debuginfo_rpm_file))
+        self.assertEquals(expected_debuginfo_rpm_file, debuginfo_rpm)
+
+    def test_no_suitable_debuginfo_rpm(self):
+        debuginfo_rpm = fedabidiff_mod.find_local_debuginfo_rpm(
+            os.path.join(self.test_dir, 'abc-0.1-1.i686.rpm'))
+        self.assertEquals(None, debuginfo_rpm)
+
+
+invoked_from_cmd = __name__ == '__main__'
+
+if invoked_from_cmd:
+    unittest.main()
diff --git a/tests/runtestfedabipkgdiff.sh b/tests/runtestfedabipkgdiff.sh
deleted file mode 100755
index 4144419..0000000
--- a/tests/runtestfedabipkgdiff.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/bash
-
-export FEDABIPKGDIFF_TESTS=1
-
-../../tools/fedabipkgdiff
\ No newline at end of file
-- 
1.8.3.1

-- 
		Dodji