From 776d53d576ff0736162beb7014a3c7985253069d Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:06:32 +0000
Subject: [PATCH 1/6] Suppress output from git command within setUp


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

---

diff --git a/tests/test_cli.py b/tests/test_cli.py
index c16656c..c02effa 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -10,6 +10,7 @@ except ImportError:
     rpmfluff = None
 import shutil
 import six
+import subprocess
 import sys
 import tempfile
 try:
@@ -75,7 +76,8 @@ class CliTestCase(CommandTestCase):
             cmds.append(['git', 'commit', '-m', 'Add new file {0}'.format(_filename)])
 
         for cmd in cmds:
-            self.run_cmd(cmd, cwd=repo_path)
+            self.run_cmd(cmd, cwd=repo_path,
+                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
 
 class TestModuleNameOption(CliTestCase):
@@ -347,7 +349,7 @@ class TestCommit(CliTestCase):
 
     def test_with_clog(self):
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'commit', '--clog']
-
+        
         with patch('sys.argv', new=cli_cmd):
             self.cli_commit()
 
@@ -891,8 +893,12 @@ class TestNew(CliTestCase):
 
     @patch('sys.stdout', new=StringIO())
     def test_get_diff(self):
-        self.run_cmd(['git', 'tag', '-m', 'New release v0.1', 'v0.1'], cwd=self.cloned_repo_path)
-        self.make_changes(repo=self.cloned_repo_path, commit=True, content='New change')
+        self.run_cmd(['git', 'tag', '-m', 'New release v0.1', 'v0.1'],
+                     cwd=self.cloned_repo_path,
+                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        self.make_changes(repo=self.cloned_repo_path,
+                          commit=True,
+                          content='New change')
 
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'new']
 
@@ -927,7 +933,9 @@ class TestNewPrintUnicode(CliTestCase):
 
     def setUp(self):
         super(TestNewPrintUnicode, self).setUp()
-        self.run_cmd(['git', 'tag', '-m', 'New release 0.1', '0.1'], cwd=self.cloned_repo_path)
+        self.run_cmd(['git', 'tag', '-m', 'New release 0.1', '0.1'],
+                     cwd=self.cloned_repo_path,
+                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         self.make_a_dummy_commit(git.Repo(self.cloned_repo_path),
                                  file_content='Include unicode chars á ř',
                                  commit_message=u'Write unicode to file')
@@ -1149,7 +1157,8 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
             ['git', 'commit', '-m', '"Add README"'],
         )
         for cmd in cmds:
-            self.run_cmd(cmd, cwd=self.chaos_repo)
+            self.run_cmd(cmd, cwd=self.chaos_repo,
+                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
     def tearDown(self):
         os.remove(self.docpkg_gz)
diff --git a/tests/test_commands.py b/tests/test_commands.py
index 2f8fe05..0dbefaa 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -3,6 +3,7 @@
 import os
 import shutil
 import six
+import subprocess
 import tempfile
 
 import git
@@ -560,7 +561,7 @@ class TestLoadModuleNameFromSpecialPushURL(CommandTestCase):
 
         self.case_repo = tempfile.mkdtemp(prefix='case-test-load-module-name-')
         cmd = ['git', 'clone', '{0}/'.format(self.repo_path), self.case_repo]
-        self.run_cmd(cmd)
+        self.run_cmd(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
     def tearDown(self):
         shutil.rmtree(self.case_repo)
diff --git a/tests/utils.py b/tests/utils.py
index 452219a..e805bd1 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -136,11 +136,13 @@ class CommandTestCase(Assertions, Utils, unittest.TestCase):
             ['git', 'branch', 'rhel-7'],
             ]
         for cmd in git_cmds:
-            self.run_cmd(cmd, cwd=self.repo_path)
+            self.run_cmd(cmd, cwd=self.repo_path,
+                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
         # Clone the repo
         self.cloned_repo_path = tempfile.mkdtemp(prefix='rpkg-commands-tests-cloned-')
-        self.run_cmd(['git', 'clone', self.repo_path, self.cloned_repo_path])
+        self.run_cmd(['git', 'clone', self.repo_path, self.cloned_repo_path],
+                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         git_cmds = [
             ['git', 'config', 'user.email', 'tester@example.com'],
             ['git', 'config', 'user.name', 'tester'],
@@ -149,7 +151,8 @@ class CommandTestCase(Assertions, Utils, unittest.TestCase):
             ['git', 'branch', '--track', 'eng-rhel-7', 'origin/eng-rhel-7'],
             ]
         for cmd in git_cmds:
-            self.run_cmd(cmd, cwd=self.cloned_repo_path)
+            self.run_cmd(cmd, cwd=self.cloned_repo_path,
+                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
     def tearDown(self):
         shutil.rmtree(self.repo_path)

From 82332efeb62cc779bfdf95a2fc07a7880810a2c0 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:06:32 +0000
Subject: [PATCH 2/6] Test for container-build to use custom config


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

---

diff --git a/tests/fixtures/rpkg-container-own-config.conf b/tests/fixtures/rpkg-container-own-config.conf
new file mode 100644
index 0000000..f81c696
--- /dev/null
+++ b/tests/fixtures/rpkg-container-own-config.conf
@@ -0,0 +1,15 @@
+[rpkg]
+lookaside = http://localhost/repo/pkgs
+lookasidehash = md5
+lookaside_cgi = https://localhost/repo/pkgs/upload.cgi
+gitbaseurl = ssh://%(user)s@localhost/%(module)s
+anongiturl = git://localhost/%(module)s
+branchre = f\d$|f\d\d$|el\d$|olpc\d$|master$
+kojiprofile = koji
+build_client = koji
+clone_config =
+  bz.default-component %(module)s
+
+[rpkg.container-build]
+kojiprofile = koji-container
+build_client = koji
diff --git a/tests/test_cli.py b/tests/test_cli.py
index c02effa..e87067e 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -175,17 +175,24 @@ class TestContainerBuildWithKoji(CliTestCase):
     def setUp(self):
         super(TestContainerBuildWithKoji, self).setUp()
         self.checkout_branch(git.Repo(self.cloned_repo_path), 'eng-rhel-7')
+        self.container_build_koji_patcher = patch(
+            'pyrpkg.Commands.container_build_koji')
+        self.mock_container_build_koji = \
+            self.container_build_koji_patcher.start()
 
-    @patch('pyrpkg.Commands.container_build_koji')
-    def test_using_kojiprofile(self, container_build_koji):
+    def tearDown(self):
+        self.mock_container_build_koji.stop()
+        super(TestContainerBuildWithKoji, self).tearDown()
+
+    def test_using_kojiprofile(self):
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
                    'container-build']
 
         with patch('sys.argv', new=cli_cmd):
             cli = self.new_cli()
-            cli.container_build()
+            cli.container_build_koji()
 
-        container_build_koji.assert_called_once_with(
+        self.mock_container_build_koji.assert_called_once_with(
             False,
             opts={
                 'scratch': False,
@@ -201,17 +208,16 @@ class TestContainerBuildWithKoji(CliTestCase):
             nowait=False
         )
 
-    @patch('pyrpkg.Commands.container_build_koji')
-    def test_override_target(self, container_build_koji):
+    def test_override_target(self):
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'container-build',
                    '--target', 'f25-docker-candidate']
 
         with patch('sys.argv', new=cli_cmd):
             cli = self.new_cli()
-            cli.container_build()
+            cli.container_build_koji()
 
         self.assertEqual('f25-docker-candidate', cli.cmd._target)
-        container_build_koji.assert_called_once_with(
+        self.mock_container_build_koji.assert_called_once_with(
             True,
             opts={
                 'scratch': False,
@@ -227,8 +233,7 @@ class TestContainerBuildWithKoji(CliTestCase):
             nowait=False
         )
 
-    @patch('pyrpkg.Commands.container_build_koji')
-    def test_using_deprecated_kojiconfig(self, container_build_koji):
+    def test_using_deprecated_kojiconfig(self):
         """test_build_using_deprecated_kojiconfig
 
         This is for ensuring container_build works with deprecated kojiconfig.
@@ -244,9 +249,9 @@ class TestContainerBuildWithKoji(CliTestCase):
 
         with patch('sys.argv', new=cli_cmd):
             cli = self.new_cli(cfg_file)
-            cli.container_build()
+            cli.container_build_koji()
 
-        container_build_koji.assert_called_once_with(
+        self.mock_container_build_koji.assert_called_once_with(
             False,
             opts={
                 'scratch': False,
@@ -262,6 +267,21 @@ class TestContainerBuildWithKoji(CliTestCase):
             nowait=False
         )
 
+    def test_use_container_build_own_config(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'container-build']
+        cfg_file = os.path.join(os.path.dirname(__file__),
+                                'fixtures',
+                                'rpkg-container-own-config.conf')
+
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli(cfg_file)
+            cli.container_build_koji()
+
+        args, kwargs = self.mock_container_build_koji.call_args
+        self.assertEqual('koji-container', kwargs['kojiprofile'])
+        self.assertEqual('koji', kwargs['build_client'])
+
 
 class TestClog(CliTestCase):
 

From f68a0eb4209c9d859638bc694f8def179742751b Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:06:32 +0000
Subject: [PATCH 3/6] Tests for container-build-setup command


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

---

diff --git a/tests/test_cli.py b/tests/test_cli.py
index e87067e..21b5147 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1434,3 +1434,79 @@ class TestMockConfig(CliTestCase):
         args, kwargs = self.mock_genMockConfig.call_args
         self.assertEqual('f26-candidate-i686', args[0])
         self.assertEqual('i686', args[1])
+
+
+class TestContainerBuildSetup(CliTestCase):
+    """Test container-build-setup command"""
+
+    def setUp(self):
+        super(TestContainerBuildSetup, self).setUp()
+
+        self.osbs_repo_config = os.path.join(self.cloned_repo_path,
+                                             '.osbs-repo-config')
+        self.write_file(self.osbs_repo_config, '''[autorebuild]
+enabled = True
+''')
+
+        self.log_patcher = patch.object(pyrpkg, 'log')
+        self.mock_log = self.log_patcher.start()
+
+    def tearDown(self):
+        if os.path.exists(self.osbs_repo_config):
+            os.unlink(self.osbs_repo_config)
+        self.mock_log.stop()
+        super(TestContainerBuildSetup, self).tearDown()
+
+    def test_get_autorebuild_when_config_file_not_exists(self):
+        os.unlink(self.osbs_repo_config)
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'container-build-setup', '--get-autorebuild']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            cli.container_build_setup()
+
+        self.mock_log.info.assert_called_once_with('false')
+
+    def test_get_autorebuild_from_config_file(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'container-build-setup', '--get-autorebuild']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            cli.container_build_setup()
+
+        self.mock_log.info.assert_called_once_with('true')
+
+    def test_set_autorebuild_by_creating_config_file(self):
+        os.unlink(self.osbs_repo_config)
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'container-build-setup', '--set-autorebuild', 'true']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            with patch('pyrpkg.Commands.repo',
+                       new_callable=PropertyMock) as repo:
+                cli.container_build_setup()
+
+                repo.return_value.index.add.assert_called_once_with(
+                    [self.osbs_repo_config])
+
+        repo_config = self.read_file(self.osbs_repo_config).strip()
+        self.assertEqual('''[autorebuild]
+enabled = true''', repo_config)
+
+    def test_set_autorebuild_in_existing_config_file(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'container-build-setup', '--set-autorebuild', 'false']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            with patch('pyrpkg.Commands.repo',
+                       new_callable=PropertyMock) as repo:
+                cli.container_build_setup()
+
+                repo.return_value.index.add.assert_called_once_with(
+                    [self.osbs_repo_config])
+
+        repo_config = self.read_file(self.osbs_repo_config).strip()
+        self.assertEqual('''[autorebuild]
+enabled = false''', repo_config)

From 010aa198aedbcce38dcaae8a43d7160d2cb72ed5 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:06:32 +0000
Subject: [PATCH 4/6] More tests for getting spec file


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

---

diff --git a/tests/test_commands.py b/tests/test_commands.py
index 0dbefaa..1f583d6 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -372,6 +372,16 @@ class TestProperties(CommandTestCase):
         cmd = self.make_commands()
         self.assertEqual('docpkg.spec', cmd.spec)
 
+    def test_no_spec_as_it_is_deadpackage(self):
+        with patch('os.listdir', return_value=['dead.package']):
+            cmd = self.make_commands()
+            self.assertRaises(rpkgError, cmd.load_spec)
+
+    def test_no_spec_there(self):
+        with patch('os.listdir', return_value=['anyfile']):
+            cmd = self.make_commands()
+            self.assertRaises(rpkgError, cmd.load_spec)
+
     def test_nvr(self):
         cmd = self.make_commands(dist='eng-rhel-6')
 

From b0e48dff646d391bc087c0a0da61944a42e77438 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:10:35 +0000
Subject: [PATCH 5/6] More Tests for mockbuild command


Also fix an issue that is keep silient when removing a non-existing
directory, which uses wrong errno.EEXIST, instead of errno.ENOENT should
be used.

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

---

diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
index 56fd9b4..017b545 100644
--- a/pyrpkg/__init__.py
+++ b/pyrpkg/__init__.py
@@ -2336,7 +2336,7 @@ class Commands(object):
         try:
             shutil.rmtree(tmp_dir)
         except OSError as error:
-            if error.errno != errno.EEXIST:
+            if error.errno != errno.ENOENT:
                 raise rpkgError('Failed to remove temporary directory'
                                 ' %s. Reason: %s.' % (tmp_dir, error))
 
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 21b5147..bc22ba3 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1222,39 +1222,85 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
 class TestMockbuild(CliTestCase):
     """Test mockbuild command"""
 
-    @patch('pyrpkg.Commands._run_command')
-    def test_mockbuild(self, _run_command):
-        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
-                   '--release', 'rhel-6', 'mockbuild',
-                   '--root', '/etc/mock/some-root']
+    def setUp(self):
+        super(TestMockbuild, self).setUp()
+        self.run_command_patcher = patch('pyrpkg.Commands._run_command')
+        self.mock_run_command = self.run_command_patcher.start()
 
+    def tearDown(self):
+        self.run_command_patcher.stop()
+        super(TestMockbuild, self).tearDown()
+
+    def mockbuild(self, cli_cmd):
         with patch('sys.argv', new=cli_cmd):
             cli = self.new_cli()
             cli.mockbuild()
+            return cli
+
+    def test_mockbuild(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   '--release', 'rhel-6', 'mockbuild',
+                   '--root', '/etc/mock/some-root']
+        cli = self.mockbuild(cli_cmd)
 
         expected_cmd = ['mock', '-r', '/etc/mock/some-root',
                         '--resultdir', cli.cmd.mock_results_dir, '--rebuild',
                         cli.cmd.srpmname]
-        _run_command.assert_called_with(expected_cmd)
+        self.mock_run_command.assert_called_with(expected_cmd)
 
-    @patch('pyrpkg.Commands._run_command')
-    def test_with_without(self, _run_command):
+    def test_with_without(self):
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
                    '--release', 'rhel-6', 'mockbuild',
                    '--root', '/etc/mock/some-root',
                    '--with', 'a', '--without', 'b', '--with', 'c',
                    '--without', 'd']
-
-        with patch('sys.argv', new=cli_cmd):
-            cli = self.new_cli()
-            cli.mockbuild()
+        cli = self.mockbuild(cli_cmd)
 
         expected_cmd = ['mock', '--with', 'a', '--with', 'c',
                         '--without', 'b', '--without', 'd',
                         '-r', '/etc/mock/some-root',
                         '--resultdir', cli.cmd.mock_results_dir, '--rebuild',
                         cli.cmd.srpmname]
-        _run_command.assert_called_with(expected_cmd)
+        self.mock_run_command.assert_called_with(expected_cmd)
+
+    @patch('pyrpkg.Commands._config_dir_basic')
+    @patch('pyrpkg.Commands._config_dir_other')
+    @patch('os.path.exists', return_value=False)
+    def test_use_mock_config_got_from_koji(
+            self, exists, config_dir_other, config_dir_basic):
+        config_dir_basic.return_value = '/path/to/config-dir'
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   '--release', 'rhel-7', 'mockbuild']
+        self.mockbuild(cli_cmd)
+
+        args, kwargs = self.mock_run_command.call_args
+        cmd_to_execute = args[0]
+
+        self.assertTrue('--configdir' in cmd_to_execute)
+        self.assertTrue(config_dir_basic.return_value in cmd_to_execute)
+
+    @patch('pyrpkg.Commands._config_dir_basic')
+    @patch('os.path.exists', return_value=False)
+    def test_fail_to_store_mock_config_in_created_config_dir(
+            self, exists, config_dir_basic):
+        config_dir_basic.side_effect = rpkgError
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   '--release', 'rhel-7', 'mockbuild']
+        self.assertRaises(rpkgError, self.mockbuild, cli_cmd)
+
+    @patch('pyrpkg.Commands._config_dir_basic')
+    @patch('pyrpkg.Commands._config_dir_other')
+    @patch('os.path.exists', return_value=False)
+    def test_fail_to_populate_mock_config(
+            self, exists, config_dir_other, config_dir_basic):
+        config_dir_basic.return_value = '/path/to/config-dir'
+        config_dir_other.side_effect = rpkgError
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   '--release', 'rhel-7', 'mockbuild']
+        self.assertRaises(rpkgError, self.mockbuild, cli_cmd)
 
 
 class TestCoprBuild(CliTestCase):
diff --git a/tests/test_commands.py b/tests/test_commands.py
index 1f583d6..2641b90 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -1,16 +1,21 @@
 # -*- coding: utf-8 -*-
 
+import errno
 import os
 import shutil
 import six
 import subprocess
 import tempfile
 
+from contextlib import contextmanager
+
 import git
 import rpm
+from mock import call
 from mock import patch
 from mock import Mock
 from mock import PropertyMock
+from mock import mock_open
 
 from pyrpkg import rpkgError
 
@@ -691,3 +696,200 @@ class TestConstructBuildURL(CommandTestCase):
             anongiturl % {'module': ns_module_name.return_value},
             commithash.return_value)
         self.assertEqual(expected_url, url)
+
+
+class TestCleanupTmpDir(CommandTestCase):
+    """Test Commands._cleanup_tmp_dir for mockbuild command"""
+
+    def setUp(self):
+        super(TestCleanupTmpDir, self).setUp()
+        self.tmp_dir_name = tempfile.mkdtemp(prefix='test-cleanup-tmp-dir-')
+
+    def tearDown(self):
+        if os.path.exists(self.tmp_dir_name):
+            os.rmdir(self.tmp_dir_name)
+        super(TestCleanupTmpDir, self).tearDown()
+
+    @patch('shutil.rmtree')
+    def test_do_nothing_is_tmp_dir_is_invalid(self, rmtree):
+        cmd = self.make_commands()
+        for invalid_dir in ('', None):
+            cmd._cleanup_tmp_dir(invalid_dir)
+            rmtree.assert_not_called()
+
+    def test_remove_tmp_dir(self):
+        cmd = self.make_commands()
+        cmd._cleanup_tmp_dir(self.tmp_dir_name)
+
+        self.assertFalse(os.path.exists(self.tmp_dir_name))
+
+    def test_keep_silient_if_tmp_dir_does_not_exist(self):
+        cmd = self.make_commands()
+        tmp_dir = tempfile.mkdtemp()
+        os.rmdir(tmp_dir)
+
+        cmd._cleanup_tmp_dir(tmp_dir)
+
+    def test_raise_error_if_other_non_no_such_file_dir_error(self):
+        cmd = self.make_commands()
+        with patch('shutil.rmtree',
+                   side_effect=OSError((errno.EEXIST), 'error message')):
+            self.assertRaises(rpkgError, cmd._cleanup_tmp_dir, '/tmp/dir')
+
+
+class TestConfigMockConfigDir(CommandTestCase):
+    """Test Commands._config_dir_basic for mockbuild"""
+
+    def setUp(self):
+        super(TestConfigMockConfigDir, self).setUp()
+
+        self.cmd = self.make_commands()
+
+        self.fake_root = 'fedora-26-x86_64'
+        self.mock_config_patcher = patch('pyrpkg.Commands.mock_config',
+                                         return_value='mock config x86_64')
+        self.mock_mock_config = self.mock_config_patcher.start()
+
+        self.mkdtemp_patcher = patch('tempfile.mkdtemp',
+                                     return_value='/tmp/mockconfig/dir')
+        self.mock_mkdtemp = self.mkdtemp_patcher.start()
+
+    def tearDown(self):
+        self.mkdtemp_patcher.stop()
+        self.mock_config_patcher.stop()
+        super(TestConfigMockConfigDir, self).tearDown()
+
+    @contextmanager
+    def assert_file_op(self, filename, mode, write_data=None):
+        """Assert file object operation"""
+        with patch('__builtin__.open', mock_open()) as mock:
+            yield
+            mock.assert_called_once_with(filename, mode)
+            if write_data is not None:
+                mock.return_value.write.assert_called_once_with(write_data)
+
+    def test_config_in_created_config_dir(self):
+        config_file = '{0}.cfg'.format(
+            os.path.join(self.mock_mkdtemp.return_value, self.fake_root))
+
+        with self.assert_file_op(
+                config_file, 'wb',
+                write_data=self.mock_mock_config.return_value):
+            config_dir = self.cmd._config_dir_basic(root=self.fake_root)
+            self.assertEqual(self.mock_mkdtemp.return_value, config_dir)
+
+    def test_config_in_specified_config_dir(self):
+        fake_config_dir = '/path/to/fake/config-dir'
+        config_file = '{0}.cfg'.format(
+            os.path.join(fake_config_dir, self.fake_root))
+
+        with self.assert_file_op(
+                config_file, 'wb',
+                write_data=self.mock_mock_config.return_value):
+            config_dir = self.cmd._config_dir_basic(config_dir=fake_config_dir,
+                                                    root=self.fake_root)
+            self.assertEqual(fake_config_dir, config_dir)
+
+    @patch('pyrpkg.Commands.mockconfig', new_callable=PropertyMock)
+    def test_config_using_root_guessed_from_branch(self, mockconfig):
+        mockconfig.return_value = 'f26-candidate-i686'
+        config_file = '{0}.cfg'.format(
+            os.path.join(self.mock_mkdtemp.return_value,
+                         mockconfig.return_value))
+
+        with self.assert_file_op(
+                config_file, 'wb',
+                write_data=self.mock_mock_config.return_value):
+            config_dir = self.cmd._config_dir_basic()
+            self.assertEqual(self.mock_mkdtemp.return_value,
+                             config_dir)
+
+    def test_fail_if_error_occurs_while_getting_mock_config(self):
+        self.mock_mock_config.side_effect = rpkgError
+
+        with patch('pyrpkg.Commands._cleanup_tmp_dir') as mock:
+            self.assertRaises(
+                rpkgError, self.cmd._config_dir_basic, root=self.fake_root)
+            mock.assert_called_once_with(self.mock_mkdtemp.return_value)
+
+        with patch('pyrpkg.Commands._cleanup_tmp_dir') as mock:
+            self.assertRaises(rpkgError,
+                              self.cmd._config_dir_basic,
+                              config_dir='/path/to/fake/config-dir',
+                              root=self.fake_root)
+            mock.assert_called_once_with(None)
+
+    def test_fail_if_error_occurs_while_writing_cfg_file(self):
+        with patch('__builtin__.open', mock_open()) as m:
+            m.return_value.write.side_effect = IOError
+
+            with patch('pyrpkg.Commands._cleanup_tmp_dir') as mock:
+                self.assertRaises(rpkgError,
+                                  self.cmd._config_dir_basic,
+                                  root=self.fake_root)
+                mock.assert_called_once_with(self.mock_mkdtemp.return_value)
+
+            with patch('pyrpkg.Commands._cleanup_tmp_dir') as mock:
+                self.assertRaises(rpkgError,
+                                  self.cmd._config_dir_basic,
+                                  config_dir='/path/to/fake/config-dir',
+                                  root=self.fake_root)
+                mock.assert_called_once_with(None)
+
+
+class TestConfigMockConfigDirWithNecessaryFiles(CommandTestCase):
+    """Test Commands._config_dir_other"""
+
+    @patch('shutil.copy2')
+    @patch('os.path.exists', return_value=True)
+    def test_copy_cfg_files_from_etc_mock_dir(self, exists, copy2):
+        cmd = self.make_commands()
+        cmd._config_dir_other('/path/to/config-dir')
+
+        exists.assert_has_calls([
+            call('/etc/mock/site-defaults.cfg'),
+            call('/etc/mock/logging.ini')
+        ])
+        copy2.assert_has_calls([
+            call('/etc/mock/site-defaults.cfg',
+                 '/path/to/config-dir/site-defaults.cfg'),
+            call('/etc/mock/logging.ini',
+                 '/path/to/config-dir/logging.ini'),
+        ])
+
+    @patch('os.path.exists', return_value=False)
+    def test_create_empty_cfg_files_if_not_exist_in_system_mock(self, exists):
+        cmd = self.make_commands()
+
+        with patch('__builtin__.open', mock_open()) as m:
+            cmd._config_dir_other('/path/to/config-dir')
+
+            m.assert_has_calls([
+                call('/path/to/config-dir/site-defaults.cfg', 'w'),
+                call().close(),
+                call('/path/to/config-dir/logging.ini', 'w'),
+                call().close(),
+            ])
+
+        exists.assert_has_calls([
+            call('/etc/mock/site-defaults.cfg'),
+            call('/etc/mock/logging.ini')
+        ])
+
+    @patch('shutil.copy2')
+    @patch('os.path.exists', return_value=True)
+    def test_fail_when_copy_cfg_file(self, exists, copy2):
+        copy2.side_effect = OSError
+
+        cmd = self.make_commands()
+        self.assertRaises(rpkgError,
+                          cmd._config_dir_other, '/path/to/config-dir')
+
+    @patch('os.path.exists', return_value=False)
+    def test_fail_if_error_when_write_empty_cfg_files(self, exists):
+        cmd = self.make_commands()
+
+        with patch('__builtin__.open', mock_open()) as m:
+            m.side_effect = IOError
+            self.assertRaises(rpkgError,
+                              cmd._config_dir_other, '/path/to/config-dir')

From 6f83daa904e1b8845b512a5d1e122c74ff4c76f9 Mon Sep 17 00:00:00 2001
From: Chenxiong Qi <cqi@redhat.com>
Date: Oct 08 2017 14:47:58 +0000
Subject: [PATCH 6/6] Tests for patch command


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

---

diff --git a/tests/test_cli.py b/tests/test_cli.py
index bc22ba3..9493b58 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -25,10 +25,12 @@ import git
 import pyrpkg.cli
 
 import utils
-from mock import patch
 from mock import PropertyMock
-from utils import CommandTestCase
+from mock import call
+from mock import mock_open
+from mock import patch
 from pyrpkg import rpkgError
+from utils import CommandTestCase
 
 
 # rpkg.conf for running tests below
@@ -369,7 +371,7 @@ class TestCommit(CliTestCase):
 
     def test_with_clog(self):
         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'commit', '--clog']
-        
+
         with patch('sys.argv', new=cli_cmd):
             self.cli_commit()
 
@@ -1556,3 +1558,129 @@ enabled = true''', repo_config)
         repo_config = self.read_file(self.osbs_repo_config).strip()
         self.assertEqual('''[autorebuild]
 enabled = false''', repo_config)
+
+
+class TestPatch(CliTestCase):
+    """Test patch command"""
+
+    def setUp(self):
+        super(TestPatch, self).setUp()
+
+        self.repo_patcher = patch('pyrpkg.Commands.repo',
+                                  new_callable=PropertyMock)
+        self.mock_repo = self.repo_patcher.start()
+
+        self.Popen_patcher = patch('subprocess.Popen')
+        self.mock_Popen = self.Popen_patcher.start()
+
+        self.module_name_patcher = patch('pyrpkg.Commands.module_name',
+                                         new_callable=PropertyMock,
+                                         return_value='docpkg')
+        self.mock_module_name = self.module_name_patcher.start()
+
+        self.ver_patcher = patch('pyrpkg.Commands.ver',
+                                 new_callable=PropertyMock,
+                                 return_value='2.0')
+        self.mock_ver = self.ver_patcher.start()
+
+    def tearDown(self):
+        self.ver_patcher.stop()
+        self.module_name_patcher.stop()
+        self.Popen_patcher.stop()
+        self.repo_patcher.stop()
+        super(TestPatch, self).tearDown()
+
+    def test_expanded_source_dir_not_found(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'patch', 'fix']
+
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            six.assertRaisesRegex(
+                self, rpkgError,
+                'Expanded source dir not found!', cli.patch)
+
+    @patch('os.path.isdir', return_value=True)
+    def test_generate_diff(self, isdir):
+        self.mock_Popen.return_value.communicate.return_value = ['+ diff', '']
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'patch', 'fix']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            with patch('__builtin__.open', mock_open()) as m:
+                cli.patch()
+                m.return_value.write.assert_called_once_with('+ diff')
+
+        patch_file = '{0}-{1}-fix.patch'.format(cli.cmd.module_name,
+                                                cli.cmd.ver)
+        self.mock_repo.return_value.index.add.assert_called_once_with(
+                [patch_file])
+
+    @patch('os.path.isdir', return_value=True)
+    def test_generate_empty_patch(self, isdir):
+        self.mock_Popen.return_value.communicate.return_value = ['', '']
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'patch', 'fix']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+            six.assertRaisesRegex(
+                self, rpkgError,
+                'gendiff generated an empty patch!', cli.patch)
+
+    @patch('os.rename')
+    @patch('os.path.isdir', return_value=True)
+    def test_rediff(self, isdir, rename):
+        origin_diff = '''diff -up fedpkg-1.29/fedpkg/__init__.py.origin fedpkg-1.29/fedpkg/__init__.py
+--- fedpkg-1.29/fedpkg/__init__.py.origin  2017-10-05 01:55:34.268488598 +0000
++++ fedpkg-1.29/fedpkg/__init__.py	2017-10-05 01:55:59.736947877 +0000
+@@ -9,12 +9,12 @@
+ # option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
+ # the full text of the license.
+
+-import pyrpkg'''
+
+        self.mock_Popen.return_value.communicate.return_value = [
+            origin_diff, '']
+
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'patch', '--rediff', 'fix']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+
+            patch_file = '{0}-{1}-fix.patch'.format(cli.cmd.module_name,
+                                                    cli.cmd.ver)
+            copied_patch_file = '{0}~'.format(patch_file)
+
+            with patch('__builtin__.open',
+                       mock_open(read_data=origin_diff)) as m:
+                with patch('os.path.exists', return_value=True) as exists:
+                    cli.patch()
+
+                    exists.assert_called_once_with(
+                        os.path.join(cli.cmd.path, patch_file))
+
+                rename.assert_called_once_with(
+                    os.path.join(cli.cmd.path, patch_file),
+                    os.path.join(cli.cmd.path, copied_patch_file))
+
+                m.assert_has_calls([
+                    call(os.path.join(cli.cmd.path, patch_file), 'r'),
+                    call().readlines(),
+                    call(os.path.join(cli.cmd.path, patch_file), 'w'),
+                    call().write(origin_diff),
+                ])
+
+    def test_fail_if_no_previous_diff_exists(self):
+        cli_cmd = ['rpkg', '--path', self.cloned_repo_path,
+                   'patch', '--rediff', 'fix']
+        with patch('sys.argv', new=cli_cmd):
+            cli = self.new_cli()
+
+            patch_file = '{0}-{1}-fix.patch'.format(cli.cmd.module_name,
+                                                    cli.cmd.ver)
+            with patch('os.path.exists', return_value=False) as exists:
+                six.assertRaisesRegex(
+                    self, rpkgError,
+                    'Patch file [^ ]+ not found, unable to rediff', cli.patch)
+
+                exists.assert_called_once_with(
+                    os.path.join(cli.cmd.path, patch_file))
diff --git a/tests/utils.py b/tests/utils.py
index e805bd1..7e77912 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -3,12 +3,17 @@
 import os
 import subprocess
 import tempfile
-import unittest
 import shutil
 import sys
 
 from pyrpkg import Commands
 
+# For running tests with Python 2.6
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
 # Following global variables are used to construct Commands for tests in this
 # module. Only for testing purpose, and they are not going to be used for
 # hitting real services.

