From 776d53d576ff0736162beb7014a3c7985253069d Mon Sep 17 00:00:00 2001 From: Chenxiong Qi Date: Oct 08 2017 14:06:32 +0000 Subject: [PATCH 1/6] Suppress output from git command within setUp Signed-off-by: Chenxiong Qi --- 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 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 --- 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 Date: Oct 08 2017 14:06:32 +0000 Subject: [PATCH 3/6] Tests for container-build-setup command Signed-off-by: Chenxiong Qi --- 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 Date: Oct 08 2017 14:06:32 +0000 Subject: [PATCH 4/6] More tests for getting spec file Signed-off-by: Chenxiong Qi --- 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 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 --- 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 Date: Oct 08 2017 14:47:58 +0000 Subject: [PATCH 6/6] Tests for patch command Signed-off-by: Chenxiong Qi --- 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.