From 8179378a8905194090ddf07e7fb40269737736a1 Mon Sep 17 00:00:00 2001 From: Jana Cupova Date: Oct 18 2021 07:39:30 +0000 Subject: Add CLI unit tests --- diff --git a/tests/test_cli/test_add_host_to_channel.py b/tests/test_cli/test_add_host_to_channel.py index e3298bc..0ca6681 100644 --- a/tests/test_cli/test_add_host_to_channel.py +++ b/tests/test_cli/test_add_host_to_channel.py @@ -74,13 +74,14 @@ class TestAddHostToChannel(utils.CliTestCase): @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel_new( + def test_handle_add_host_to_channel_new_and_force( self, activate_session_mock, stdout): host = 'host' host_info = mock.ANY channel = 'channel' new_arg = '--new' - args = [host, channel, new_arg] + force_arg = '--force' + args = [host, channel, new_arg, force_arg] options = mock.MagicMock() # Mock out the xmlrpc server @@ -98,7 +99,7 @@ class TestAddHostToChannel(utils.CliTestCase): activate_session_mock.assert_called_once_with(session, options) session.getChannel.assert_not_called() session.getHost.assert_called_once_with(host) - session.addHostToChannel.assert_called_once_with(host, channel, create=True) + session.addHostToChannel.assert_called_once_with(host, channel, create=True, force=True) self.assertNotEqual(rv, 1) @mock.patch('sys.stderr', new_callable=six.StringIO) diff --git a/tests/test_cli/test_add_target.py b/tests/test_cli/test_add_target.py index cc0ff17..18a2858 100644 --- a/tests/test_cli/test_add_target.py +++ b/tests/test_cli/test_add_target.py @@ -127,6 +127,25 @@ class TestAddTarget(utils.CliTestCase): self.session.createBuildTarget.assert_called_once_with(target, tag, target) self.session.getTag.assert_called_with(target) + @mock.patch('sys.stderr', new_callable=StringIO) + def test_add_target_without_perms(self, stderr): + side_effect_result = [False, False] + + target = 'test-target' + tag = 'test-tag' + self.session.hasPerm.side_effect = side_effect_result + with self.assertRaises(SystemExit) as ex: + handle_add_target(self.options, self.session, [target, tag]) + self.assertExitCode(ex, 2) + expected_msg = """Usage: %s add-target +(Specify the --help global option for a list of other help options) + +%s: error: This action requires target or admin privileges +""" % (self.progname, self.progname) + self.assert_console_message(stderr, expected_msg) + self.session.createBuildTarget.assert_not_called() + self.session.getTag.assert_not_called() + def test_add_target_help(self): self.assert_help( handle_add_target, diff --git a/tests/test_cli/test_build.py b/tests/test_cli/test_build.py index fb0b911..076d2c0 100644 --- a/tests/test_cli/test_build.py +++ b/tests/test_cli/test_build.py @@ -1,12 +1,11 @@ from __future__ import absolute_import import mock -import os import six -import sys from koji_cli.commands import handle_build, _progress_callback from . import utils + class TestBuild(utils.CliTestCase): # Show long diffs in error output... maxDiff = None @@ -17,8 +16,24 @@ class TestBuild(utils.CliTestCase): self.options.quiet = None self.options.weburl = 'weburl' self.options.poll_interval = 0 + self.options.debug = False # Mock out the xmlrpc server self.session = mock.MagicMock() + self.target = 'target' + self.dest_tag = 'dest_tag' + self.target_info = {'dest_tag': self.dest_tag} + self.dest_tag_info = {'locked': False} + self.source_srpm = 'srpm' + self.source_scm = 'http://scm' + self.task_id = 1 + self.priority = None + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.unique_path_mock = mock.patch('koji_cli.commands.unique_path').start() + self.unique_path_mock.return_value = 'random_path' + self.running_in_bg_mock = mock.patch('koji_cli.commands._running_in_bg').start() + self.running_in_bg_mock.return_value = False + self.watch_tasks_mock = mock.patch('koji_cli.commands.watch_tasks').start() + self.watch_tasks_mock.return_value = 0 self.error_format = """Usage: %s build [options] The first option is the build target, not to be confused with the destination @@ -34,30 +49,13 @@ https://docs.pagure.org/koji/HOWTO/#package-organization """ % (self.progname, self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_from_srpm( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 - args = [target, source] + def test_handle_build_from_srpm(self, stdout): + args = [self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: target, srpm # expected: success @@ -70,47 +68,30 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') - self.assertEqual(running_in_bg_mock.call_count, 2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') + self.assertEqual(self.running_in_bg_mock.call_count, 2) self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=_progress_callback) + self.source_srpm, 'random_path', callback=_progress_callback) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_from_scm( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'http://scm' - task_id = 1 - args = [target, source] + def test_handle_build_from_scm(self, stdout): + args = [self.target, self.source_scm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: target, http://scm # expected: success @@ -121,36 +102,24 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_called_once() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_called_once() self.session.uploadWrapper.assert_not_called() self.session.build.assert_called_once_with( - source, target, opts, priority=priority) + self.source_scm, self.target, opts, priority=self.priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_no_arg( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr, - stdout): + def test_handle_build_no_arg(self, stderr, stdout): args = [] - progname = os.path.basename(sys.argv[0]) or 'koji' # Run it and check immediate output with self.assertRaises(SystemExit) as ex: @@ -159,37 +128,26 @@ Task info: weburl/taskinfo?taskID=1 actual_stdout = stdout.getvalue() actual_stderr = stderr.getvalue() expected_stdout = '' - expected_stderr = self.format_error_message("Exactly two arguments (a build target and a SCM URL or srpm file) are required") + expected_stderr = self.format_error_message("Exactly two arguments (a build target and " + "a SCM URL or srpm file) are required") self.assertMultiLineEqual(actual_stdout, expected_stdout) self.assertMultiLineEqual(actual_stderr, expected_stderr) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_help( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr, - stdout): + def test_handle_build_help(self, stderr, stdout): args = ['--help'] - progname = os.path.basename(sys.argv[0]) or 'koji' # Run it and check immediate output with self.assertRaises(SystemExit) as ex: @@ -230,47 +188,31 @@ Options: Provide a JSON string of custom metadata to be deserialized and stored under the build's extra.custom_user_metadata field -""" % (progname, progname) +""" % (self.progname, self.progname) expected_stderr = '' self.assertMultiLineEqual(actual_stdout, expected_stdout) self.assertMultiLineEqual(actual_stderr, expected_stderr) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_custom_user_metadata( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'http://scm' - task_id = 1 - args = ['--custom-user-metadata={"automation-triggered-by": "yoda"}', target, source] + def test_handle_build_custom_user_metadata(self, stdout): + args = ['--custom-user-metadata={"automation-triggered-by": "yoda"}', self.target, + self.source_scm] opts = {'custom_user_metadata': {'automation-triggered-by': 'yoda'}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: target, http://scm # expected: success @@ -281,37 +223,25 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_called_once() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_called_once() self.session.uploadWrapper.assert_not_called() self.session.build.assert_called_once_with( - source, target, opts, priority=priority) + self.source_scm, self.target, opts, priority=self.priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_custom_user_metadata_invalid_json( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr, - stdout): - target = 'target' - source = 'http://scm' - args = [target, source, '--custom-user-metadata={Do or do not. There is no try.}'] + def test_handle_build_custom_user_metadata_invalid_json(self, stderr, stdout): + args = [self.target, self.source_scm, + '--custom-user-metadata={Do or do not. There is no try.}'] # Run it and check immediate output with self.assertRaises(SystemExit) as ex: @@ -325,33 +255,21 @@ Task info: weburl/taskinfo?taskID=1 self.assertMultiLineEqual(actual_stderr, expected_stderr) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_custom_user_metadata_not_json_object( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr, - stdout): - target = 'target' - source = 'http://scm' - args = [target, source, '--custom-user-metadata="Do or do not. There is no try."'] + def test_handle_build_custom_user_metadata_not_json_object(self, stderr, stdout): + args = [self.target, self.source_scm, + '--custom-user-metadata="Do or do not. There is no try."'] # Run it and check immediate output with self.assertRaises(SystemExit) as ex: @@ -365,35 +283,21 @@ Task info: weburl/taskinfo?taskID=1 self.assertMultiLineEqual(actual_stderr, expected_stderr) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_arch_override_denied( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr, - stdout): - target = 'target' - source = 'http://scm' + def test_handle_build_arch_override_denied(self, stderr, stdout): arch_override = 'somearch' - args = [target, source, '--arch-override=' + arch_override] - progname = os.path.basename(sys.argv[0]) or 'koji' + args = [self.target, self.source_scm, '--arch-override=' + arch_override] # Run it and check immediate output with self.assertRaises(SystemExit) as ex: @@ -402,44 +306,32 @@ Task info: weburl/taskinfo?taskID=1 actual_stdout = stdout.getvalue() actual_stderr = stderr.getvalue() expected_stdout = '' - expected_stderr = self.format_error_message("--arch_override is only allowed for --scratch builds") + expected_stderr = self.format_error_message( + "--arch_override is only allowed for --scratch builds") self.assertMultiLineEqual(actual_stdout, expected_stdout) self.assertMultiLineEqual(actual_stderr, expected_stderr) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_none_tag( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): + def test_handle_build_none_tag(self, stdout): target = 'nOne' - source = 'http://scm' - task_id = 1 repo_id = 2 - args = ['--repo-id=' + str(repo_id), target, source] + args = ['--repo-id=' + str(repo_id), target, self.source_scm] opts = { 'repo_id': repo_id, 'skip_tag': True, 'wait_builds': [], 'custom_user_metadata': {} } - priority = None - self.session.build.return_value = task_id + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --repo-id=2, nOne, http://scm # expected: success @@ -450,39 +342,25 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.getBuildTarget.assert_not_called() self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_called_once() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_called_once() self.session.uploadWrapper.assert_not_called() # target==None, repo_id==2, skip_tag==True self.session.build.assert_called_once_with( - source, None, opts, priority=priority) + self.source_scm, None, opts, priority=self.priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_target_not_found( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr): - target = 'target' + def test_handle_build_target_not_found(self, stderr): target_info = None - source = 'http://scm' - args = [target, source] - - progname = os.path.basename(sys.argv[0]) or 'koji' + args = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info # Run it and check immediate output @@ -492,40 +370,25 @@ Task info: weburl/taskinfo?taskID=1 handle_build(self.options, self.session, args) self.assertExitCode(ex, 2) actual = stderr.getvalue() - expected = self.format_error_message( "No such build target: target") + expected = self.format_error_message("No such build target: target") self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) self.session.getTag.assert_not_called() - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_dest_tag_not_found( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr): - target = 'target' - dest_tag = 'dest_tag' + def test_handle_build_dest_tag_not_found(self, stderr): dest_tag_name = 'dest_tag_name' - target_info = {'dest_tag': dest_tag, 'dest_tag_name': dest_tag_name} + target_info = {'dest_tag': self.dest_tag, 'dest_tag_name': dest_tag_name} dest_tag_info = None - source = 'http://scm' - args = [target, source] - - progname = os.path.basename(sys.argv[0]) or 'koji' + args = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info @@ -539,37 +402,22 @@ Task info: weburl/taskinfo?taskID=1 expected = self.format_error_message("No such destination tag: dest_tag_name") self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_dest_tag_locked( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stderr): - target = 'target' - dest_tag = 'dest_tag' + def test_handle_build_dest_tag_locked(self, stderr): dest_tag_name = 'dest_tag_name' - target_info = {'dest_tag': dest_tag, 'dest_tag_name': dest_tag_name} + target_info = {'dest_tag': self.dest_tag, 'dest_tag_name': dest_tag_name} dest_tag_info = {'name': 'dest_tag_name', 'locked': True} - source = 'http://scm' - args = [target, source] - - progname = os.path.basename(sys.argv[0]) or 'koji' + args = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info @@ -583,52 +431,30 @@ Task info: weburl/taskinfo?taskID=1 expected = self.format_error_message("Destination tag dest_tag_name is locked") self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.uploadWrapper.assert_not_called() self.session.build.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_arch_override( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'http://scm' - task_id = 1 + def test_handle_build_arch_override(self, stdout): arch_override = 'somearch' - args = [ - '--arch-override=' + - arch_override, - '--scratch', - target, - source] + args = ['--arch-override=' + arch_override, '--scratch', self.target, self.source_scm] opts = { 'arch_override': arch_override, 'custom_user_metadata': {}, 'scratch': True, 'wait_builds': [], } - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --arch-override=somearch, --scratch, target, http://scm # expected: success @@ -639,46 +465,30 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_called_once() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_called_once() self.session.uploadWrapper.assert_not_called() # arch-override=='somearch', scratch==True self.session.build.assert_called_once_with( - source, target, opts, priority=priority) + self.source_scm, self.target, opts, priority=self.priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_background( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'http://scm' - task_id = 1 - args = ['--background', target, source] + def test_handle_build_background(self, stdout): + args = ['--background', self.target, self.source_scm] priority = 5 opts = {'custom_user_metadata': {}, 'wait_builds': []} - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --background, target, http://scm # expected: success @@ -689,45 +499,29 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_not_called() - running_in_bg_mock.assert_called_once() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_called_once() self.session.uploadWrapper.assert_not_called() self.session.build.assert_called_once_with( - source, target, opts, priority=priority) + self.source_scm, self.target, opts, priority=priority) self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') @mock.patch('koji_cli.commands._running_in_bg', return_value=True) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_running_in_bg( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 - args = [target, source] + def test_handle_build_running_in_bg(self, running_in_bg_mock, stdout): + args = [self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: target, srpm # expected: success @@ -740,45 +534,28 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') self.assertEqual(running_in_bg_mock.call_count, 2) # callback==None self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=None) + self.source_srpm, 'random_path', callback=None) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() self.assertIsNone(rv) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_noprogress( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 - args = ['--noprogress', target, source] + def test_handle_build_noprogress(self, stdout): + args = ['--noprogress', self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --noprogress, target, srpm # expected: success @@ -791,48 +568,31 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') - self.assertEqual(running_in_bg_mock.call_count, 2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') + self.assertEqual(self.running_in_bg_mock.call_count, 2) # callback==None self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=None) + self.source_srpm, 'random_path', callback=None) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_called_once() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_quiet( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 + def test_handle_build_quiet(self, stdout): quiet = True - args = ['--quiet', target, source] + args = ['--quiet', self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --quiet, target, srpm # expected: success @@ -841,48 +601,30 @@ Task info: weburl/taskinfo?taskID=1 expected = '\n' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') - self.assertEqual(running_in_bg_mock.call_count, 2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') + self.assertEqual(self.running_in_bg_mock.call_count, 2) # callback==None self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=None) + self.source_srpm, 'random_path', callback=None) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_called_once() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_wait( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 - quiet = None - args = ['--wait', target, source] + def test_handle_build_wait(self, stdout): + args = ['--wait', self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --wait, target, srpm # expected: success @@ -895,47 +637,30 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') # the second one won't be executed when wait==False - self.assertEqual(running_in_bg_mock.call_count, 1) + self.assertEqual(self.running_in_bg_mock.call_count, 1) self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=_progress_callback) + self.source_srpm, 'random_path', callback=_progress_callback) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_called_once() - watch_tasks_mock.assert_called_once_with( - self.session, [task_id], quiet=self.options.quiet, + self.watch_tasks_mock.assert_called_once_with( + self.session, [self.task_id], quiet=self.options.quiet, poll_interval=self.options.poll_interval, topurl=self.options.topurl) self.assertEqual(rv, 0) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands.unique_path', return_value='random_path') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_nowait( - self, - watch_tasks_mock, - running_in_bg_mock, - unique_path_mock, - activate_session_mock, - stdout): - target = 'target' - dest_tag = 'dest_tag' - target_info = {'dest_tag': dest_tag} - dest_tag_info = {'locked': False} - source = 'srpm' - task_id = 1 - args = ['--nowait', target, source] + def test_handle_build_nowait(self, stdout): + args = ['--nowait', self.target, self.source_srpm] opts = {'custom_user_metadata': {}, 'wait_builds': []} - priority = None - self.session.getBuildTarget.return_value = target_info - self.session.getTag.return_value = dest_tag_info - self.session.build.return_value = task_id + self.session.getBuildTarget.return_value = self.target_info + self.session.getTag.return_value = self.dest_tag_info + self.session.build.return_value = self.task_id # Run it and check immediate output # args: --nowait, target, srpm # expected: success @@ -948,16 +673,44 @@ Task info: weburl/taskinfo?taskID=1 """ self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(self.session, self.options) - self.session.getBuildTarget.assert_called_once_with(target) - self.session.getTag.assert_called_once_with(dest_tag) - unique_path_mock.assert_called_once_with('cli-build') + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getBuildTarget.assert_called_once_with(self.target) + self.session.getTag.assert_called_once_with(self.dest_tag) + self.unique_path_mock.assert_called_once_with('cli-build') # the second one won't be executed when wait==False - self.assertEqual(running_in_bg_mock.call_count, 1) + self.assertEqual(self.running_in_bg_mock.call_count, 1) self.session.uploadWrapper.assert_called_once_with( - source, 'random_path', callback=_progress_callback) + self.source_srpm, 'random_path', callback=_progress_callback) self.session.build.assert_called_once_with( - 'random_path/' + source, target, opts, priority=priority) + 'random_path/' + self.source_srpm, self.target, opts, priority=self.priority) self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() self.assertIsNone(rv) + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + def test_handle_build_rebuild_srpm_without_scratch(self, stderr, stdout): + args = ['--rebuild-srpm', self.target, self.source_srpm] + + # Run it and check immediate output + with self.assertRaises(SystemExit) as ex: + handle_build(self.options, self.session, args) + self.assertExitCode(ex, 2) + actual_stdout = stdout.getvalue() + actual_stderr = stderr.getvalue() + expected_stdout = '' + expected_stderr = self.format_error_message( + "--no-/rebuild-srpm is only allowed for --scratch builds") + self.assertMultiLineEqual(actual_stdout, expected_stdout) + self.assertMultiLineEqual(actual_stderr, expected_stderr) + + # Finally, assert that things were called as we expected. + self.activate_session_mock.assert_not_called() + self.session.getBuildTarget.assert_not_called() + self.session.getTag.assert_not_called() + self.unique_path_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() + self.session.uploadWrapper.assert_not_called() + self.session.build.assert_not_called() + self.session.logout.assert_not_called() + self.watch_tasks_mock.assert_not_called() diff --git a/tests/test_cli/test_edit_channel.py b/tests/test_cli/test_edit_channel.py index 58f37cb..017440f 100644 --- a/tests/test_cli/test_edit_channel.py +++ b/tests/test_cli/test_edit_channel.py @@ -19,6 +19,11 @@ class TestEditChannel(utils.CliTestCase): self.channel_old = 'test-channel' self.channel_new = 'test-channel-new' self.description = 'description' + self.channel_info = { + 'id': 123, + 'name': self.channel_old, + 'description': self.description, + } self.maxDiff = None def tearDown(self): @@ -82,6 +87,39 @@ Options: self.session.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new, description=self.description) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_edit_channel_non_exist_channel(self, activate_session_mock, stderr): + expected = 'No such channel: %s\n' % self.channel_old + channel_info = None + self.session.getChannel.return_value = channel_info + with self.assertRaises(SystemExit) as ex: + handle_edit_channel(self.options, self.session, + [self.channel_old, '--name', self.channel_new, + '--description', self.description]) + self.assertExitCode(ex, 1) + actual = stderr.getvalue() + self.assertMultiLineEqual(actual, expected) + activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.editChannel.assert_not_called() + + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_edit_channel_non_result(self, activate_session_mock, stderr): + expected = 'No changes made, please correct the command line\n' + self.session.getChannel.return_value = self.channel_info + self.session.editChannel.return_value = None + with self.assertRaises(SystemExit) as ex: + handle_edit_channel(self.options, self.session, + [self.channel_old, '--name', self.channel_new, + '--description', self.description]) + self.assertExitCode(ex, 1) + actual = stderr.getvalue() + self.assertMultiLineEqual(actual, expected) + activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new, + description=self.description) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_cli/test_edit_external_repo.py b/tests/test_cli/test_edit_external_repo.py index c1b17d3..c0d2b32 100644 --- a/tests/test_cli/test_edit_external_repo.py +++ b/tests/test_cli/test_edit_external_repo.py @@ -56,7 +56,7 @@ class TestEditExternalRepo(utils.CliTestCase): # edit ext-repo only handle_edit_external_repo(self.options, self.session, - ['ext_repo','--name', 'newname', '--url', 'https://newurl']) + ['ext_repo', '--name', 'newname', '--url', 'https://newurl']) self.assert_console_message(stdout, "") self.assert_console_message(stderr, "") self.session.editExternalRepo.assert_called_once_with('ext_repo', @@ -66,14 +66,15 @@ class TestEditExternalRepo(utils.CliTestCase): # edit tag-repo only self.session.reset_mock() handle_edit_external_repo(self.options, self.session, - ['ext_repo','-t', 'tag', '-p', '0', '-m', 'koji']) + ['ext_repo', '-t', 'tag', '-p', '0', '-m', 'koji', '-a', 'i386']) self.assert_console_message(stdout, "") self.assert_console_message(stderr, "") self.session.editExternalRepo.assert_not_called() self.session.editTagExternalRepo.assert_called_once_with(repo_info='ext_repo', tag_info='tag', priority=0, - merge_mode='koji') + merge_mode='koji', + arches='i386') def test_handle_edit_external_repo_help(self): self.assert_help( diff --git a/tests/test_cli/test_edit_target.py b/tests/test_cli/test_edit_target.py index fdda38c..d8760c6 100644 --- a/tests/test_cli/test_edit_target.py +++ b/tests/test_cli/test_edit_target.py @@ -1,5 +1,7 @@ from __future__ import absolute_import +import copy + import mock from six.moves import StringIO @@ -14,6 +16,20 @@ class TestEditTarget(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.build_target_info = {'build_tag': 444, + 'build_tag_name': 'test-tag', + 'dest_tag': 445, + 'dest_tag_name': 'dest-test-tag', + 'id': 1, + 'name': 'test-target'} + self.dest_tag_info = {'arches': 'x86_64', + 'extra': {}, + 'id': 1, + 'name': 'new-dest-tag'} + self.build_tag_info = {'arches': 'x86_64', + 'extra': {}, + 'id': 1, + 'name': 'new-build-tag'} @mock.patch('sys.stderr', new_callable=StringIO) def test_edit_target_without_option(self, stderr): @@ -46,3 +62,100 @@ class TestEditTarget(utils.CliTestCase): self.assertExitCode(ex, 1) self.assert_console_message(stderr, expected) self.session.editBuildTarget.assert_not_called() + + @mock.patch('sys.stderr', new_callable=StringIO) + def test_edit_target_without_perms(self, stderr): + side_effect_result = [False, False] + + target = 'test-target' + self.session.hasPerm.side_effect = side_effect_result + with self.assertRaises(SystemExit) as ex: + handle_edit_target(self.options, self.session, [target]) + self.assertExitCode(ex, 2) + expected_msg = """Usage: %s edit-target [options] +(Specify the --help global option for a list of other help options) + +%s: error: This action requires target or admin privileges +""" % (self.progname, self.progname) + self.assert_console_message(stderr, expected_msg) + self.session.editBuildTarget.assert_not_called() + self.session.getBuildTarget.assert_not_called() + + @mock.patch('sys.stdout', new_callable=StringIO) + def test_edit_target_new_name(self, stdout): + target = 'test-target' + new_target_name = 'new-test-target' + self.session.getBuildTarget.return_value = self.build_target_info + rv = handle_edit_target(self.options, self.session, ['--rename', new_target_name, target]) + self.assertEqual(rv, None) + expected_msg = '' + self.assert_console_message(stdout, expected_msg) + self.session.getTag.assert_not_called() + self.session.getBuildTarget.assert_called_once_with(target) + self.session.editBuildTarget.assert_called_once_with( + self.build_target_info['orig_name'], new_target_name, + self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name']) + + @mock.patch('sys.stdout', new_callable=StringIO) + def test_edit_target_dest_tag(self, stdout): + target = 'test-target' + new_dest_tag = 'new-dest-tag' + self.session.getBuildTarget.return_value = self.build_target_info + self.session.getTag.return_value = self.dest_tag_info + rv = handle_edit_target(self.options, self.session, ['--dest-tag', new_dest_tag, target]) + self.assertEqual(rv, None) + expected_msg = '' + self.assert_console_message(stdout, expected_msg) + self.session.getTag.assert_called_once_with(new_dest_tag) + self.session.getBuildTarget.assert_called_once_with(target) + self.session.editBuildTarget.assert_called_once_with( + self.build_target_info['orig_name'], self.build_target_info['name'], + self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name']) + + @mock.patch('sys.stderr', new_callable=StringIO) + def test_edit_target_non_exist_build_tag(self, stderr): + target = 'test-target' + new_build_tag = 'new-build-tag' + self.session.getBuildTarget.return_value = self.build_target_info + self.session.getTag.return_value = None + with self.assertRaises(SystemExit) as ex: + handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target]) + self.assertExitCode(ex, 1) + expected_msg = "No such tag: %s\n" % new_build_tag + self.assert_console_message(stderr, expected_msg) + self.session.getTag.assert_called_once_with(new_build_tag) + self.session.getBuildTarget.assert_called_once_with(target) + self.session.editBuildTarget.assert_not_called() + + @mock.patch('sys.stderr', new_callable=StringIO) + def test_edit_target_tag_arch_none(self, stderr): + target = 'test-target' + new_build_tag = 'new-build-tag' + build_tag_info = copy.deepcopy(self.build_tag_info) + build_tag_info['arches'] = '' + self.session.getBuildTarget.return_value = self.build_target_info + self.session.getTag.return_value = build_tag_info + with self.assertRaises(SystemExit) as ex: + handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target]) + self.assertExitCode(ex, 1) + expected_msg = "Build tag has no arches: %s\n" % new_build_tag + self.assert_console_message(stderr, expected_msg) + self.session.getTag.assert_called_once_with(new_build_tag) + self.session.getBuildTarget.assert_called_once_with(target) + self.session.editBuildTarget.assert_not_called() + + @mock.patch('sys.stdout', new_callable=StringIO) + def test_edit_target_build_tag_valid(self, stdout): + target = 'test-target' + new_build_tag = 'new-build-tag' + self.session.getBuildTarget.return_value = self.build_target_info + self.session.getTag.return_value = self.build_tag_info + rv = handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target]) + self.assertEqual(rv, None) + expected_msg = '' + self.assert_console_message(stdout, expected_msg) + self.session.getTag.assert_called_once_with(new_build_tag) + self.session.getBuildTarget.assert_called_once_with(target) + self.session.editBuildTarget.assert_called_once_with( + self.build_target_info['orig_name'], self.build_target_info['name'], + self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name']) diff --git a/tests/test_cli/test_remove_tag.py b/tests/test_cli/test_remove_tag.py index 0f045d4..67441d6 100644 --- a/tests/test_cli/test_remove_tag.py +++ b/tests/test_cli/test_remove_tag.py @@ -52,6 +52,24 @@ class TestRemoveTag(utils.CliTestCase): self.session.deleteTag.assert_called_once_with(tag_info['id']) self.session.getTag.assert_called_with(tag_info['name']) + @mock.patch('sys.stderr', new_callable=StringIO) + def test_remove_tag_without_perms(self, stderr): + side_effect_result = [False, False] + + tag = 'test-tag' + self.session.hasPerm.side_effect = side_effect_result + with self.assertRaises(SystemExit) as ex: + handle_remove_tag(self.options, self.session, [tag]) + self.assertExitCode(ex, 2) + expected_msg = """Usage: %s remove-tag [options] +(Specify the --help global option for a list of other help options) + +%s: error: This action requires tag or admin privileges +""" % (self.progname, self.progname) + self.assert_console_message(stderr, expected_msg) + self.session.deleteTag.assert_not_called() + self.session.getTag.assert_not_called() + def test_remove_tag_help(self): self.assert_help( handle_remove_tag, diff --git a/tests/test_cli/test_remove_target.py b/tests/test_cli/test_remove_target.py index 8bb6c94..45b0e0e 100644 --- a/tests/test_cli/test_remove_target.py +++ b/tests/test_cli/test_remove_target.py @@ -51,6 +51,24 @@ class TestRemoveTarget(utils.CliTestCase): self.session.deleteBuildTarget.assert_called_once_with(build_target['id']) self.session.getBuildTarget.assert_called_with(build_target['name']) + @mock.patch('sys.stderr', new_callable=StringIO) + def test_remove_target_without_perms(self, stderr): + side_effect_result = [False, False] + + target = 'test-target' + self.session.hasPerm.side_effect = side_effect_result + with self.assertRaises(SystemExit) as ex: + handle_remove_target(self.options, self.session, [target]) + self.assertExitCode(ex, 2) + expected_msg = """Usage: %s remove-target [options] +(Specify the --help global option for a list of other help options) + +%s: error: This action requires target or admin privileges +""" % (self.progname, self.progname) + self.assert_console_message(stderr, expected_msg) + self.session.deleteBuildTarget.assert_not_called() + self.session.getBuildTarget.assert_not_called() + def test_remove_target_help(self): self.assert_help( handle_remove_target, diff --git a/tests/test_cli/test_rename_channel.py b/tests/test_cli/test_rename_channel.py index b485c5c..dd6cd4f 100644 --- a/tests/test_cli/test_rename_channel.py +++ b/tests/test_cli/test_rename_channel.py @@ -64,6 +64,23 @@ class TestRenameChannel(utils.CliTestCase): self.session.getChannel.assert_called_once_with(self.channel_name_old) self.session.renameChannel.assert_not_called() + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_rename_channel_more_args(self, activate_session_mock, stderr, stdout): + args = [self.channel_name_old, self.channel_name_new, 'extra-arg'] + with self.assertRaises(SystemExit) as ex: + handle_rename_channel(self.options, self.session, args) + self.assertExitCode(ex, 2) + expected = 'Incorrect number of arguments' + depr_warn = 'rename-channel is deprecated and will be removed in 1.28' + self.assert_console_message(stderr, expected, wipe=False, regex=True) + self.assert_console_message(stdout, depr_warn, wipe=False, regex=True) + # Finally, assert that things were called as we expected. + activate_session_mock.assert_not_called() + self.session.getChannel.assert_not_called() + self.session.renameChannel.assert_not_called() + def test_handle_rename_channel_help(self): self.assert_help( handle_rename_channel, diff --git a/tests/test_cli/test_restart_host.py b/tests/test_cli/test_restart_host.py index 750bb3d..7801148 100644 --- a/tests/test_cli/test_restart_host.py +++ b/tests/test_cli/test_restart_host.py @@ -14,59 +14,44 @@ class TestRestartHosts(utils.CliTestCase): maxDiff = None def setUp(self): + self.options = mock.MagicMock() + self.options.quiet = None + self.options.poll_interval = 3 + self.session = mock.MagicMock() + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.running_in_bg_mock = mock.patch('koji_cli.commands._running_in_bg').start() + self.running_in_bg_mock.return_value = False + self.watch_tasks_mock = mock.patch('koji_cli.commands.watch_tasks').start() self.task_id = 101 - @mock.patch('koji_cli.commands.watch_tasks') - @mock.patch('koji_cli.commands._running_in_bg') - @mock.patch('koji_cli.commands.activate_session') - def test_handle_restart_hosts_force_options( - self, activate_session_mock, running_in_bg_mock, watch_tasks_mock): + def test_handle_restart_hosts_force_options(self): """Test %s function with --force option""" % handle_restart_hosts.__name__ arguments = ['--force'] - options = mock.MagicMock(quiet=None, poll_interval=3) - session = mock.MagicMock() - - # set running in foreground - running_in_bg_mock.return_value = False - session.getHost.return_value = None - session.restartHosts.return_value = self.task_id - session.logout.return_value = None + self.session.getHost.return_value = None + self.session.restartHosts.return_value = self.task_id + self.session.logout.return_value = None # has other restart tasks are running case - session.listTasks.return_value = [{'id': 1}, {'id': 2}, {'id': 3}] + self.session.listTasks.return_value = [{'id': 1}, {'id': 2}, {'id': 3}] - handle_restart_hosts(options, session, arguments) - activate_session_mock.assert_called_once() - session.listTasks.assert_not_called() + handle_restart_hosts(self.options, self.session, arguments) + self.activate_session_mock.assert_called_once() + self.session.listTasks.assert_not_called() - session.restartHosts.assert_called_with() - session.logout.assert_called_once() - watch_tasks_mock.assert_called_with( - session, [self.task_id], quiet=None, poll_interval=3, topurl=options.topurl) + self.session.restartHosts.assert_called_with() + self.session.logout.assert_called_once() + self.watch_tasks_mock.assert_called_with( + self.session, [self.task_id], quiet=None, poll_interval=3, topurl=self.options.topurl) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.watch_tasks') - @mock.patch('koji_cli.commands._running_in_bg') - @mock.patch('koji_cli.commands.activate_session') - def test_handle_restart_hosts_has_other_tasks( - self, - activate_session_mock, - running_in_bg_mock, - watch_tasks_mock, - stdout, - stderr): - """Test %s function when there has other restart tasks exist""" % handle_restart_hosts.__name__ - options = mock.MagicMock() - session = mock.MagicMock() - - # set running in foreground - running_in_bg_mock.return_value = False - - session.getHost.return_value = None - session.restartHosts.return_value = True - session.logout.return_value = None + def test_handle_restart_hosts_has_other_tasks(self, stderr): + """Test %s function when there has other restart tasks exist + """ % handle_restart_hosts.__name__ + + self.session.getHost.return_value = None + self.session.restartHosts.return_value = True + self.session.logout.return_value = None # # session.listTasks returns: @@ -90,94 +75,110 @@ class TestRestartHosts(utils.CliTestCase): # 'start_ts': 1509647428.02884, # 'create_ts': 1509647408.93375, # 'host_id': 1, 'arch': 'noarch', - # 'request': "\n\nrestartHosts\n\n\n\n", + # 'request': "\n\nrestartHosts + # \n\n\n\n", # 'channel_id': 1, # 'owner_type': 0}] # # has other restart tasks are running case - session.listTasks.return_value = [{'id': 1}, {'id': 2}, {'id': 3}] + self.session.listTasks.return_value = [{'id': 1}, {'id': 2}, {'id': 3}] with self.assertRaises(SystemExit) as ex: - handle_restart_hosts(options, session, []) + handle_restart_hosts(self.options, self.session, []) self.assertExitCode(ex, 1) - activate_session_mock.assert_called_once() + self.activate_session_mock.assert_called_once() query_opt = { 'method': 'restartHosts', 'state': [koji.TASK_STATES[s] for s in ('FREE', 'OPEN', 'ASSIGNED')] } - session.listTasks.assert_called_with(query_opt) - session.restartHosts.assert_not_called() - session.logout.assert_not_called() + self.session.listTasks.assert_called_with(query_opt) + self.session.restartHosts.assert_not_called() + self.session.logout.assert_not_called() expect = "Found other restartHosts tasks running.\n" expect += "Task ids: %r\n" % \ - [t['id'] for t in session.listTasks.return_value] + [t['id'] for t in self.session.listTasks.return_value] expect += "Use --force to run anyway\n" self.assert_console_message(stderr, expect) - @mock.patch('koji_cli.commands.watch_tasks') @mock.patch('koji_cli.commands._running_in_bg') - @mock.patch('koji_cli.commands.activate_session') - def test_handle_restart_hosts_wait_option( - self, activate_session_mock, running_in_bg_mock, watch_tasks_mock): + def test_handle_restart_hosts_wait_option(self, running_in_bg_mock): """Test %s function with --force option""" % handle_restart_hosts.__name__ arguments = ['--wait'] - options = mock.MagicMock(quiet=None, poll_interval=3) - session = mock.MagicMock() # --wait is specified, running_in_bg() should not matter. running_in_bg_mock.return_value = True - session.getHost.return_value = None - session.restartHosts.return_value = self.task_id - session.logout.return_value = None + self.session.getHost.return_value = None + self.session.restartHosts.return_value = self.task_id + self.session.logout.return_value = None # has other restart tasks are running case - session.listTasks.return_value = [] + self.session.listTasks.return_value = [] - handle_restart_hosts(options, session, arguments) - activate_session_mock.assert_called_once() - session.listTasks.assert_called_once() + handle_restart_hosts(self.options, self.session, arguments) + self.activate_session_mock.assert_called_once() + self.session.listTasks.assert_called_once() - session.restartHosts.assert_called_with() - session.logout.assert_called_once() - watch_tasks_mock.assert_called_with( - session, [self.task_id], quiet=None, poll_interval=3, topurl=options.topurl) + self.session.restartHosts.assert_called_with() + self.session.logout.assert_called_once() + self.watch_tasks_mock.assert_called_with( + self.session, [self.task_id], quiet=None, poll_interval=3, topurl=self.options.topurl) - @mock.patch('koji_cli.commands.watch_tasks') @mock.patch('koji_cli.commands._running_in_bg') - @mock.patch('koji_cli.commands.activate_session') - def test_handle_restart_hosts_other_options( - self, activate_session_mock, running_in_bg_mock, watch_tasks_mock): + def test_handle_restart_hosts_other_options(self, running_in_bg_mock): """Test %s function with --force option""" % handle_restart_hosts.__name__ arguments = ['--nowait', '--channel', 'createrepo', '--arch', 'x86_64', '--timeout', '10'] - options = mock.MagicMock(quiet=None, poll_interval=3) - session = mock.MagicMock() # --no-wait is specified, running_in_bg() should not matter. running_in_bg_mock.return_value = True - session.getHost.return_value = None - session.restartHosts.return_value = 101 - session.logout.return_value = None + self.session.getHost.return_value = None + self.session.restartHosts.return_value = 101 + self.session.logout.return_value = None # has other restart tasks are running case - session.listTasks.return_value = [] + self.session.listTasks.return_value = [] - handle_restart_hosts(options, session, arguments) - activate_session_mock.assert_called_once() - session.listTasks.assert_called_once() + handle_restart_hosts(self.options, self.session, arguments) + self.activate_session_mock.assert_called_once() + self.session.listTasks.assert_called_once() - session.restartHosts.assert_called_with( + self.session.restartHosts.assert_called_with( options={'arches': ['x86_64'], 'timeout': 10, 'channel': 'createrepo'}) - session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.session.logout.assert_not_called() + self.watch_tasks_mock.assert_not_called() + + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands._running_in_bg') + def test_handle_restart_hosts_arguments(self, running_in_bg_mock, stderr): + """Test %s function with --force option""" % handle_restart_hosts.__name__ + + # --no-wait is specified, running_in_bg() should not matter. + running_in_bg_mock.return_value = True + + with self.assertRaises(SystemExit) as ex: + handle_restart_hosts(self.options, self.session, ['10']) + + self.assertExitCode(ex, 2) + expected_msg = """Usage: %s restart-hosts [options] +(Specify the --help global option for a list of other help options) + +%s: error: restart-hosts does not accept arguments +""" % (self.progname, self.progname) + self.assert_console_message(stderr, expected_msg) + + self.session.listTasks.assert_not_called() + self.activate_session_mock.assert_not_called() + self.session.restartHosts.assert_not_called() + self.session.logout.assert_not_called() + self.watch_tasks_mock.assert_not_called() def test_handle_restart_hosts_help(self): self.assert_help( diff --git a/tests/test_cli/test_spin_commands.py b/tests/test_cli/test_spin_commands.py index 5fb86b1..9de23e2 100644 --- a/tests/test_cli/test_spin_commands.py +++ b/tests/test_cli/test_spin_commands.py @@ -501,6 +501,16 @@ class TestSpinLiveCD(utils.CliTestCase): activate_session=None) build_image_mock.assert_not_called() + @mock.patch('koji_cli.commands._build_image') + def test_handle_spin_livecd_longer_volid(self, build_image_mock): + """Test handle_spin_livecd volid options error""" + expected = self.format_error_message("Volume ID has a maximum length of 32 characters") + volid = '12345678901234567890123456789012345' + args = ['--volid', volid, 'name', 'version', 'target', 'arch', 'file.ks'] + self.assert_system_exit(handle_spin_livecd, self.options, self.session, args, + stderr=expected, activate_session=None) + build_image_mock.assert_not_called() + def test_handle_spin_livecd_help(self): """Test handle_spin_livecd help message""" self.assert_help(