From cc16c18311b9d0e3eb5abba59d48dbc93a6fe651 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Feb 11 2018 02:00:06 +0000
Subject: [PATCH 1/2] Drop rpmfluff in test


rpmfluff builds packages inside base_dir returned from get_base_dir.
This causes TestImportSrpm fails when run with detox or other ways in
parallel. This patch drops rpmfluff and builds SRPM for that test
directly with rpmbuild.

Relates: #288

Signed-off-by: Chenxiong Qi <cqi@redhat.com>

---

diff --git a/tests/fixtures/docpkg/docpkg.spec b/tests/fixtures/docpkg/docpkg.spec
new file mode 100644
index 0000000..e317fc7
--- /dev/null
+++ b/tests/fixtures/docpkg/docpkg.spec
@@ -0,0 +1,38 @@
+# autogenerated specfile
+Summary: Dummy summary
+Name: docpkg
+Version: 0.2
+Release: 1%{?dist}
+License: GPL
+Group: Applications/Productivity
+
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+Source0: hello-world.txt
+Source1: docpkg.tar.gz
+
+%description
+This is a dummy description.
+
+%prep
+cp %{SOURCE0} .
+
+%build
+
+%clean
+rm -rf $$RPM_BUILD_ROOT
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc
+cp %{SOURCE0} $RPM_BUILD_ROOT/usr/share/doc/hello-world.txt
+
+%files
+%doc "/usr/share/doc/hello-world.txt"
+
+%changelog
+* Sun Jan  1 2006 tester <tester@example.com> - 0.2-1
+- - New release 0.2-1
+
+* Sun Jan  1 2006 John Doe <jdoe@example.com> - 0.2-1
+- Initial version
+
diff --git a/tests/fixtures/docpkg/docpkg.tar.gz b/tests/fixtures/docpkg/docpkg.tar.gz
new file mode 100644
index 0000000..05c2e14
Binary files /dev/null and b/tests/fixtures/docpkg/docpkg.tar.gz differ
diff --git a/tests/fixtures/docpkg/hello-world.txt b/tests/fixtures/docpkg/hello-world.txt
new file mode 100644
index 0000000..3b18e51
--- /dev/null
+++ b/tests/fixtures/docpkg/hello-world.txt
@@ -0,0 +1 @@
+hello world
diff --git a/tests/test_cli.py b/tests/test_cli.py
index fb95e5c..a35a29f 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1,13 +1,8 @@
 # -*- coding: utf-8 -*-
 
-import gzip
 import hashlib
 import logging
 import os
-try:
-    import rpmfluff
-except ImportError:
-    rpmfluff = None
 import shutil
 import six
 import subprocess
@@ -37,8 +32,9 @@ from pyrpkg import rpkgError, Commands
 from utils import CommandTestCase
 
 
+fixtures_dir = os.path.join(os.path.dirname(__file__), 'fixtures')
 # rpkg.conf for running tests below
-config_file = os.path.join(os.path.dirname(__file__), 'fixtures', 'rpkg.conf')
+config_file = os.path.join(fixtures_dir, 'rpkg.conf')
 
 fake_spec_content = '''
 Summary: package demo
@@ -994,8 +990,8 @@ class LookasideCacheMock(object):
     def lookasidecache_upload(self, module_name, filepath, hash):
         filename = os.path.basename(filepath)
         storage_filename = os.path.join(self.lookasidecache_storage, filename)
-        with open(storage_filename, 'w') as fout:
-            with open(filepath, 'r') as fin:
+        with open(storage_filename, 'wb') as fout:
+            with open(filepath, 'rb') as fin:
                 fout.write(fin.read())
 
     def lookasidecache_download(self, name, filename, hash, outfile, hashtype=None, **kwargs):
@@ -1004,10 +1000,8 @@ class LookasideCacheMock(object):
 
     def hash_file(self, filename):
         md5 = hashlib.md5()
-        with open(filename, 'r') as f:
+        with open(filename, 'rb') as f:
             content = f.read()
-            if six.PY3:
-                content = content.encode('utf-8')
             md5.update(content)
         return md5.hexdigest()
 
@@ -1154,30 +1148,36 @@ class TestFailureImportSrpm(CliTestCase):
                 self.fail('import_srpm should fail if package repository is dirty.')
 
 
-@unittest.skipUnless(rpmfluff, 'rpmfluff is not available')
 class TestImportSrpm(LookasideCacheMock, CliTestCase):
 
+    @staticmethod
+    def build_srpm(srcrpmdir):
+        """Build a fake SRPM used by this test case"""
+        docpkg_dir = os.path.join(fixtures_dir, 'docpkg')
+        specfile = os.path.join(docpkg_dir, 'docpkg.spec')
+        rpmbuild = [
+            'rpmbuild', '-bs',
+            '--define', '_topdir {0}'.format(srcrpmdir),
+            '--define', '_builddir {0}'.format(srcrpmdir),
+            '--define', '_sourcedir {0}'.format(docpkg_dir),
+            '--define', '_specdir {0}'.format(docpkg_dir),
+            specfile
+        ]
+        proc = subprocess.Popen(
+            rpmbuild, stdout=subprocess.PIPE, universal_newlines=True)
+        stdout, _ = proc.communicate()
+        if proc.returncode > 0:
+            raise rpkgError('Failed to build SRPM for test case {0}'.format(
+                TestImportSrpm.__name__))
+        _, filename = stdout.split()
+        return filename.strip()
+
     def setUp(self):
         super(TestImportSrpm, self).setUp()
         self.init_lookaside_cache()
 
-        # Gzip file that will be added into the SRPM
-        self.docpkg_gz = os.path.join(self.cloned_repo_path, 'docpkg.gz')
-        gzf = gzip.open(self.docpkg_gz, 'w')
-        gzf.write(b'file content of docpkg')
-        gzf.close()
-
-        # Build the SRPM
-        self.build = rpmfluff.SimpleRpmBuild(name='docpkg', version='0.2', release='1')
-        self.build.add_changelog_entry('- New release 0.2-1', version='0.2', release='1',
-                                       nameStr='tester <tester@example.com>')
-        self.build.add_simple_payload_file()
-        content = gzip.open(self.docpkg_gz, 'r').read()
-        if six.PY3:
-            content = str(content, encoding='utf-8')
-        self.build.add_source(rpmfluff.SourceFile('docpkg.gz', content))
-        self.build.make()
-        self.srpm_file = self.build.get_built_srpm()
+        self.srcrpmdir = tempfile.mkdtemp(prefix='test-import-srpm-topdir-')
+        self.srpm_file = TestImportSrpm.build_srpm(self.srcrpmdir)
 
         self.chaos_repo = tempfile.mkdtemp(prefix='rpkg-tests-chaos-repo-')
         cmds = (
@@ -1193,8 +1193,7 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
     def tearDown(self):
-        os.remove(self.docpkg_gz)
-        shutil.rmtree(self.build.get_base_dir())
+        shutil.rmtree(self.srcrpmdir)
         shutil.rmtree(self.chaos_repo)
         self.destroy_lookaside_cache()
         super(TestImportSrpm, self).tearDown()
@@ -1208,7 +1207,7 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
             with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
                 cli.import_srpm()
 
-        docpkg_gz = os.path.basename(self.docpkg_gz)
+        docpkg_gz = 'docpkg.tar.gz'
         diff_cached = cli.cmd.repo.git.diff('--cached')
         self.assertTrue('+- - New release 0.2-1' in diff_cached)
         self.assertTrue('+hello world' in diff_cached)

From a35132be037dd6db4d0ccded73eb485cb00f8780 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Feb 12 2018 04:36:22 +0000
Subject: [PATCH 2/2] Mock ThreadPool in test_module_overview


Signed-off-by: Chenxiong Qi <cqi@redhat.com>

---

diff --git a/tests/test_cli.py b/tests/test_cli.py
index a35a29f..135b25e 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -29,7 +29,7 @@ except ImportError:
 import utils
 from mock import PropertyMock, call, mock_open, patch, Mock
 from pyrpkg import rpkgError, Commands
-from utils import CommandTestCase
+from utils import CommandTestCase, FakeThreadPool
 
 
 fixtures_dir = os.path.join(os.path.dirname(__file__), 'fixtures')
@@ -2020,6 +2020,7 @@ torsava's build #2150 of python3-ecosystem-master is in the "failed" state (reas
 
     @patch('sys.stdout', new=StringIO())
     @patch('requests.get')
+    @patch('pyrpkg.ThreadPool', new=FakeThreadPool)
     def test_module_overview(self, mock_get):
         """
         Test the module overview command with 4 modules in the finished state
@@ -2099,6 +2100,7 @@ torsava's build #2150 of python3-ecosystem-master is in the "failed" state (reas
         mock_rv.ok = True
         mock_rv.json.side_effect = [json_one, json_two, json_three]
         mock_get.return_value = mock_rv
+
         with patch('sys.argv', new=cli_cmd):
             cli = self.new_cli()
             cli.module_overview()
diff --git a/tests/utils.py b/tests/utils.py
index 46c2b79..5a4ac91 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -220,3 +220,13 @@ class CommandTestCase(Assertions, Utils, unittest.TestCase):
             return sorted((line.strip() for line in buf))
         finally:
             buf.close()
+
+
+class FakeThreadPool(object):
+    """Fake thread pool to run functions sequentially"""
+
+    def __init__(self, processes):
+        self.processes = processes
+
+    def map(self, func, iterable):
+        return [func(item) for item in iterable]

