From 0e51a06add3b500a0997c3b555d9ccf1b869312f Mon Sep 17 00:00:00 2001 From: Jana Cupova Date: Nov 23 2021 11:13:17 +0000 Subject: Add and upfate CLI unit tests Fixes: https://pagure.io/koji/issue/729 --- diff --git a/tests/test_cli/test_add_channel.py b/tests/test_cli/test_add_channel.py index 0e5b048..48c1695 100644 --- a/tests/test_cli/test_add_channel.py +++ b/tests/test_cli/test_add_channel.py @@ -19,87 +19,84 @@ class TestAddChannel(utils.CliTestCase): self.channel_id = 1 self.options = mock.MagicMock() self.session = mock.MagicMock() + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-channel [options] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_channel(self, activate_session_mock, stdout): + def test_handle_add_channel(self, stdout): self.session.addChannel.return_value = self.channel_id rv = handle_add_channel(self.options, self.session, ['--description', self.description, self.channel_name]) actual = stdout.getvalue() expected = '%s added: id %s\n' % (self.channel_name, self.channel_id) self.assertMultiLineEqual(actual, 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.addChannel.assert_called_once_with(self.channel_name, description=self.description) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_channel_exist(self, activate_session_mock, stderr): + def test_handle_add_channel_exist(self): expected_api = 'channel %s already exists (id=%s)' % (self.channel_name, self.channel_id) expected = 'channel %s already exists\n' % self.channel_name self.session.addChannel.side_effect = koji.GenericError(expected_api) - with self.assertRaises(SystemExit) as ex: - handle_add_channel(self.options, self.session, - ['--description', self.description, self.channel_name]) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - self.assertMultiLineEqual(actual, expected) - activate_session_mock.assert_called_once_with(self.session, self.options) + arguments = ['--description', self.description, self.channel_name] + self.assert_system_exit( + handle_add_channel, + self.options, self.session, arguments, + stdout='', + stderr=expected, + exit_code=1, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.addChannel.assert_called_once_with(self.channel_name, description=self.description) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_channel_older_hub(self, activate_session_mock, stderr): + def test_handle_add_channel_older_hub(self): expected_api = 'Invalid method: addChannel' expected = 'addChannel is available on hub from Koji 1.26 version, your version ' \ 'is 1.25.1\n' self.session.getKojiVersion.return_value = '1.25.1' self.session.addChannel.side_effect = koji.GenericError(expected_api) - with self.assertRaises(SystemExit) as ex: - handle_add_channel(self.options, self.session, - ['--description', self.description, self.channel_name]) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - self.assertMultiLineEqual(actual, expected) - activate_session_mock.assert_called_once_with(self.session, self.options) + arguments = ['--description', self.description, self.channel_name] + self.assert_system_exit( + handle_add_channel, + self.options, self.session, arguments, + stdout='', + stderr=expected, + exit_code=1, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.addChannel.assert_called_once_with(self.channel_name, description=self.description) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_channel_without_args(self, activate_session_mock, stderr): - with self.assertRaises(SystemExit) as ex: - handle_add_channel(self.options, self.session, []) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected_stderr = """Usage: %s add-channel [options] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify one channel name -""" % (self.progname, self.progname) - self.assertMultiLineEqual(actual, expected_stderr) - activate_session_mock.assert_not_called() - - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_channel_more_args(self, activate_session_mock, stderr): + def test_handle_add_channel_without_args(self): + arguments = [] + self.assert_system_exit( + handle_add_channel, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message('Please specify one channel name'), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_not_called() + + def test_handle_add_channel_more_args(self): channel_2 = 'channel-2' - with self.assertRaises(SystemExit) as ex: - handle_add_channel(self.options, self.session, [self.channel_name, channel_2]) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected_stderr = """Usage: %s add-channel [options] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify one channel name -""" % (self.progname, self.progname) - self.assertMultiLineEqual(actual, expected_stderr) - activate_session_mock.assert_not_called() + arguments = [self.channel_name, channel_2] + self.assert_system_exit( + handle_add_channel, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message('Please specify one channel name'), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_not_called() def test_handle_add_channel_help(self): self.assert_help( diff --git a/tests/test_cli/test_add_group.py b/tests/test_cli/test_add_group.py index ed09f18..2e6a82a 100644 --- a/tests/test_cli/test_add_group.py +++ b/tests/test_cli/test_add_group.py @@ -7,12 +7,14 @@ import unittest from koji_cli.commands import handle_add_group from . import utils + class TestAddGroup(utils.CliTestCase): # Show long diffs in error output... maxDiff = None def setUp(self): + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s add-group (Specify the --help global option for a list of other help options) @@ -20,8 +22,7 @@ class TestAddGroup(utils.CliTestCase): """ % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_group(self, activate_session_mock, stdout): + def test_handle_add_group(self, stdout): tag = 'tag' group = 'group' arguments = [tag, group] @@ -41,16 +42,14 @@ class TestAddGroup(utils.CliTestCase): self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.hasPerm.assert_called_once_with('admin') session.getTag.assert_called_once_with(tag) session.getTagGroups.assert_called_once_with(tag, inherit=False) session.groupListAdd.assert_called_once_with(tag, group) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_group_dupl(self, activate_session_mock, stderr): + def test_handle_add_group_dupl(self): tag = 'tag' group = 'group' arguments = [tag, group] @@ -64,28 +63,22 @@ class TestAddGroup(utils.CliTestCase): {'name': 'group', 'group_id': 'groupId'}] # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_add_group(options, session, arguments) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'Group group already exists for tag tag\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_add_group, + options, session, arguments, + stdout='', + stderr='Group group already exists for tag tag\n', + exit_code=1, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.hasPerm.assert_called_once_with('admin') session.getTag.assert_called_once_with(tag) session.getTagGroups.assert_called_once_with(tag, inherit=False) session.groupListAdd.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_add_group_help( - self, - activate_session_mock, - stderr, - stdout): + def test_handle_add_group_help(self): arguments = [] options = mock.MagicMock() @@ -102,15 +95,13 @@ class TestAddGroup(utils.CliTestCase): activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() session.hasPerm.assert_not_called() session.getTag.assert_not_called() session.getTagGroups.assert_not_called() session.groupListAdd.assert_not_called() - @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_group_no_perm(self, activate_session_mock, stdout): + def test_handle_add_group_no_perm(self): tag = 'tag' group = 'group' arguments = [tag, group] @@ -130,16 +121,14 @@ class TestAddGroup(utils.CliTestCase): exit_code=2) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.hasPerm.assert_has_calls([mock.call('admin'), mock.call('tag')]) session.getTag.assert_not_called() session.getTagGroups.assert_not_called() session.groupListAdd.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_group_no_tag(self, activate_session_mock, stderr): + def test_handle_add_group_no_tag(self): tag = 'tag' group = 'group' arguments = [tag, group] @@ -151,15 +140,16 @@ class TestAddGroup(utils.CliTestCase): session.getTag.return_value = None # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_add_group(options, session, arguments) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such tag: tag\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_add_group, + options, session, arguments, + stdout='', + stderr='No such tag: tag\n', + exit_code=1, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.hasPerm.assert_called_once_with('admin') session.getTag.assert_called_once_with(tag) session.getTagGroups.assert_not_called() diff --git a/tests/test_cli/test_add_host.py b/tests/test_cli/test_add_host.py index 3c1320c..7a71469 100644 --- a/tests/test_cli/test_add_host.py +++ b/tests/test_cli/test_add_host.py @@ -1,8 +1,5 @@ from __future__ import absolute_import -import os -import sys - import mock import six @@ -13,12 +10,17 @@ from . import utils class TestAddHost(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None + def setUp(self): + self.maxDiff = None + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-host [options] [ ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host(self, activate_session_mock, stdout): + def test_handle_add_host(self, stdout): host = 'host' host_id = 1 arches = ['arch1', 'arch2'] @@ -41,15 +43,13 @@ class TestAddHost(utils.CliTestCase): expected = 'host added: id 1\n' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getHost.assert_called_once_with(host) session.addHost.assert_called_once_with(host, arches, **kwargs) self.assertNotEqual(rv, 1) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_no_krb_principal( - self, activate_session_mock, stdout): + def test_handle_add_host_no_krb_principal(self, stdout): host = 'host' host_id = 1 arches = ['arch1', 'arch2'] @@ -68,14 +68,12 @@ class TestAddHost(utils.CliTestCase): expected = 'host added: id 1\n' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getHost.assert_called_once_with(host) session.addHost.assert_called_once_with(host, arches, force=False) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_dupl(self, activate_session_mock, stderr): + def test_handle_add_host_dupl(self): host = 'host' host_id = 1 arches = ['arch1', 'arch2'] @@ -90,45 +88,36 @@ class TestAddHost(utils.CliTestCase): # Run it and check immediate output # args: host, arch1, arch2, --krb-principal=krb # expected: failed, host already exists - with self.assertRaises(SystemExit) as ex: - handle_add_host(options, session, arguments) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'host is already in the database\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_add_host, + options, session, arguments, + stdout='', + stderr='host is already in the database\n', + exit_code=1, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getHost.assert_called_once_with(host) session.addHost.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_add_host_without_args(self, activate_session_mock, stderr, stdout): + def test_handle_add_host_without_args(self): arguments = [] options = mock.MagicMock() - progname = os.path.basename(sys.argv[0]) or 'koji' # Mock out the xmlrpc server session = mock.MagicMock() # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_add_host(options, session, arguments) - self.assertExitCode(ex, 2) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() - expected_stdout = '' - expected_stderr = """Usage: %s add-host [options] [ ...] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify a hostname and at least one arch -""" % (progname, progname) - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_add_host, + options, session, arguments, + stdout='', + stderr=self.format_error_message('Please specify a hostname and at least one arch'), + exit_code=2, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() session.hasHost.assert_not_called() session.addHost.assert_not_called() @@ -147,8 +136,7 @@ Options: """ % self.progname) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_failed(self, activate_session_mock, stderr): + def test_handle_add_host_failed(self, stderr): host = 'host' arches = ['arch1', 'arch2'] krb_principal = '--krb-principal=krb' @@ -171,6 +159,6 @@ Options: expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getHost.assert_called_once_with(host) session.addHost.assert_called_once_with(host, arches, **kwargs) diff --git a/tests/test_cli/test_add_host_to_channel.py b/tests/test_cli/test_add_host_to_channel.py index 0ca6681..1f47aa0 100644 --- a/tests/test_cli/test_add_host_to_channel.py +++ b/tests/test_cli/test_add_host_to_channel.py @@ -1,9 +1,7 @@ from __future__ import absolute_import import mock -import os import six -import sys import unittest from koji_cli.commands import handle_add_host_to_channel @@ -12,12 +10,17 @@ from . import utils class TestAddHostToChannel(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None + def setUp(self): + self.maxDiff = None + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-host-to-channel [options] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel(self, activate_session_mock, stdout): + def test_handle_add_host_to_channel(self, stdout): host = 'host' host_info = mock.ANY channel = 'channel' @@ -38,16 +41,14 @@ class TestAddHostToChannel(utils.CliTestCase): expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getChannel.assert_called_once_with(channel) session.getHost.assert_called_once_with(host) session.addHostToChannel.assert_called_once_with(host, channel) self.assertNotEqual(rv, 1) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel_list( - self, activate_session_mock, stdout): + def test_handle_add_host_to_channel_list(self, stdout): list_arg = '--list' args = [list_arg] channel_infos = [{'name': 'channel1'}, {'name': 'channel2'}] @@ -65,7 +66,7 @@ class TestAddHostToChannel(utils.CliTestCase): expected = 'channel1\nchannel2\n' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.listChannels.assert_called_once() session.getChannel.assert_not_called() session.getHost.assert_not_called() @@ -73,9 +74,7 @@ class TestAddHostToChannel(utils.CliTestCase): self.assertNotEqual(rv, 1) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel_new_and_force( - self, activate_session_mock, stdout): + def test_handle_add_host_to_channel_new_and_force(self, stdout): host = 'host' host_info = mock.ANY channel = 'channel' @@ -96,20 +95,17 @@ class TestAddHostToChannel(utils.CliTestCase): expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.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, force=True) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel_no_channel( - self, activate_session_mock, stderr): + def test_handle_add_host_to_channel_no_channel(self): host = 'host' channel = 'channel' channel_info = None - args = [host, channel] + arguments = [host, channel] options = mock.MagicMock() # Mock out the xmlrpc server @@ -119,27 +115,25 @@ class TestAddHostToChannel(utils.CliTestCase): # Run it and check immediate output # args: host, channel # expected: failed, channel not found - with self.assertRaises(SystemExit) as ex: - handle_add_host_to_channel(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such channel: channel\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_add_host_to_channel, + options, session, arguments, + stdout='', + stderr='No such channel: channel\n', + exit_code=1, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getChannel.assert_called_once_with(channel) session.getHost.assert_not_called() session.addHostToChannel.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_host_to_channel_no_host( - self, activate_session_mock, stderr): + def test_handle_add_host_to_channel_no_host(self): host = 'host' host_info = None channel = 'channel' channel_info = mock.ANY - args = [host, channel] + arguments = [host, channel] options = mock.MagicMock() # Mock out the xmlrpc server @@ -150,14 +144,15 @@ class TestAddHostToChannel(utils.CliTestCase): # Run it and check immediate output # args: host, channel # expected: success - with self.assertRaises(SystemExit) as ex: - handle_add_host_to_channel(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such host: host\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_add_host_to_channel, + options, session, arguments, + stdout='', + stderr='No such host: host\n', + exit_code=1, + activate_session=None) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(session, options) session.getChannel.assert_called_once_with(channel) session.getHost.assert_called_once_with(host) session.addHostToChannel.assert_not_called() @@ -167,9 +162,8 @@ class TestAddHostToChannel(utils.CliTestCase): @mock.patch('koji_cli.commands.activate_session') def test_handle_add_host_to_channel_help( self, activate_session_mock, stderr, stdout): - args = [] + arguments = [] options = mock.MagicMock() - progname = os.path.basename(sys.argv[0]) or 'koji' # Mock out the xmlrpc server session = mock.MagicMock() @@ -177,19 +171,13 @@ class TestAddHostToChannel(utils.CliTestCase): # Run it and check immediate output # args: _empty_ # expected: failed, help msg shows - with self.assertRaises(SystemExit) as ex: - handle_add_host_to_channel(options, session, args) - self.assertExitCode(ex, 2) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() - expected_stdout = '' - expected_stderr = """Usage: %s add-host-to-channel [options] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify a hostname and a channel -""" % (progname, progname) - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_add_host_to_channel, + options, session, arguments, + stdout='', + stderr=self.format_error_message("Please specify a hostname and a channel"), + exit_code=2, + activate_session=None) # Finally, assert that things were called as we expected. activate_session_mock.assert_not_called() diff --git a/tests/test_cli/test_add_notification.py b/tests/test_cli/test_add_notification.py index 577a45c..212c97d 100644 --- a/tests/test_cli/test_add_notification.py +++ b/tests/test_cli/test_add_notification.py @@ -6,6 +6,7 @@ from six.moves import StringIO from koji_cli.commands import handle_add_notification from . import utils + class TestAddNotification(utils.CliTestCase): def setUp(self): self.options = mock.MagicMock() @@ -13,25 +14,29 @@ class TestAddNotification(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-notification [options] +(Specify the --help global option for a list of other help options) +%s: error: {message} +""" % (self.progname, self.progname) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_notification(self, activate_session_mock): + def test_handle_add_notification(self): self.session.getPackageID.return_value = 1234 self.session.getTagID.return_value = 4321 self.session.getLoggedInUser.return_value = {'id': 678} - handle_add_notification(self.options, self.session, ['--package', 'pkg_a', '--tag', 'tag_a', '--success-only']) + handle_add_notification(self.options, self.session, + ['--package', 'pkg_a', '--tag', 'tag_a', '--success-only']) self.session.getPackageID.assert_called_once_with('pkg_a') self.session.getTagID.assert_called_once_with('tag_a', strict=True) self.session.getLoggedInUser.assert_called_once_with() self.session.getUser.assert_not_called() self.session.createNotification.assert_called_once_with(678, 1234, 4321, True) + self.activate_session_mock.assert_called_once_with(self.session, self.options) - - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_notification_no_pkg(self, activate_session_mock): + def test_handle_add_notification_no_pkg(self,): self.session.getTagID.return_value = 4321 self.session.getLoggedInUser.return_value = {'id': 678} @@ -42,10 +47,9 @@ class TestAddNotification(utils.CliTestCase): self.session.getLoggedInUser.assert_called_once_with() self.session.getUser.assert_not_called() self.session.createNotification.assert_called_once_with(678, None, 4321, True) + self.activate_session_mock.assert_called_once_with(self.session, self.options) - - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_notification_no_tag(self, activate_session_mock): + def test_handle_add_notification_no_tag(self): self.session.getPackageID.return_value = 1234 self.session.getLoggedInUser.return_value = {'id': 678} @@ -56,87 +60,104 @@ class TestAddNotification(utils.CliTestCase): self.session.getLoggedInUser.assert_called_once_with() self.session.getUser.assert_not_called() self.session.createNotification.assert_called_once_with(678, 1234, None, False) - + self.activate_session_mock.assert_called_once_with(self.session, self.options) @mock.patch('sys.exit') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_no_pkg_no_tag(self, sys_stderr, sys_exit): + def test_handle_add_notification_no_pkg_no_tag(self, sys_exit): sys_exit.side_effect = SystemExit() + arguments = ['--success-only'] - with self.assertRaises(SystemExit): - handle_add_notification(self.options, self.session, ['--success-only']) + self.assert_system_exit( + handle_add_notification, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message( + "Command need at least one from --tag or --package options."), + exit_code=None, + activate_session=None) self.session.getPackageID.assert_not_called() self.session.getTagID.assert_not_called() self.session.getLoggedInUser.assert_not_called() self.session.getUser.assert_not_called() self.session.createNotification.assert_not_called() - + self.activate_session_mock.assert_not_called() @mock.patch('sys.exit') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_user_no_admin(self, sys_stderr, sys_exit): + def test_handle_add_notification_user_no_admin(self, sys_exit): sys_exit.side_effect = SystemExit() self.session.hasPerm.return_value = False + arguments = ['--user', 'username', '--tag', 'tag_a'] - with self.assertRaises(SystemExit): - handle_add_notification(self.options, self.session, ['--user', 'username', '--tag', 'tag_a']) + self.assert_system_exit( + handle_add_notification, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message('--user requires admin permission'), + exit_code=None, + activate_session=None) self.session.getPackageID.assert_not_called() self.session.getTagID.assert_not_called() self.session.getLoggedInUser.assert_not_called() self.session.getUser.assert_not_called() self.session.createNotification.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) - - @mock.patch('sys.exit') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_user_admin(self, sys_stderr, sys_exit): + def test_handle_add_notification_user_admin(self): self.session.hasPerm.return_value = True self.session.getPackageID.return_value = 1234 self.session.getUser.return_value = {'id': 789} - handle_add_notification(self.options, self.session, ['--package', 'pkg_a', '--user', 'username']) + handle_add_notification(self.options, self.session, + ['--package', 'pkg_a', '--user', 'username']) self.session.getPackageID.assert_called_once_with('pkg_a') self.session.getTagID.assert_not_called() self.session.getLoggedInUser.assert_not_called() self.session.getUser.assert_called_once_with('username') self.session.createNotification.assert_called_once_with(789, 1234, None, False) + self.activate_session_mock.assert_called_once_with(self.session, self.options) - - @mock.patch('sys.exit') @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_args(self, sys_stderr, sys_exit): + def test_handle_add_notification_args(self, sys_exit): sys_exit.side_effect = SystemExit() - - with self.assertRaises(SystemExit): - handle_add_notification(self.options, self.session, ['bogus']) + arguments = ['bogus'] + self.assert_system_exit( + handle_add_notification, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("This command takes no arguments"), + exit_code=2, + activate_session=None) self.session.createNotification.assert_not_called() + self.activate_session_mock.assert_not_called() - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_non_exist_tag(self, stderr): + def test_handle_add_notification_non_exist_tag(self): tag = 'tag_a' - expected = "Usage: %s add-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such tag: %s\n" % (self.progname, self.progname, tag) + arguments = ['--tag', tag] self.session.getTagID.side_effect = koji.GenericError - with self.assertRaises(SystemExit) as ex: - handle_add_notification(self.options, self.session, ['--tag', tag]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_add_notification_non_exist_pkg(self, stderr): + self.assert_system_exit( + handle_add_notification, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message('No such tag: %s' % tag), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_handle_add_notification_non_exist_pkg(self): pkg = 'pkg_a' - expected = "Usage: %s add-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such package: %s\n" % (self.progname, self.progname, pkg) + arguments = ['--package', pkg] self.session.getPackageID.return_value = None - with self.assertRaises(SystemExit) as ex: - handle_add_notification(self.options, self.session, ['--package', pkg]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) + self.assert_system_exit( + handle_add_notification, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message('No such package: %s' % pkg), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) diff --git a/tests/test_cli/test_add_tag.py b/tests/test_cli/test_add_tag.py index 4a56a39..c5d8640 100644 --- a/tests/test_cli/test_add_tag.py +++ b/tests/test_cli/test_add_tag.py @@ -1,6 +1,5 @@ from __future__ import absolute_import import mock -import six import unittest from koji_cli.commands import handle_add_tag @@ -9,45 +8,42 @@ from . import utils class TestAddTag(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None - def setUp(self): + self.maxDiff = None + self.options = mock.MagicMock() + self.options.quiet = True + self.options.debug = False + self.session = mock.MagicMock() + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s add-tag [options] (Specify the --help global option for a list of other help options) %s: error: {message} """ % (self.progname, self.progname) - @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_tag( - self, - activate_session_mock, - stdout): + def test_handle_add_tag(self): """Test handle_add_tag function""" - session = mock.MagicMock() - options = mock.MagicMock() - # Case 1. no argument error - expected = self.format_error_message( - "Please specify a name for the tag") self.assert_system_exit( handle_add_tag, - options, - session, - [], - stderr=expected, + self.options, self.session, [], + stderr=self.format_error_message("Please specify a name for the tag"), + exit_code=2, activate_session=None) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 2. not admin account - session.hasPerm.return_value = None + self.session.hasPerm.return_value = None self.assert_system_exit( handle_add_tag, - options, session, ['test-tag'], + self.options, self.session, ['test-tag'], stdout='', stderr=self.format_error_message("This action requires tag or admin privileges"), + exit_code=2, ) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 3. options test arguments = ['test-tag', @@ -70,9 +66,10 @@ class TestAddTag(utils.CliTestCase): } } - session.hasPerm.return_value = True - handle_add_tag(options, session, arguments) - session.createTag.assert_called_with('test-tag', **opts) + self.session.hasPerm.return_value = True + handle_add_tag(self.options, self.session, arguments) + self.session.createTag.assert_called_with('test-tag', **opts) + self.activate_session_mock.assert_called_once_with(self.session, self.options) def test_handle_add_tag_help(self): self.assert_help( diff --git a/tests/test_cli/test_add_tag_inheritance.py b/tests/test_cli/test_add_tag_inheritance.py index 5d45881..0e146c4 100644 --- a/tests/test_cli/test_add_tag_inheritance.py +++ b/tests/test_cli/test_add_tag_inheritance.py @@ -1,6 +1,5 @@ from __future__ import absolute_import -from six.moves import StringIO import mock import koji @@ -14,34 +13,43 @@ class TestAddTagInheritance(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-tag-inheritance [options] +(Specify the --help global option for a list of other help options) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_tag_inheritance_without_option(self, stderr): - expected = "Usage: %s add-tag-inheritance [options] \n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: This command takes exctly two argument: " \ - "a tag name or ID and that tag's new parent name " \ - "or ID\n" % (self.progname, self.progname) - with self.assertRaises(SystemExit) as ex: - handle_add_tag_inheritance(self.options, self.session, []) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) +%s: error: {message} +""" % (self.progname, self.progname) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_tag_inheritance_non_exist_tag(self, stderr): + def test_add_tag_inheritance_without_option(self): + arguments = [] + expected = self.format_error_message( + "This command takes exctly two argument: a tag name or ID and that tag's new " + "parent name or ID") + self.assert_system_exit( + handle_add_tag_inheritance, + self.options, self.session, arguments, + stdout='', + stderr=expected, + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_not_called() + + def test_add_tag_inheritance_non_exist_tag(self): tag = 'test-tag' parent_tag = 'parent-test-tag' - expected = "Usage: %s add-tag-inheritance [options] \n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such tag: %s\n" % (self.progname, self.progname, tag) + arguments = [tag, parent_tag] self.session.getTag.return_value = None - with self.assertRaises(SystemExit) as ex: - handle_add_tag_inheritance(self.options, self.session, [tag, parent_tag]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_tag_inheritance_non_exist_parent_tag(self, stderr): + self.assert_system_exit( + handle_add_tag_inheritance, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("No such tag: %s" % tag), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_add_tag_inheritance_non_exist_parent_tag(self): side_effect_result = [{'arches': 'x86_64', 'extra': {}, 'id': 1, @@ -54,11 +62,13 @@ class TestAddTagInheritance(utils.CliTestCase): None] tag = 'test-tag' parent_tag = 'parent-test-tag' - expected = "Usage: %s add-tag-inheritance [options] \n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such tag: %s\n" % (self.progname, self.progname, parent_tag) + arguments = [tag, parent_tag] self.session.getTag.side_effect = side_effect_result - with self.assertRaises(SystemExit) as ex: - handle_add_tag_inheritance(self.options, self.session, [tag, parent_tag]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) + self.assert_system_exit( + handle_add_tag_inheritance, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("No such tag: %s" % parent_tag), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) diff --git a/tests/test_cli/test_add_target.py b/tests/test_cli/test_add_target.py index 18a2858..a453cdc 100644 --- a/tests/test_cli/test_add_target.py +++ b/tests/test_cli/test_add_target.py @@ -1,7 +1,6 @@ from __future__ import absolute_import import mock -from six.moves import StringIO import koji from koji_cli.commands import handle_add_target @@ -14,32 +13,41 @@ class TestAddTarget(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s add-target +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_without_option(self, stderr): - expected = "Usage: %s add-target \n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: Please specify a target name, a build tag, " \ - "and destination tag\n" % (self.progname, self.progname) - with self.assertRaises(SystemExit) as ex: - handle_add_target(self.options, self.session, []) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_non_exist_tag(self, stderr): + def test_add_target_without_option(self,): + expected = self.format_error_message( + "Please specify a target name, a build tag, and destination tag") + self.assert_system_exit( + handle_add_target, + self.options, self.session, [], + stdout='', + stderr=expected, + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_not_called() + + def test_add_target_non_exist_tag(self): target = 'test-target' tag = 'test-tag' dest_tag = 'test-dest-tag' - expected = "No such tag: %s\n" % tag + arguments = [target, tag, dest_tag] self.session.getTag.return_value = None - with self.assertRaises(SystemExit) as ex: - handle_add_target(self.options, self.session, [target, tag, dest_tag]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_tag_without_arch(self, stderr): + self.assert_system_exit( + handle_add_target, + self.options, self.session, arguments, + stdout='', + stderr="No such tag: %s\n" % tag, + exit_code=1, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_add_target_tag_without_arch(self,): tag_info = {'arches': None, 'extra': {}, 'id': 1, @@ -52,15 +60,18 @@ class TestAddTarget(utils.CliTestCase): target = 'test-target' tag = 'test-tag' dest_tag = 'test-dest-tag' - expected = "Build tag has no arches: %s\n" % tag self.session.getTag.return_value = tag_info - with self.assertRaises(SystemExit) as ex: - handle_add_target(self.options, self.session, [target, tag, dest_tag]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_non_exist_dest_tag(self, stderr): + arguments = [target, tag, dest_tag] + self.assert_system_exit( + handle_add_target, + self.options, self.session, arguments, + stdout='', + stderr="Build tag has no arches: %s\n" % tag, + exit_code=1, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_add_target_non_exist_dest_tag(self): side_effect_result = [{'arches': 'x86_64', 'extra': {}, 'id': 1, @@ -77,23 +88,27 @@ class TestAddTarget(utils.CliTestCase): target = 'test-target' tag = 'test-tag' dest_tag = 'test-dest-tag' - expected = "No such destination tag: %s\n" % dest_tag self.session.getTag.side_effect = side_effect_result - with self.assertRaises(SystemExit) as ex: - handle_add_target(self.options, self.session, [target, tag, dest_tag]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_more_option(self, stderr): - args = ['test-target', 'tag', 'test-dest-tag', 'tag-2'] - expected = "Usage: %s add-target \n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: Incorrect number of arguments\n" % (self.progname, self.progname) - with self.assertRaises(SystemExit) as ex: - handle_add_target(self.options, self.session, args) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) + arguments = [target, tag, dest_tag] + self.assert_system_exit( + handle_add_target, + self.options, self.session, arguments, + stdout='', + stderr="No such destination tag: %s\n" % dest_tag, + exit_code=1, + activate_session=None) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_add_target_more_option(self): + arguments = ['test-target', 'tag', 'test-dest-tag', 'tag-2'] + self.assert_system_exit( + handle_add_target, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("Incorrect number of arguments"), + exit_code=2, + activate_session=None) + self.activate_session_mock.assert_not_called() def test_add_target_valid(self): side_effect_result = [{'arches': 'x86_64', @@ -126,25 +141,25 @@ class TestAddTarget(utils.CliTestCase): self.assertEqual(rv, None) self.session.createBuildTarget.assert_called_once_with(target, tag, target) self.session.getTag.assert_called_with(target) + self.activate_session_mock.assert_called_once_with(self.session, self.options) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_add_target_without_perms(self, stderr): + def test_add_target_without_perms(self): 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) + arguments = [target, tag] + self.assert_system_exit( + handle_add_target, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("This action requires target or admin privileges"), + exit_code=2, + activate_session=None) self.session.createBuildTarget.assert_not_called() self.session.getTag.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) def test_add_target_help(self): self.assert_help( diff --git a/tests/test_cli/test_add_user.py b/tests/test_cli/test_add_user.py index d0604da..a7099d7 100644 --- a/tests/test_cli/test_add_user.py +++ b/tests/test_cli/test_add_user.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import mock import six import unittest +import koji from koji_cli.commands import handle_add_user from . import utils @@ -13,6 +14,11 @@ class TestAddUser(utils.CliTestCase): maxDiff = None def setUp(self): + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s add-user [options] (Specify the --help global option for a list of other help options) @@ -20,14 +26,8 @@ class TestAddUser(utils.CliTestCase): """ % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_user( - self, - activate_session_mock, - stdout): + def test_handle_add_user(self, stdout): """Test handle_add_user function""" - session = mock.MagicMock() - options = mock.MagicMock() username = 'user' user_id = 1001 principal = 'krb-pricipal' @@ -37,44 +37,49 @@ class TestAddUser(utils.CliTestCase): "You must specify the username of the user to add") self.assert_system_exit( handle_add_user, - options, - session, - [], + self.options, self.session, [], + stdout='', stderr=expected, + exit_code=2, activate_session=None) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 2. Too many argument error expected = self.format_error_message( "This command only accepts one argument (username)") self.assert_system_exit( handle_add_user, - options, - session, - ['user-1', 'user-2', 'user-3'], + self.options, self.session, ['user-1', 'user-2', 'user-3'], + stdout='', stderr=expected, + exit_code=2, activate_session=None) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 3. Add user test expected = "Added user %s (%i)" % (username, user_id) + "\n" arguments = [username, '--principal', principal] - session.createUser.return_value = user_id - handle_add_user(options, session, arguments) - session.createUser.assert_called_with( + self.session.createUser.return_value = user_id + handle_add_user(self.options, self.session, arguments) + self.session.createUser.assert_called_with( username, status=0, krb_principal=principal) self.assert_console_message(stdout, expected) - activate_session_mock.assert_called_with(session, options) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.activate_session_mock.reset_mock() # Case 3. Add blocked user arguments = [username, '--principal', principal, '--disable'] - handle_add_user(options, session, arguments) - session.createUser.assert_called_with( + handle_add_user(self.options, self.session, arguments) + self.session.createUser.assert_called_with( username, status=1, # 0: normal, 1: disabled krb_principal=principal) self.assert_console_message(stdout, expected) - activate_session_mock.assert_called_with(session, options) + self.activate_session_mock.assert_called_with(self.session, self.options) def test_handle_add_user_help(self): self.assert_help( diff --git a/tests/test_cli/test_add_volume.py b/tests/test_cli/test_add_volume.py index dceff3b..5fa8436 100644 --- a/tests/test_cli/test_add_volume.py +++ b/tests/test_cli/test_add_volume.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import mock import six import unittest +import koji from koji_cli.commands import handle_add_volume from . import utils @@ -9,60 +10,59 @@ from . import utils class TestAddVolume(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None - def setUp(self): + # Show long diffs in error output... + self.maxDiff = None + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s add-volume (Specify the --help global option for a list of other help options) %s: error: {message} """ % (self.progname, self.progname) - @mock.patch('sys.stderr', new_callable=six.StringIO) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_add_volume( - self, - activate_session_mock, - stdout, - stderr): + def test_handle_add_volume(self, stdout): """Test handle_add_volume function""" - session = mock.MagicMock() - options = mock.MagicMock() vol_name = 'vol-test-01' vol_info = {'id': 1, 'name': vol_name} # Case 1. argument error - expected = self.format_error_message( - "Command requires exactly one volume-name.") for arg in [[], ['test-1', 'test-2']]: self.assert_system_exit( handle_add_volume, - options, - session, - arg, - stderr=expected, + self.options, self.session, arg, + stdout='', + stderr=self.format_error_message("Command requires exactly one volume-name."), + exit_code=2, activate_session=None) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 2. volume already exists - expected = "Volume %s already exists" % vol_name + "\n" - session.getVolume.return_value = vol_info - with self.assertRaises(SystemExit) as ex: - handle_add_volume(options, session, [vol_name]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected) - session.getVolume.assert_called_with(vol_name) - activate_session_mock.assert_not_called() + self.session.getVolume.return_value = vol_info + self.assert_system_exit( + handle_add_volume, + self.options, self.session, [vol_name], + stdout='', + stderr="Volume %s already exists" % vol_name + "\n", + exit_code=1, + activate_session=None) + self.session.getVolume.assert_called_with(vol_name) + self.activate_session_mock.assert_not_called() + self.activate_session_mock.reset_mock() # Case 3. Add volume expected = "Added volume %(name)s with id %(id)i" % vol_info + "\n" - session.getVolume.return_value = {} - session.addVolume.return_value = vol_info - handle_add_volume(options, session, [vol_name]) + self.session.getVolume.return_value = {} + self.session.addVolume.return_value = vol_info + handle_add_volume(self.options, self.session, [vol_name]) self.assert_console_message(stdout, expected) - session.addVolume(vol_name) - activate_session_mock.assert_called_with(session, options) + self.session.addVolume(vol_name) + self.activate_session_mock.assert_called_with(self.session, self.options) def test_handle_add_volume_help(self): self.assert_help( diff --git a/tests/test_cli/test_assign_task.py b/tests/test_cli/test_assign_task.py index c7ab2d3..53c69bc 100644 --- a/tests/test_cli/test_assign_task.py +++ b/tests/test_cli/test_assign_task.py @@ -10,10 +10,14 @@ from . import utils class TestAssignTask(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None - def setUp(self): + # Show long diffs in error output... + self.maxDiff = None + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s assign-task (Specify the --help global option for a list of other help options) @@ -21,44 +25,40 @@ class TestAssignTask(utils.CliTestCase): """ % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_assign_task( - self, activate_session_mock, stdout): + def test_handle_assign_task(self, stdout): hostname = "host" task_id = "1" arguments = [task_id, hostname] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.getTaskInfo.return_value = None + self.session.getTaskInfo.return_value = None with six.assertRaisesRegex(self, koji.GenericError, "No such task: %s" % task_id): - handle_assign_task(options, session, arguments) + handle_assign_task(self.options, self.session, arguments) - session.getTaskInfo.return_value = "task_info" - session.getHost.return_value = None + self.session.getTaskInfo.return_value = "task_info" + self.session.getHost.return_value = None with six.assertRaisesRegex(self, koji.GenericError, "No such host: %s" % hostname): - handle_assign_task(options, session, arguments) + handle_assign_task(self.options, self.session, arguments) arguments.append("--force") - session.getHost.return_value = hostname - session.hasPerm.return_value = False + self.session.getHost.return_value = hostname + self.session.hasPerm.return_value = False self.assert_system_exit( handle_assign_task, - options, session, arguments, - stderr=self.format_error_message("This action requires admin privileges") + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("This action requires admin privileges"), + exit_code=2 ) # Clean stdout buffer stdout.truncate(0) stdout.seek(0) - session.hasPerm.return_value = True - session.assignTask.return_value = True - handle_assign_task(options, session, arguments) + self.session.hasPerm.return_value = True + self.session.assignTask.return_value = True + handle_assign_task(self.options, self.session, arguments) actual = stdout.getvalue() expected = 'assigned task %s to host %s\n' % \ (task_id, hostname) @@ -68,32 +68,23 @@ class TestAssignTask(utils.CliTestCase): stdout.truncate(0) stdout.seek(0) - session.assignTask.return_value = False - handle_assign_task(options, session, arguments) + self.session.assignTask.return_value = False + handle_assign_task(self.options, self.session, arguments) actual = stdout.getvalue() expected = 'failed to assign task %s to host %s\n' % \ (task_id, hostname) self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_with(session, options) - session.assignTask.assert_called_with(int(task_id), hostname, True) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.session.assignTask.assert_called_with(int(task_id), hostname, True) - @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_assign_task_help( - self, activate_session_mock, stderr, stdout): + def test_handle_assign_task_help(self): arguments = [] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - # Run it and check immediate output self.assert_system_exit( handle_assign_task, - options, session, arguments, + self.options, self.session, arguments, stdout='', stderr=self.format_error_message('please specify a task id and a hostname'), activate_session=None, @@ -101,9 +92,9 @@ class TestAssignTask(utils.CliTestCase): ) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() - session.hasHost.assert_not_called() - session.addHost.assert_not_called() + self.activate_session_mock.assert_not_called() + self.session.hasHost.assert_not_called() + self.session.addHost.assert_not_called() if __name__ == '__main__': diff --git a/tests/test_cli/test_block_group.py b/tests/test_cli/test_block_group.py index a755427..e3583a5 100644 --- a/tests/test_cli/test_block_group.py +++ b/tests/test_cli/test_block_group.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import mock import six +import koji from koji_cli.commands import handle_block_group from . import utils @@ -12,123 +13,108 @@ class TestBlockGroup(utils.CliTestCase): maxDiff = None def setUp(self): + self.maxDiff = None + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s block-group (Specify the --help global option for a list of other help options) %s: error: {message} """ % (self.progname, self.progname) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_group_nonexistent_tag(self, activate_session_mock, stderr): + def test_handle_block_group_nonexistent_tag(self): tag = 'nonexistent-tag' group = 'group' arguments = [tag, group] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.hasPerm.return_value = True - session.getTag.return_value = None + self.session.hasPerm.return_value = True + self.session.getTag.return_value = None # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_block_group(options, session, arguments) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such tag: %s\n' % tag - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_block_group, + self.options, self.session, arguments, + stderr='No such tag: %s\n' % tag, + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.hasPerm.assert_called_once_with('admin') - session.getTag.assert_called_once_with(tag) - session.getTagGroups.assert_not_called() - session.groupListBlock.assert_not_called() - - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_group_nonexistent_group(self, activate_session_mock, stderr): + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.hasPerm.assert_called_once_with('admin') + self.session.getTag.assert_called_once_with(tag) + self.session.getTagGroups.assert_not_called() + self.session.groupListBlock.assert_not_called() + + def test_handle_block_group_nonexistent_group(self): tag = 'tag' group = 'group' arguments = [tag, group] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.hasPerm.return_value = True - session.getTag.return_value = tag - session.getTagGroups.return_value = [] + self.session.hasPerm.return_value = True + self.session.getTag.return_value = tag + self.session.getTagGroups.return_value = [] # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_block_group(options, session, arguments) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = "Group %s doesn't exist within tag %s\n" % (group, tag) - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_block_group, + self.options, self.session, arguments, + stderr="Group %s doesn't exist within tag %s\n" % (group, tag), + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.hasPerm.assert_called_once_with('admin') - session.getTag.assert_called_once_with(tag) - session.getTagGroups.assert_called_once_with(tag, inherit=False) - session.groupListBlock.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.hasPerm.assert_called_once_with('admin') + self.session.getTag.assert_called_once_with(tag) + self.session.getTagGroups.assert_called_once_with(tag, inherit=False) + self.session.groupListBlock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_group(self, activate_session_mock, stdout): + def test_handle_block_group(self, stdout): tag = 'tag' group = 'group' arguments = [tag, group] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.hasPerm.return_value = True - session.getTag.return_value = tag - session.getTagGroups.return_value = [ + self.session.hasPerm.return_value = True + self.session.getTag.return_value = tag + self.session.getTagGroups.return_value = [ {'name': 'group', 'group_id': 'groupId'}] # Run it and check immediate output - rv = handle_block_group(options, session, arguments) + rv = handle_block_group(self.options, self.session, arguments) actual = stdout.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.hasPerm.assert_called_once_with('admin') - session.getTag.assert_called_once_with(tag) - session.getTagGroups.assert_called_once_with(tag, inherit=False) - session.groupListBlock.assert_called_once_with(tag, group) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.hasPerm.assert_called_once_with('admin') + self.session.getTag.assert_called_once_with(tag) + self.session.getTagGroups.assert_called_once_with(tag, inherit=False) + self.session.groupListBlock.assert_called_once_with(tag, group) self.assertEqual(rv, None) - @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_group_error_handling(self, activate_session_mock, stdout): - session = mock.MagicMock() - options = mock.MagicMock() - + def test_handle_block_group_error_handling(self): expected = self.format_error_message( - "Please specify a tag name and a group name") + "Please specify a tag name and a group name") for args in [[], ['tag'], ['tag', 'grp', 'etc']]: self.assert_system_exit( handle_block_group, - options, - session, - args, + self.options, self.session, args, stderr=expected, + stdout='', activate_session=None, exit_code=2) # if we don't have 'admin' permission - session.hasPerm.return_value = False + self.session.hasPerm.return_value = False self.assert_system_exit( handle_block_group, - options, session, ['tag', 'grp'], + self.options, self.session, ['tag', 'grp'], stderr=self.format_error_message('This action requires tag or admin privileges'), stdout='', exit_code=2, activate_session=None) - activate_session_mock.assert_called_with(session, options) + self.activate_session_mock.assert_called_with(self.session, self.options) diff --git a/tests/test_cli/test_block_notification.py b/tests/test_cli/test_block_notification.py index 236cb95..6d93145 100644 --- a/tests/test_cli/test_block_notification.py +++ b/tests/test_cli/test_block_notification.py @@ -14,80 +14,77 @@ class TestBlockNotification(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s block-notification [options] +(Specify the --help global option for a list of other help options) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_non_exist_tag(self, stderr): +%s: error: {message} +""" % (self.progname, self.progname) + + def test_handle_block_notification_non_exist_tag(self): tag = 'test-tag' - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such tag: %s\n" % (self.progname, self.progname, tag) + arguments = ['--tag', tag] self.session.getTagID.side_effect = koji.GenericError - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--tag', tag]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_non_exist_pkg(self, stderr): + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("No such tag: %s" % tag), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_handle_block_notification_non_exist_pkg(self): pkg = 'test-pkg' - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: No such package: %s\n" % (self.progname, self.progname, pkg) - + arguments = ['--package', pkg] self.session.getPackageID.return_value = None - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--package', pkg]) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_with_args(self, stderr, activate_session): - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: This command takes no arguments\n" \ - % (self.progname, self.progname) - - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['1234']) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - activate_session.assert_not_called() - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_with_user_only(self, stderr, activate_session): - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: One of --tag, --package or --all must be specified.\n" \ - % (self.progname, self.progname) - - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--user', 'testuser']) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - activate_session.assert_not_called() - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_with_user_non_admin_tag(self, stderr, activate_session): - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: --user requires admin permission\n" \ - % (self.progname, self.progname) - + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("No such package: %s" % pkg), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_handle_block_notification_with_args(self): + arguments = ['1234'] + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("This command takes no arguments"), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_not_called() + + def test_handle_block_notification_with_user_only(self): + arguments = ['--user', 'testuser'] + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message( + "One of --tag, --package or --all must be specified."), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_not_called() + + def test_handle_block_notification_with_user_non_admin_tag(self): + arguments = ['--user', 'testuser', '--tag', 'tagtest'] self.session.hasPerm.return_value = False - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--user', 'testuser', - '--tag', 'tagtest']) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - activate_session.assert_called_once_with(self.session, self.options) - - @mock.patch('koji_cli.commands.activate_session') + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("--user requires admin permission"), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + @mock.patch('sys.stdout', new_callable=StringIO) - def test_handle_block_notification_with_user_pkg(self, stdout, activate_session): + def test_handle_block_notification_with_user_pkg(self, stdout): expected = "" self.session.hasPerm.return_value = True @@ -100,31 +97,21 @@ class TestBlockNotification(utils.CliTestCase): '--package', 'pkgtest']) self.assert_console_message(stdout, expected) - activate_session.assert_called_once_with(self.session, self.options) - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_without_user_not_logged(self, stderr, activate_session): - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: Please login with authentication or specify --user\n" \ - % (self.progname, self.progname) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + def test_handle_block_notification_without_user_not_logged(self): + arguments = ['--tag', 'tagtest'] self.session.getLoggedInUser.return_value = None - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--tag', 'tagtest']) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - activate_session.assert_called_once_with(self.session, self.options) - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('sys.stderr', new_callable=StringIO) - def test_handle_block_notification_existing_block(self, stderr, activate_session): - expected = "Usage: %s block-notification [options]\n" \ - "(Specify the --help global option for a list of other help options)\n\n" \ - "%s: error: Notification already exists.\n" \ - % (self.progname, self.progname) - + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("Please login with authentication or specify --user"), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) + + def test_handle_block_notification_existing_block(self): self.session.hasPerm.return_value = True self.session.getUser.return_value = {'id': 2, 'krb_principals': [], 'name': 'testuser', 'status': 0, 'usertype': 0} @@ -133,11 +120,12 @@ class TestBlockNotification(utils.CliTestCase): self.session.createNotificationBlock.return_value = None self.session.getPackageID.return_value = 1 self.session.getTagID.return_value = 2 - with self.assertRaises(SystemExit) as ex: - handle_block_notification(self.options, self.session, ['--user', 'testuser', - '--package', 'pkgtest', - '--tag', 'testtag']) - - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) - activate_session.assert_called_once_with(self.session, self.options) + arguments = ['--user', 'testuser', '--package', 'pkgtest', '--tag', 'testtag'] + self.assert_system_exit( + handle_block_notification, + self.options, self.session, arguments, + stderr=self.format_error_message("Notification already exists."), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_called_once_with(self.session, self.options) diff --git a/tests/test_cli/test_block_pkg.py b/tests/test_cli/test_block_pkg.py index 203187b..74428c9 100644 --- a/tests/test_cli/test_block_pkg.py +++ b/tests/test_cli/test_block_pkg.py @@ -1,67 +1,96 @@ from __future__ import absolute_import -import os -import sys - import mock import six from mock import call from koji_cli.commands import handle_block_pkg + +import koji from . import utils class TestBlockPkg(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None + def setUp(self): + # Show long diffs in error output... + self.maxDiff = None + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s block-pkg [options] [ ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_pkg(self, activate_session_mock, stdout): + def test_handle_block_pkg(self, stdout): tag = 'tag' dsttag = {'name': tag, 'id': 1} package = 'package' args = [tag, package, '--force'] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': package, 'package_id': 1}] # Run it and check immediate output # args: tag, package # expected: success - rv = handle_block_pkg(options, session, args) + rv = handle_block_pkg(self.options, self.session, args) actual = stdout.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_called_once_with( + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_called_once_with( tagID=dsttag['id'], inherited=True, with_owners=False) - session.packageListBlock.assert_called_once_with( + self.session.packageListBlock.assert_called_once_with( + tag, package, force=True) + self.session.multiCall.assert_called_once_with(strict=True) + self.assertFalse(rv) + + @mock.patch('sys.stdout', new_callable=six.StringIO) + def test_handle_block_pkg_parameter_error(self, stdout): + tag = 'tag' + dsttag = {'name': tag, 'id': 1} + package = 'package' + args = [tag, package, '--force'] + + self.session.getTag.return_value = dsttag + self.session.listPackages.side_effect = [koji.ParameterError, + [{'package_name': package, 'package_id': 1}]] + # Run it and check immediate output + # args: tag, package + # expected: success + rv = handle_block_pkg(self.options, self.session, args) + actual = stdout.getvalue() + expected = '' + self.assertMultiLineEqual(actual, expected) + # Finally, assert that things were called as we expected. + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_has_calls([ + call(tagID=dsttag['id'], inherited=True, with_owners=False), + call(tagID=dsttag['id'], inherited=True) + ]) + self.session.packageListBlock.assert_called_once_with( tag, package, force=True) - session.multiCall.assert_called_once_with(strict=True) + self.session.multiCall.assert_called_once_with(strict=True) self.assertFalse(rv) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_pkg_multi_pkg(self, activate_session_mock, stdout): + def test_handle_block_pkg_multi_pkg(self, stdout): tag = 'tag' dsttag = {'name': tag, 'id': 1} packages = ['package1', 'package2', 'package3'] args = [tag] + packages - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': 'package1', 'package_id': 1}, {'package_name': 'package2', 'package_id': 2}, {'package_name': 'package3', 'package_id': 3}, @@ -70,14 +99,14 @@ class TestBlockPkg(utils.CliTestCase): # Run it and check immediate output # args: tag, package1, package2, package3 # expected: success - rv = handle_block_pkg(options, session, args) + rv = handle_block_pkg(self.options, self.session, args) actual = stdout.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.assertEqual( - session.mock_calls, [ + self.session.mock_calls, [ call.getTag(tag), call.listPackages(tagID=dsttag['id'], inherited=True, with_owners=False), call.packageListBlock(tag, packages[0]), @@ -86,99 +115,71 @@ class TestBlockPkg(utils.CliTestCase): call.multiCall(strict=True)]) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_pkg_no_package(self, activate_session_mock, stderr): + def test_handle_block_pkg_no_package(self): tag = 'tag' dsttag = {'name': tag, 'id': 1} packages = ['package1', 'package2', 'package3'] - args = [tag] + packages - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() + arguments = [tag] + packages - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': 'package1', 'package_id': 1}, {'package_name': 'package3', 'package_id': 3}, {'package_name': 'other_package', 'package_id': 4}] # Run it and check immediate output # args: tag, package1, package2, package3 # expected: failed: can not find package2 under tag - with self.assertRaises(SystemExit) as ex: - handle_block_pkg(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'Package package2 doesn\'t exist in tag tag\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_block_pkg, + self.options, self.session, arguments, + stderr='Package package2 doesn\'t exist in tag tag\n', + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_called_once_with( + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_called_once_with( tagID=dsttag['id'], inherited=True, with_owners=False) - session.packageListBlock.assert_not_called() - session.multiCall.assert_not_called() + self.session.packageListBlock.assert_not_called() + self.session.multiCall.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_block_pkg_tag_no_exists( - self, activate_session_mock, stderr): + def test_handle_block_pkg_tag_no_exists(self): tag = 'tag' dsttag = None packages = ['package1', 'package2', 'package3'] - args = [tag] + packages - options = mock.MagicMock() + arguments = [tag] + packages - # Mock out the xmlrpc server - session = mock.MagicMock() - - session.getTag.return_value = dsttag + self.session.getTag.return_value = dsttag # Run it and check immediate output # args: tag, package1, package2, package3 # expected: failed: tag does not exist - with self.assertRaises(SystemExit) as ex: - handle_block_pkg(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such tag: %s\n' % tag - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_block_pkg, + self.options, self.session, arguments, + stderr='No such tag: %s\n' % tag, + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_not_called() - session.packageListBlock.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_block_pkg_help( - self, activate_session_mock, stderr, stdout): - args = [] - options = mock.MagicMock() - - progname = os.path.basename(sys.argv[0]) or 'koji' - - # Mock out the xmlrpc server - session = mock.MagicMock() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_not_called() + self.session.packageListBlock.assert_not_called() + def test_handle_block_pkg_without_args(self): + arguments = [] # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_block_pkg(options, session, args) - self.assertExitCode(ex, 2) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() - expected_stdout = '' - expected_stderr = """Usage: %s block-pkg [options] [ ...] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify a tag and at least one package -""" % (progname, progname) - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_block_pkg, + self.options, self.session, arguments, + stderr=self.format_error_message('Please specify a tag and at least one package'), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() - session.getTag.assert_not_called() - session.listPackages.assert_not_called() - session.packageListBlock.assert_not_called() + self.activate_session_mock.assert_not_called() + self.session.getTag.assert_not_called() + self.session.listPackages.assert_not_called() + self.session.packageListBlock.assert_not_called() diff --git a/tests/test_cli/test_build.py b/tests/test_cli/test_build.py index 076d2c0..ef9918c 100644 --- a/tests/test_cli/test_build.py +++ b/tests/test_cli/test_build.py @@ -116,22 +116,18 @@ Task info: weburl/taskinfo?taskID=1 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) - def test_handle_build_no_arg(self, stderr, stdout): - args = [] + def test_handle_build_no_arg(self): + arguments = [] # 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("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) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("Exactly two arguments (a build target and " + "a SCM URL or srpm file) are required"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() @@ -144,17 +140,8 @@ Task info: weburl/taskinfo?taskID=1 self.session.logout.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) - def test_handle_build_help(self, stderr, stdout): - args = ['--help'] - - # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_build(self.options, self.session, args) - self.assertExitCode(ex, 0) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() + def test_handle_build_help(self): + arguments = ['--help'] expected_stdout = """Usage: %s build [options] The first option is the build target, not to be confused with the destination @@ -189,9 +176,15 @@ Options: deserialized and stored under the build's extra.custom_user_metadata field """ % (self.progname, self.progname) - expected_stderr = '' - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + + # Run it and check immediate output + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr='', + stdout=expected_stdout, + activate_session=None, + exit_code=0) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() @@ -237,22 +230,18 @@ Task info: weburl/taskinfo?taskID=1 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) - 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.}'] + def test_handle_build_custom_user_metadata_invalid_json(self): + arguments = [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: - 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("--custom-user-metadata is not valid JSON") - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("--custom-user-metadata is not valid JSON"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() @@ -265,22 +254,18 @@ Task info: weburl/taskinfo?taskID=1 self.session.logout.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) - 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."'] + def test_handle_build_custom_user_metadata_not_json_object(self): + arguments = [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: - 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("--custom-user-metadata must be a JSON object") - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("--custom-user-metadata must be a JSON object"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() @@ -293,23 +278,19 @@ Task info: weburl/taskinfo?taskID=1 self.session.logout.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) - def test_handle_build_arch_override_denied(self, stderr, stdout): + def test_handle_build_arch_override_denied(self): arch_override = 'somearch' - args = [self.target, self.source_scm, '--arch-override=' + arch_override] + arguments = [self.target, self.source_scm, '--arch-override=' + arch_override] # 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( - "--arch_override is only allowed for --scratch builds") - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message( + "--arch_override is only allowed for --scratch builds"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() @@ -360,18 +341,19 @@ Task info: weburl/taskinfo?taskID=1 @mock.patch('sys.stderr', new_callable=six.StringIO) def test_handle_build_target_not_found(self, stderr): target_info = None - args = [self.target, self.source_scm] + arguments = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info # Run it and check immediate output # args: target, http://scm # expected: failed, target not found - with self.assertRaises(SystemExit) as ex: - handle_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected = self.format_error_message("No such build target: target") - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("No such build target: target"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.getBuildTarget.assert_called_once_with(self.target) @@ -383,24 +365,24 @@ Task info: weburl/taskinfo?taskID=1 self.session.logout.assert_not_called() self.watch_tasks_mock.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - def test_handle_build_dest_tag_not_found(self, stderr): + def test_handle_build_dest_tag_not_found(self): dest_tag_name = 'dest_tag_name' target_info = {'dest_tag': self.dest_tag, 'dest_tag_name': dest_tag_name} dest_tag_info = None - args = [self.target, self.source_scm] + arguments = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info # Run it and check immediate output # args: target, http://scm # expected: failed, dest_tag not found - with self.assertRaises(SystemExit) as ex: - handle_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected = self.format_error_message("No such destination tag: dest_tag_name") - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("No such destination tag: dest_tag_name"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.getBuildTarget.assert_called_once_with(self.target) @@ -412,24 +394,24 @@ Task info: weburl/taskinfo?taskID=1 self.session.logout.assert_not_called() self.watch_tasks_mock.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - def test_handle_build_dest_tag_locked(self, stderr): + def test_handle_build_dest_tag_locked(self): 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} - args = [self.target, self.source_scm] + arguments = [self.target, self.source_scm] self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info # Run it and check immediate output # args: target, http://scm # expected: failed, dest_tag is locked - with self.assertRaises(SystemExit) as ex: - handle_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected = self.format_error_message("Destination tag dest_tag_name is locked") - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message("Destination tag dest_tag_name is locked"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.getBuildTarget.assert_called_once_with(self.target) @@ -687,22 +669,18 @@ Task info: weburl/taskinfo?taskID=1 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] + def test_handle_build_rebuild_srpm_without_scratch(self): + arguments = ['--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) + self.assert_system_exit( + handle_build, + self.options, self.session, arguments, + stderr=self.format_error_message( + "--no-/rebuild-srpm is only allowed for --scratch builds"), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. self.activate_session_mock.assert_not_called() diff --git a/tests/test_cli/test_buildinfo.py b/tests/test_cli/test_buildinfo.py index d7d94d5..efcd8f6 100644 --- a/tests/test_cli/test_buildinfo.py +++ b/tests/test_cli/test_buildinfo.py @@ -75,9 +75,7 @@ Tags: self.session.listRPMs.assert_called_once_with(buildID=self.buildinfo['id']) self.assertEqual(self.session.listArchives.call_count, 4) - @mock.patch('sys.stderr', new_callable=StringIO) - @mock.patch('sys.stdout', new_callable=StringIO) - def test_buildinfo_more_build_with_non_exist_build(self, stdout, stderr): + def test_buildinfo_more_build_with_non_exist_build(self): build = 'test-build-1-1' non_exist_build = 'test-build-11-12' buildinfo = copy.deepcopy(self.buildinfo) @@ -96,12 +94,14 @@ Task: none Finished: Thu, 04 Mar 2021 14:45:40 UTC Tags: """ - expected_error = "No such build: %s\n\n" % non_exist_build - with self.assertRaises(SystemExit) as ex: - anon_handle_buildinfo(self.options, self.session, [non_exist_build, build]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected_error) - self.assert_console_message(stdout, expected_stdout) + arguments = [non_exist_build, build] + self.assert_system_exit( + anon_handle_buildinfo, + self.options, self.session, arguments, + stderr="No such build: %s\n\n" % non_exist_build, + stdout=expected_stdout, + activate_session=None, + exit_code=1) self.session.listTags.assert_called_once_with(build) self.session.getMavenBuild.assert_called_once_with(self.buildinfo['id']) self.session.getWinBuild.assert_called_once_with(self.buildinfo['id']) @@ -109,12 +109,14 @@ Tags: self.assertEqual(self.session.getBuild.call_count, 2) self.assertEqual(self.session.listArchives.call_count, 4) - @mock.patch('sys.stderr', new_callable=StringIO) - def test_buildinfo_non_exist_build(self, stderr): + def test_buildinfo_non_exist_build(self): non_exist_build = 'test-build-11-12' self.session.getBuild.return_value = None - expected = "No such build: %s\n\n" % non_exist_build - with self.assertRaises(SystemExit) as ex: - anon_handle_buildinfo(self.options, self.session, [non_exist_build]) - self.assertExitCode(ex, 1) - self.assert_console_message(stderr, expected) + arguments = [non_exist_build] + self.assert_system_exit( + anon_handle_buildinfo, + self.options, self.session, arguments, + stderr="No such build: %s\n\n" % non_exist_build, + stdout='', + activate_session=None, + exit_code=1) diff --git a/tests/test_cli/test_call.py b/tests/test_cli/test_call.py index 8d430b5..fb70d78 100644 --- a/tests/test_cli/test_call.py +++ b/tests/test_cli/test_call.py @@ -3,6 +3,7 @@ import json import mock import six import unittest +import koji from koji_cli.commands import handle_call from . import utils @@ -10,10 +11,15 @@ from . import utils class TestCall(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None - def setUp(self): + # Show long diffs in error output... + self.maxDiff = None + self.options = mock.MagicMock() + self.options.quiet = True + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s call [options] [ ...] Note, that you can use global option --noauth for anonymous calls here @@ -23,51 +29,38 @@ Note, that you can use global option --noauth for anonymous calls here """ % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_call(self, activate_session_mock, stdout): + def test_handle_call(self, stdout): """Test handle_call function""" arguments = ['ssl_login', 'cert=/etc/pki/cert', 'debug'] response = "SUCCESS" - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.ssl_login.return_value = response + self.session.ssl_login.return_value = response - handle_call(options, session, arguments) - activate_session_mock.assert_called_with(session, options) - session.ssl_login.assert_called_with('debug', cert='/etc/pki/cert') + handle_call(self.options, self.session, arguments) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.session.ssl_login.assert_called_with('debug', cert='/etc/pki/cert') self.assert_console_message(stdout, "'%s'\n" % response) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_call_python_syntax(self, activate_session_mock, stdout): + def test_handle_call_python_syntax(self, stdout): """Test handle_call with python syntax""" - arguments = [] response = ["SUCCESS", "FAKE-RESPONSE"] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.ssl_login.return_value = response[1] + self.session.ssl_login.return_value = response[1] # Invalid python syntax arguments = ['ssl_login', 'cert=/etc/pki/cert', '--python'] with self.assertRaises(SyntaxError, msg='invalid syntax'): - handle_call(options, session, arguments) + handle_call(self.options, self.session, arguments) arguments = ['ssl_login', '--kwargs', '{"cert":"/etc/pki/cert"}'] - handle_call(options, session, arguments) - activate_session_mock.assert_called_with(session, options) - session.ssl_login.assert_called_with(cert='/etc/pki/cert') + handle_call(self.options, self.session, arguments) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.session.ssl_login.assert_called_with(cert='/etc/pki/cert') self.assert_console_message(stdout, "'%s'\n" % response[1]) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_call_json_output(self, activate_session_mock, stdout): + def test_handle_call_json_output(self, stdout): """Test handle_call with json output""" arguments = ['ssl_login', 'cert=/etc/pki/cert', '--json-output'] - options = mock.MagicMock() response = { 'method': 'ssl_login', @@ -77,39 +70,28 @@ Note, that you can use global option --noauth for anonymous calls here 'result': 'success' } - # Mock out the xmlrpc server - session = mock.MagicMock() - session.ssl_login.return_value = response + self.session.ssl_login.return_value = response - handle_call(options, session, arguments) - activate_session_mock.assert_called_with(session, options) - session.ssl_login.assert_called_with(cert='/etc/pki/cert') + handle_call(self.options, self.session, arguments) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.session.ssl_login.assert_called_with(cert='/etc/pki/cert') expect = json.dumps(response, indent=2, separators=(',', ': ')) self.assert_console_message(stdout, '%s\n' % expect) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_call_errors(self, activate_session_mock, stderr): + def test_handle_call_errors(self, stderr): """Test handle_call error messages""" arguments = [] - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() # Run it and check immediate output # argument is empty - expected = self.format_error_message( - "Please specify the name of the XML-RPC method") self.assert_system_exit( handle_call, - options, - session, - arguments, - stderr=expected, + self.options, self.session, arguments, + stderr=self.format_error_message("Please specify the name of the XML-RPC method"), activate_session=None) - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() arguments = ['ssl_login', '--python', '--json-output'] @@ -121,11 +103,11 @@ Note, that you can use global option --noauth for anonymous calls here for mod, msg in module.items(): with mock.patch('koji_cli.commands.%s' % mod, new=None): with self.assertRaises(SystemExit) as ex: - handle_call(options, session, arguments) + handle_call(self.options, self.session, arguments) self.assertExitCode(ex, 2) expected = self.format_error_message(msg) self.assert_console_message(stderr, expected) - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() def test_handle_call_help(self): """Test handle_call help message""" @@ -142,7 +124,7 @@ Options: --kwargs=KWARGS Specify keyword arguments as a dictionary (implies --python) --json-output Use JSON syntax for output -""" % (self.progname)) +""" % self.progname) if __name__ == '__main__': diff --git a/tests/test_cli/test_cancel.py b/tests/test_cli/test_cancel.py index f5aa7a2..429ca74 100644 --- a/tests/test_cli/test_cancel.py +++ b/tests/test_cli/test_cancel.py @@ -1,7 +1,6 @@ from __future__ import absolute_import import mock -from six.moves import StringIO import koji from koji_cli.commands import handle_cancel @@ -9,13 +8,14 @@ from . import utils class TestCancel(utils.CliTestCase): - maxDiff = None def setUp(self): + self.maxDiff = None self.options = mock.MagicMock() self.options.quiet = False self.session = mock.MagicMock() self.session.multicall.return_value.__enter__.return_value = self.session + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s cancel [options] [ ...] (Specify the --help global option for a list of other help options) @@ -23,27 +23,25 @@ class TestCancel(utils.CliTestCase): %s: error: {message} """ % (self.progname, self.progname) - @mock.patch('koji_cli.commands.activate_session') - def test_anon_cancel(self, activate_session_mock): + def test_anon_cancel(self): args = ['123'] - activate_session_mock.side_effect = koji.GenericError + self.activate_session_mock.side_effect = koji.GenericError with self.assertRaises(koji.GenericError): handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_not_called() self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_not_called() - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_tasks(self, activate_session_mock): + def test_cancel_tasks(self): # integers are always treated like task IDs, not build IDs args = ['123', '234'] handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_has_calls([mock.call(123), mock.call(234)]) self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_not_called() @@ -54,9 +52,7 @@ class TestCancel(utils.CliTestCase): "please specify only task ids (integer) or builds (n-v-r)") self.assert_system_exit( handle_cancel, - self.options, - self.session, - args, + self.options, self.session, args, stdout='', stderr=expected) @@ -64,72 +60,66 @@ class TestCancel(utils.CliTestCase): self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_not_called() - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_builds(self, activate_session_mock): + def test_cancel_builds(self): args = ['name-version-release'] handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_not_called() self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_called_once_with(args[0]) - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_builds_unused_options(self, activate_session_mock): + def test_cancel_builds_unused_options(self): # it is good for nothing here args = ['name-version-release', '--full', '--justone', '--force'] handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_not_called() self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_called_once_with(args[0]) - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_tasks_full(self, activate_session_mock): + def test_cancel_tasks_full(self): args = ['123', '--full'] handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_not_called() self.session.cancelTaskFull.assert_called_once_with(123) self.session.cancelBuild.assert_not_called() - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_tasks_justone(self, activate_session_mock): + def test_cancel_tasks_justone(self): args = ['123', '--justone'] handle_cancel(self.options, self.session, args) - 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.cancelTask.assert_called_once_with(123, recurse=False) self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_not_called() - @mock.patch('koji_cli.commands.activate_session') - def test_cancel_tasks_force(self, activate_session_mock): + def test_cancel_tasks_force(self): args = ['123', '--force', '--full'] handle_cancel(self.options, self.session, args) - 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.cancelTaskFull.assert_called_once_with(123, strict=False) self.session.cancelBuild.assert_not_called() - @mock.patch('sys.stderr', new_callable=StringIO) - def test_cancel_without_arguments(self, stderr): - expected = """Usage: %s cancel [options] [ ...] -(Specify the --help global option for a list of other help options) - -%s: error: You must specify at least one task id or build -""" % (self.progname, self.progname) - with self.assertRaises(SystemExit) as ex: - handle_cancel(self.options, self.session, []) - self.assertExitCode(ex, 2) - self.assert_console_message(stderr, expected) + def test_cancel_without_arguments(self): + arguments = [] + self.assert_system_exit( + handle_cancel, + self.options, self.session, arguments, + stderr=self.format_error_message("You must specify at least one task id or build"), + stdout='', + activate_session=None, + exit_code=2) + self.activate_session_mock.assert_not_called() self.session.cancelTask.assert_not_called() self.session.cancelTaskFull.assert_not_called() self.session.cancelBuild.assert_not_called() diff --git a/tests/test_cli/test_chain_build.py b/tests/test_cli/test_chain_build.py index d82d39f..e0510f6 100644 --- a/tests/test_cli/test_chain_build.py +++ b/tests/test_cli/test_chain_build.py @@ -1,9 +1,7 @@ from __future__ import absolute_import import mock -import os import six -import sys import unittest from koji_cli.commands import handle_chain_build @@ -11,10 +9,10 @@ from . import utils class TestChainBuild(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None def setUp(self): + # Show long diffs in error output... + self.maxDiff = None # Mock out the options parsed in main self.options = mock.MagicMock() self.options.quiet = None @@ -22,13 +20,19 @@ class TestChainBuild(utils.CliTestCase): self.options.poll_interval = 0 # Mock out the xmlrpc server 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.watch_tasks_mock.return_value = 0 + self.error_format = """Usage: %s chain-build [options] [ [:] [:] ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build(self, watch_tasks_mock, running_in_bg_mock, - activate_session_mock, stdout): + def test_handle_chain_build(self, stdout): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -70,80 +74,43 @@ 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) - self.session.chainBuild.assert_called_once_with( - sources, target, priority=priority) - running_in_bg_mock.assert_called_once() + self.session.chainBuild.assert_called_once_with(sources, target, priority=priority) + self.running_in_bg_mock.assert_called_once() self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( + self.watch_tasks_mock.assert_called_once_with( self.session, [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._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_no_arg( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stderr, - stdout): - args = [] - progname = os.path.basename(sys.argv[0]) or 'koji' + def test_handle_chain_build_no_arg(self): + arguments = [] # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_chain_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() - expected_stdout = '' - expected_stderr = """Usage: %s chain-build [options] [ [:] [:] ...] -(Specify the --help global option for a list of other help options) - -%s: error: At least two arguments (a build target and a SCM URL) are required -""" % (progname, progname) - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_chain_build, + self.options, self.session, arguments, + stderr=self.format_error_message( + "At least two arguments (a build target and a SCM URL) are required"), + stdout='', + activate_session=None, + exit_code=2) # 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() self.session.getFullInheritance.assert_not_called() - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.chainBuild.assert_not_called() self.session.logout.assert_not_called() - 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._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_help( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stderr, - stdout): - args = ['--help'] - progname = os.path.basename(sys.argv[0]) or 'koji' + self.watch_tasks_mock.assert_not_called() - # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_chain_build(self.options, self.session, args) - self.assertExitCode(ex, 0) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() + def test_handle_chain_build_help(self): + arguments = ['--help'] expected_stdout = """Usage: %s chain-build [options] [ [:] [:] ...] (Specify the --help global option for a list of other help options) @@ -153,31 +120,28 @@ Options: --nowait Don't wait on build --quiet Do not print the task information --background Run the build at a lower priority -""" % progname - expected_stderr = '' - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) +""" % self.progname + + # Run it and check immediate output + self.assert_system_exit( + handle_chain_build, + self.options, self.session, arguments, + stderr='', + stdout=expected_stdout, + activate_session=None, + exit_code=0) # 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() self.session.getFullInheritance.assert_not_called() - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.chainBuild.assert_not_called() self.session.logout.assert_not_called() - 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._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_target_not_found( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stderr): + self.watch_tasks_mock.assert_not_called() + + def test_handle_chain_build_target_not_found(self): target = 'target' target_info = None source_args = [ @@ -189,44 +153,30 @@ Options: ':', 'n-v-r-2', 'n-v-r-3'] - args = [target] + source_args - - progname = os.path.basename(sys.argv[0]) or 'koji' + arguments = [target] + source_args self.session.getBuildTarget.return_value = target_info # Run it and check immediate output # args: target http://scm1 : http://scm2 http://scm3 n-v-r-1 : n-v-r-2 n-v-r-3 # expected: failed, target not found - with self.assertRaises(SystemExit) as ex: - handle_chain_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected = """Usage: %s chain-build [options] [ [:] [:] ...] -(Specify the --help global option for a list of other help options) - -%s: error: No such build target: target -""" % (progname, progname) - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_chain_build, + self.options, self.session, arguments, + stderr=self.format_error_message("No such build target: target"), + stdout='', + activate_session=None, + exit_code=2) # 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_called_once_with(target) self.session.getTag.assert_not_called() self.session.getFullInheritance.assert_not_called() - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.chainBuild.assert_not_called() self.session.logout.assert_not_called() - 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._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, - activate_session_mock, - stderr): + self.watch_tasks_mock.assert_not_called() + + def test_handle_build_dest_tag_locked(self): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -247,41 +197,31 @@ Options: ':', 'n-v-r-2', 'n-v-r-3'] - args = [target] + source_args - - progname = os.path.basename(sys.argv[0]) or 'koji' + arguments = [target] + source_args self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info # Run it and check immediate output # args: target http://scm1 : http://scm2 http://scm3 n-v-r-1 : n-v-r-2 n-v-r-3 # expected: failed, dest_tag is locked - with self.assertRaises(SystemExit) as ex: - handle_chain_build(self.options, self.session, args) - self.assertExitCode(ex, 2) - actual = stderr.getvalue() - expected = """Usage: %s chain-build [options] [ [:] [:] ...] -(Specify the --help global option for a list of other help options) - -%s: error: Destination tag dest_tag is locked -""" % (progname, progname) - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_chain_build, + self.options, self.session, arguments, + stderr=self.format_error_message("Destination tag dest_tag is locked"), + stdout='', + activate_session=None, + exit_code=2) # 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_not_called() - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.chainBuild.assert_not_called() self.session.logout.assert_not_called() - 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._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_build_dest_tag_not_inherited_by_build_tag( - self, watch_tasks_mock, running_in_bg_mock, activate_session_mock, stderr): + self.watch_tasks_mock.assert_not_called() + + def test_handle_build_dest_tag_not_inherited_by_build_tag(self): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -304,7 +244,7 @@ Options: ':', 'n-v-r-2', 'n-v-r-3'] - args = [target] + source_args + arguments = [target] + source_args self.session.getBuildTarget.return_value = target_info self.session.getTag.return_value = dest_tag_info @@ -312,32 +252,27 @@ Options: # Run it and check immediate output # args: target, target http://scm1 : http://scm2 http://scm3 n-v-r-1 : n-v-r-2 n-v-r-3 # expected: failed, dest_tag is not in build_tag's inheritance - with self.assertRaises(SystemExit) as ex: - handle_chain_build(self.options, self.session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() expected = """Packages in destination tag dest_tag are not inherited by build tag build_tag Target target is not usable for a chain-build """ - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_chain_build, + self.options, self.session, arguments, + stderr=expected, + stdout='', + activate_session=None, + exit_code=1) # 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.chainBuild.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() - - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_invalidated_src( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock): + self.watch_tasks_mock.assert_not_called() + + def test_handle_chain_build_invalidated_src(self): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -375,16 +310,16 @@ Target target is not usable for a chain-build expected = '"badnvr" is not a SCM URL or package N-V-R\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.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_id, strict=True) self.session.getFullInheritance.assert_called_once_with( build_tag_id) self.session.chainBuild.assert_not_called() - running_in_bg_mock.assert_not_called() + self.running_in_bg_mock.assert_not_called() self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() with mock.patch('sys.stderr', new_callable=six.StringIO) as stderr: source_args = [ @@ -450,32 +385,19 @@ Target target is not usable for a chain-build source_args = ['http://scm'] args = [target] + source_args - progname = os.path.basename(sys.argv[0]) or 'koji' - # args: target http://scm # expected: failed, only one src found with self.assertRaises(SystemExit) as ex: handle_chain_build(self.options, self.session, args) self.assertExitCode(ex, 2) actual = stderr.getvalue() - expected = """Usage: %s chain-build [options] [ [:] [:] ...] -(Specify the --help global option for a list of other help options) - -%s: error: You must specify at least one dependency between builds with : (colon) -If there are no dependencies, use the build command instead -""" % (progname, progname) + expected = self.format_error_message( + "You must specify at least one dependency between builds with : (colon)\n" + "If there are no dependencies, use the build command instead") self.assertMultiLineEqual(actual, expected) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - @mock.patch('koji_cli.commands._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_background( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stdout): + def test_handle_chain_build_background(self, stdout): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -517,29 +439,21 @@ 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) self.session.chainBuild.assert_called_once_with( sources, target, priority=priority) - running_in_bg_mock.assert_called_once() + self.running_in_bg_mock.assert_called_once() self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( + self.watch_tasks_mock.assert_called_once_with( self.session, [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._running_in_bg', return_value=False) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_quiet( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stdout): + def test_handle_chain_build_quiet(self, stdout): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -580,29 +494,22 @@ Task info: weburl/taskinfo?taskID=1 expected = '' 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) self.session.chainBuild.assert_called_once_with( sources, target, priority=priority) - running_in_bg_mock.assert_called_once() + self.running_in_bg_mock.assert_called_once() self.session.logout.assert_called() - watch_tasks_mock.assert_called_once_with( + self.watch_tasks_mock.assert_called_once_with( self.session, [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._running_in_bg', return_value=True) - @mock.patch('koji_cli.commands.watch_tasks', return_value=0) - def test_handle_chain_build_running_in_bg( - self, - watch_tasks_mock, - running_in_bg_mock, - activate_session_mock, - stdout): + def test_handle_chain_build_running_in_bg(self, stdout): + self.running_in_bg_mock.return_value = True target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -644,25 +551,19 @@ 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) self.session.chainBuild.assert_called_once_with( sources, target, priority=priority) - running_in_bg_mock.assert_called_once() + self.running_in_bg_mock.assert_called_once() 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.watch_tasks', return_value=0) - def test_handle_chain_build_nowait( - self, - watch_tasks_mock, - activate_session_mock, - stdout): + def test_handle_chain_build_nowait(self, stdout): target = 'target' dest_tag = 'dest_tag' dest_tag_id = 2 @@ -704,14 +605,14 @@ 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_called_once_with(target) self.session.getTag.assert_called_once_with(dest_tag_id, strict=True) self.session.getFullInheritance.assert_called_once_with(build_tag_id) self.session.chainBuild.assert_called_once_with( sources, target, priority=priority) self.session.logout.assert_not_called() - watch_tasks_mock.assert_not_called() + self.watch_tasks_mock.assert_not_called() self.assertIsNone(rv) diff --git a/tests/test_cli/test_clone_tag.py b/tests/test_cli/test_clone_tag.py index c7214ff..95f99f7 100644 --- a/tests/test_cli/test_clone_tag.py +++ b/tests/test_cli/test_clone_tag.py @@ -23,8 +23,7 @@ class TestCloneTag(utils.CliTestCase): 'locked': False}, {'id': 2, 'locked': False}] - self.activate_session = mock.patch( - 'koji_cli.commands.activate_session').start() + self.activate_session = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s clone-tag [options] clone-tag will create the destination tag if it does not already exist @@ -121,6 +120,7 @@ clone-tag will create the destination tag if it does not already exist self.activate_session.getTag.has_called([call('src-tag'), call('dst-tag')]) + @mock.patch('sys.stdout', new_callable=six.StringIO) def test_handle_clone_tag_new_dsttag(self, stdout): args = ['src-tag', 'dst-tag', '--all', '-v'] @@ -186,95 +186,70 @@ clone-tag will create the destination tag if it does not already exist 'locked': False, 'extra': {}}] self.session.getBuildConfig.side_effect = [{'id': 1, - 'name': 'src-tag', - 'arches': 'arch1 arch2', - 'perm_id': 1, - 'maven_support': False, - 'maven_include_all': True, - 'locked': False, - 'extra': {}}, - ] + 'name': 'src-tag', + 'arches': 'arch1 arch2', + 'perm_id': 1, + 'maven_support': False, + 'maven_include_all': True, + 'locked': False, + 'extra': {}}, + ] self.session.multiCall.return_value = [] handle_clone_tag(self.options, self.session, args) self.activate_session.assert_called_once() self.session.assert_has_calls([call.hasPerm('admin'), call.getBuildConfig('src-tag', event=None), call.getTag('dst-tag'), - call.createTag('dst-tag', - arches='arch1 arch2', - locked=False, - maven_include_all=True, - maven_support=False, - parent=None, perm=1, + call.createTag('dst-tag', arches='arch1 arch2', + locked=False, maven_include_all=True, + maven_support=False, parent=None, perm=1, extra={}), call.getTag('dst-tag', strict=True), - call.listPackages(event=None, - inherited=True, - tagID=1), - call.packageListAdd('dst-tag', 'apkg', - block=False, - extra_arches='arch4', - owner='userA'), - call.packageListAdd('dst-tag', 'pkg1', - block=False, - extra_arches=None, - owner='userA'), - call.packageListAdd('dst-tag', 'pkg2', - block=True, + call.listPackages(event=None, inherited=True, tagID=1), + call.packageListAdd('dst-tag', 'apkg', block=False, + extra_arches='arch4', owner='userA'), + call.packageListAdd('dst-tag', 'pkg1', block=False, + extra_arches=None, owner='userA'), + call.packageListAdd('dst-tag', 'pkg2', block=True, extra_arches='arch3 arch4', owner='userB'), call.multiCall(batch=100), - call.listTagged(1, event=None, - inherit=None, - latest=None), + call.listTagged(1, event=None, inherit=None, latest=None), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg2-1.0-1', 'package_name': 'pkg2', 'state': 2, 'tag_name': 'src-tag-p', - 'name': 'pkg2'}, force=None, - notify=False), + 'name': 'pkg2'}, force=None, notify=False), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-1.0-1', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-1.0-2', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-1.1-2', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.multiCall(batch=100), - call.getTagGroups('src-tag', - event=None), + call.getTagGroups('src-tag', event=None), call.groupListAdd('dst-tag', 'group1'), - call.groupPackageListAdd('dst-tag', - 'group1', - 'pkg1', + call.groupPackageListAdd('dst-tag', 'group1', 'pkg1', block=False), - call.groupPackageListAdd('dst-tag', - 'group1', - 'pkg2', + call.groupPackageListAdd('dst-tag', 'group1', 'pkg2', block=False), call.groupListAdd('dst-tag', 'group2'), - call.groupPackageListAdd('dst-tag', - 'group2', - 'apkg', + call.groupPackageListAdd('dst-tag', 'group2', 'apkg', block=False), - call.groupPackageListAdd('dst-tag', - 'group2', - 'bpkg', + call.groupPackageListAdd('dst-tag', 'group2', 'bpkg', block=False), call.multiCall(batch=100)]) self.assert_console_message(stdout, """ @@ -457,13 +432,13 @@ List of changes: 'blocked': False}]} ]] self.session.getBuildConfig.side_effect = [{'id': 1, - 'name': 'src-tag', - 'arches': 'arch1 arch2', - 'perm_id': 1, - 'maven_support': False, - 'maven_include_all': True, - 'locked': False, - 'extra': {}}] + 'name': 'src-tag', + 'arches': 'arch1 arch2', + 'perm_id': 1, + 'maven_support': False, + 'maven_include_all': True, + 'locked': False, + 'extra': {}}] self.session.getTag.side_effect = [{'id': 2, 'name': 'dst-tag', 'arches': 'arch1 arch2', @@ -491,21 +466,13 @@ List of changes: maven_support=False, parent=None, perm=1), call.getTag(2, strict=True), - call.listPackages(event=None, - inherited=True, - tagID=1), - call.listPackages(inherited=True, - tagID=2), - call.listTagged(1, event=None, - inherit=None, - latest=None), - call.listTagged(2, inherit=False, - latest=False), - call.getTagGroups('src-tag', - event=None), + call.listPackages(event=None, inherited=True, tagID=1), + call.listPackages(inherited=True, tagID=2), + call.listTagged(1, event=None, inherit=None, latest=None), + call.listTagged(2, inherit=False, latest=False), + call.getTagGroups('src-tag', event=None), call.getTagGroups('dst-tag'), - call.packageListAdd('dst-tag', 'pkg2', - block=True, + call.packageListAdd('dst-tag', 'pkg2', block=True, extra_arches='arch3 arch4', owner='userB'), call.multiCall(batch=100), @@ -514,84 +481,60 @@ List of changes: 'nvr': 'pkg1-2.1-2', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'dst-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.untagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-0.1-1', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'dst-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.untagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg3-1.0-1', 'package_name': 'pkg3', 'state': 1, 'tag_name': 'dst-tag', - 'name': 'pkg3'}, force=None, - notify=False), + 'name': 'pkg3'}, force=None, notify=False), call.multiCall(batch=100), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-0.1-1', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-1.0-2', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.tagBuildBypass('dst-tag', { 'owner_name': 'b_owner', 'nvr': 'pkg1-1.1-2', 'package_name': 'pkg1', 'state': 1, 'tag_name': 'src-tag', - 'name': 'pkg1'}, force=None, - notify=False), + 'name': 'pkg1'}, force=None, notify=False), call.multiCall(batch=100), call.multiCall(batch=100), - call.groupPackageListAdd('dst-tag', - 'group1', - 'pkg2', + call.groupPackageListAdd('dst-tag', 'group1', 'pkg2', force=None), - call.groupPackageListAdd('dst-tag', - 'group1', - 'pkg3', + call.groupPackageListAdd('dst-tag', 'group1', 'pkg3', force=None), - call.groupPackageListAdd('dst-tag', - 'group1', - 'pkg4', + call.groupPackageListAdd('dst-tag', 'group1', 'pkg4', force=None), - call.groupPackageListAdd('dst-tag', - 'group2', - 'bpkg', + call.groupPackageListAdd('dst-tag', 'group2', 'bpkg', force=None), call.multiCall(batch=100), call.multiCall(batch=100), - call.packageListBlock('dst-tag', - 'bpkg'), - call.packageListBlock('dst-tag', - 'cpkg'), - call.packageListBlock('dst-tag', - 'dpkg'), + call.packageListBlock('dst-tag', 'bpkg'), + call.packageListBlock('dst-tag', 'cpkg'), + call.packageListBlock('dst-tag', 'dpkg'), call.multiCall(batch=100), - call.groupListRemove('dst-tag', - 'group3', - force=None), - call.groupListBlock('dst-tag', - 'group4'), + call.groupListRemove('dst-tag', 'group3', force=None), + call.groupListBlock('dst-tag', 'group4'), call.multiCall(batch=100), - call.groupPackageListRemove('dst-tag', - 'group1', - 'pkg5', + call.groupPackageListRemove('dst-tag', 'group1', 'pkg5', force=None), - call.groupPackageListBlock('dst-tag', - 'group2', - 'cpkg'), + call.groupPackageListBlock('dst-tag', 'group2', 'cpkg'), call.multiCall(batch=100)]) self.assert_console_message(stdout, """ List of changes: @@ -654,14 +597,14 @@ List of changes: ] self.session.getTagGroups.return_value = [] self.session.getBuildConfig.side_effect = [{'id': 1, - 'name': 'src-tag', - 'arches': 'arch1 arch2', - 'perm_id': 1, - 'maven_support': False, - 'maven_include_all': True, - 'locked': False, - 'extra': {}}] - self.session.getTag.side_effect = [ {'id': 2, + 'name': 'src-tag', + 'arches': 'arch1 arch2', + 'perm_id': 1, + 'maven_support': False, + 'maven_include_all': True, + 'locked': False, + 'extra': {}}] + self.session.getTag.side_effect = [{'id': 2, 'name': 'dst-tag', 'arches': 'arch1 arch2', 'perm_id': 1, @@ -719,8 +662,8 @@ List of changes: 'owner_name': 'b_owner', 'tag_name': 'src-tag'}, ], - [{'id': 1, - 'package_name': 'pkg', + [{'id': 1, + 'package_name': 'pkg', 'nvr': 'pkg-1.0-23', 'state': 1, 'owner_name': 'b_owner', @@ -757,14 +700,14 @@ List of changes: 'locked': False, 'extra': {}}] self.session.getBuildConfig.return_value = { - 'id': 1, - 'name': 'src-tag', - 'arches': 'arch1 arch2', - 'perm_id': 1, - 'maven_support': False, - 'maven_include_all': True, - 'locked': False, - 'extra': {}} + 'id': 1, + 'name': 'src-tag', + 'arches': 'arch1 arch2', + 'perm_id': 1, + 'maven_support': False, + 'maven_include_all': True, + 'locked': False, + 'extra': {}} handle_clone_tag(self.options, self.session, args) self.activate_session.assert_called_once() self.assert_console_message(stdout, """ @@ -806,19 +749,19 @@ List of changes: 'owner_name': 'b_owner', 'tag_name': 'src-tag'}, ], - [{'id': 2, - 'package_name': 'pkg', - 'nvr': 'pkg-1.0-21', - 'state': 1, - 'owner_name': 'b_owner', - 'tag_name': 'src-tag'}, - {'id': 3, - 'package_name': 'pkg', - 'nvr': 'pkg-0.1-1', - 'state': 1, - 'owner_name': 'b_owner', - 'tag_name': 'src-tag'}, - ] + [{'id': 2, + 'package_name': 'pkg', + 'nvr': 'pkg-1.0-21', + 'state': 1, + 'owner_name': 'b_owner', + 'tag_name': 'src-tag'}, + {'id': 3, + 'package_name': 'pkg', + 'nvr': 'pkg-0.1-1', + 'state': 1, + 'owner_name': 'b_owner', + 'tag_name': 'src-tag'}, + ] ] self.session.getTagGroups.return_value = [] self.session.getTag.side_effect = [{'id': 2, @@ -829,7 +772,7 @@ List of changes: 'maven_include_all': True, 'locked': False, 'extra': {}}, - {'id': 2, + {'id': 2, 'name': 'dst-tag', 'arches': 'arch1 arch2', 'perm_id': 1, @@ -838,14 +781,14 @@ List of changes: 'locked': False, 'extra': {}}] self.session.getBuildConfig.side_effect = [{'id': 1, - 'name': 'src-tag', - 'arches': 'arch1 arch2', - 'perm_id': 1, - 'maven_support': False, - 'maven_include_all': True, - 'locked': False, - 'extra': {}}, - ] + 'name': 'src-tag', + 'arches': 'arch1 arch2', + 'perm_id': 1, + 'maven_support': False, + 'maven_include_all': True, + 'locked': False, + 'extra': {}}, + ] handle_clone_tag(self.options, self.session, args) self.activate_session.assert_called_once() self.assert_console_message(stdout, """ @@ -861,6 +804,7 @@ List of changes: Action Package Group ------- ---------------------------- ---------------------------- """) + def test_handle_clone_tag_help(self): self.assert_help( handle_clone_tag, diff --git a/tests/test_cli/test_free_task.py b/tests/test_cli/test_free_task.py new file mode 100644 index 0000000..49bceef --- /dev/null +++ b/tests/test_cli/test_free_task.py @@ -0,0 +1,55 @@ +from __future__ import absolute_import +import mock +from six.moves import StringIO + +from koji_cli.commands import handle_free_task +from . import utils + + +class TestFreeTask(utils.CliTestCase): + + def setUp(self): + self.options = mock.MagicMock() + self.options.maxDiff = None + self.session = mock.MagicMock() + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s free-task [options] [ ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + + @mock.patch('sys.stderr', new_callable=StringIO) + def test_free_task_without_arg(self, stderr): + expected = self.format_error_message('please specify at least one task_id') + with self.assertRaises(SystemExit) as ex: + handle_free_task(self.options, self.session, []) + self.assertExitCode(ex, 2) + self.assert_console_message(stderr, expected) + self.activate_session_mock.assert_called_with(self.session, self.options) + + @mock.patch('sys.stderr', new_callable=StringIO) + def test_free_task_id_string_chars(self, stderr): + expected = self.format_error_message('task_id must be an integer') + with self.assertRaises(SystemExit) as ex: + handle_free_task(self.options, self.session, ['1abc']) + self.assertExitCode(ex, 2) + self.assert_console_message(stderr, expected) + self.activate_session_mock.assert_called_with(self.session, self.options) + + @mock.patch('sys.stdout', new_callable=StringIO) + def test_free_task_valid(self, stdout): + self.session.freeTask.side_effect = [True, True, True] + handle_free_task(self.options, self.session, ['1', '2', '3']) + self.assert_console_message(stdout, '') + self.activate_session_mock.assert_called_with(self.session, self.options) + + def test_handle_free_task_help(self): + self.assert_help( + handle_free_task, + """Usage: %s free-task [options] [ ...] +(Specify the --help global option for a list of other help options) + +Options: + -h, --help show this help message and exit +""" % self.progname) diff --git a/tests/test_cli/test_import_archive.py b/tests/test_cli/test_import_archive.py index 9db69aa..15d2e36 100644 --- a/tests/test_cli/test_import_archive.py +++ b/tests/test_cli/test_import_archive.py @@ -14,28 +14,129 @@ class TestImportArchive(utils.CliTestCase): self.options.debug = False self.session = mock.MagicMock() self.session.getAPIVersion.return_value = koji.API_VERSION + self.build_id = '1' + self.archive_path = '/mnt/brew/work/test-archive.type' + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() + self.error_format = """Usage: %s import-archive [ [ ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_remove_pkg(self, activate_session_mock, stderr): + def test_handle_remove_pkg(self, stderr): tag = 'tag' dsttag = {'name': tag, 'id': 1} package = 'package' args = [tag, package] kwargs = {'force': None} - options = mock.MagicMock() - # Mock out the xmlrpc server - session = mock.MagicMock() - - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': package, 'package_id': 1}] # Run it and check immediate output # args: tag, package # expected: success - handle_remove_pkg(options, session, args) + handle_remove_pkg(self.options, self.session, args) + actual = stderr.getvalue() + expected = '' + self.assertMultiLineEqual(actual, expected) + # Finally, assert that things were called as we expected. + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_called_once_with(tagID=dsttag['id'], with_owners=False) + self.session.packageListRemove.assert_called_once_with( + tag, package, **kwargs) + self.session.multiCall.assert_called_once_with(strict=True) + + @mock.patch('sys.stderr', new_callable=six.StringIO) + def test_handle_remove_pkg_parameter_error(self, stderr): + tag = 'tag' + dsttag = {'name': tag, 'id': 1} + package = 'package' + args = [tag, package] + kwargs = {'force': None} + + self.session.getTag.return_value = dsttag + self.session.listPackages.side_effect = [koji.ParameterError, + [{'package_name': package, 'package_id': 1}]] + # Run it and check immediate output + # args: tag, package + # expected: success + handle_remove_pkg(self.options, self.session, args) actual = stderr.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_called_once_with(tagID=dsttag['id'], with_owners=False) - session.packageListRemove.assert_called_once_with( + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_has_calls([ + call(tagID=dsttag['id'], with_owners=False), + call(tagID=dsttag['id']) + ]) + self.session.packageListRemove.assert_called_once_with( tag, package, **kwargs) - session.multiCall.assert_called_once_with(strict=True) + self.session.multiCall.assert_called_once_with(strict=True) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_remove_pkg_multi_pkg(self, activate_session_mock, stdout): + def test_handle_remove_pkg_multi_pkg(self, stdout): tag = 'tag' dsttag = {'name': tag, 'id': 1} packages = ['package1', 'package2', 'package3'] args = [tag] + packages kwargs = {'force': None} - options = mock.MagicMock() - # Mock out the xmlrpc server - session = mock.MagicMock() - - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': 'package1', 'package_id': 1}, {'package_name': 'package2', 'package_id': 2}, {'package_name': 'package3', 'package_id': 3}, @@ -71,39 +101,34 @@ class TestRemovePkg(utils.CliTestCase): # Run it and check immediate output # args: tag, package1, package2, package3 # expected: success - rv = handle_remove_pkg(options, session, args) + rv = handle_remove_pkg(self.options, self.session, args) actual = stdout.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.assertEqual( - session.mock_calls, [ + self.session.mock_calls, [ call.getTag(tag), call.listPackages(tagID=dsttag['id'], with_owners=False), call.packageListRemove(tag, packages[0], **kwargs), call.packageListRemove(tag, packages[1], **kwargs), call.packageListRemove(tag, packages[2], **kwargs), - call.multiCall( strict=True) + call.multiCall(strict=True) ] ) self.assertNotEqual(rv, 1) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_remove_pkg_force(self, activate_session_mock, stdout): + def test_handle_remove_pkg_force(self, stdout): tag = 'tag' dsttag = {'name': tag, 'id': 1} packages = ['package1', 'package2', 'package3'] args = ['--force', tag] + packages kwargs = {'force': True} - options = mock.MagicMock() - - # Mock out the xmlrpc server - session = mock.MagicMock() - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': 'package1', 'package_id': 1}, {'package_name': 'package2', 'package_id': 2}, {'package_name': 'package3', 'package_id': 3}, @@ -112,14 +137,14 @@ class TestRemovePkg(utils.CliTestCase): # Run it and check immediate output # args: --force, tag, package1, package2, package3 # expected: success - rv = handle_remove_pkg(options, session, args) + rv = handle_remove_pkg(self.options, self.session, args) actual = stdout.getvalue() expected = '' self.assertMultiLineEqual(actual, expected) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) + self.activate_session_mock.assert_called_once_with(self.session, self.options) self.assertEqual( - session.mock_calls, [ + self.session.mock_calls, [ call.getTag(tag), call.listPackages(tagID=dsttag['id'], with_owners=False), call.packageListRemove(tag, packages[0], **kwargs), @@ -130,101 +155,73 @@ class TestRemovePkg(utils.CliTestCase): ) self.assertNotEqual(rv, 1) - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_remove_pkg_no_package(self, activate_session_mock, stderr): + def test_handle_remove_pkg_no_package(self): tag = 'tag' dsttag = {'name': tag, 'id': 1} packages = ['package1', 'package2', 'package3'] - args = [tag] + packages - options = mock.MagicMock() + arguments = [tag] + packages - # Mock out the xmlrpc server - session = mock.MagicMock() - - session.getTag.return_value = dsttag - session.listPackages.return_value = [ + self.session.getTag.return_value = dsttag + self.session.listPackages.return_value = [ {'package_name': 'package1', 'package_id': 1}, {'package_name': 'package3', 'package_id': 3}, {'package_name': 'other_package', 'package_id': 4}] # Run it and check immediate output # args: tag, package1, package2, package3 # expected: failed: can not find package2 under tag - with self.assertRaises(SystemExit) as ex: - handle_remove_pkg(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'Package package2 is not in tag tag\n' - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_remove_pkg, + self.options, self.session, arguments, + stderr='Package package2 is not in tag tag\n', + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_called_once_with(tagID=dsttag['id'], with_owners=False) - session.packageListRemove.assert_not_called() - session.multiCall.assert_not_called() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_called_once_with(tagID=dsttag['id'], with_owners=False) + self.session.packageListRemove.assert_not_called() + self.session.multiCall.assert_not_called() - @mock.patch('sys.stderr', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_remove_pkg_tag_no_exists( - self, activate_session_mock, stderr): + def test_handle_remove_pkg_tag_no_exists(self): tag = 'tag' dsttag = None packages = ['package1', 'package2', 'package3'] - args = [tag] + packages - options = mock.MagicMock() + arguments = [tag] + packages - # Mock out the xmlrpc server - session = mock.MagicMock() - - session.getTag.return_value = dsttag + self.session.getTag.return_value = dsttag # Run it and check immediate output # args: tag, package1, package2, package3 # expected: failed: tag does not exist - with self.assertRaises(SystemExit) as ex: - handle_remove_pkg(options, session, args) - self.assertExitCode(ex, 1) - actual = stderr.getvalue() - expected = 'No such tag: %s\n' % tag - self.assertMultiLineEqual(actual, expected) + self.assert_system_exit( + handle_remove_pkg, + self.options, self.session, arguments, + stderr='No such tag: %s\n' % tag, + stdout='', + activate_session=None, + exit_code=1) # Finally, assert that things were called as we expected. - activate_session_mock.assert_called_once_with(session, options) - session.getTag.assert_called_once_with(tag) - session.listPackages.assert_not_called() - session.packageListRemove.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_remove_pkg_help( - self, activate_session_mock, stderr, stdout): - args = [] - options = mock.MagicMock() - - progname = os.path.basename(sys.argv[0]) or 'koji' - - # Mock out the xmlrpc server - session = mock.MagicMock() + self.activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.getTag.assert_called_once_with(tag) + self.session.listPackages.assert_not_called() + self.session.packageListRemove.assert_not_called() + def test_handle_remove_pkg_without_args(self): + arguments = [] # Run it and check immediate output - with self.assertRaises(SystemExit) as ex: - handle_remove_pkg(options, session, args) - self.assertExitCode(ex, 2) - actual_stdout = stdout.getvalue() - actual_stderr = stderr.getvalue() - expected_stdout = '' - expected_stderr = """Usage: %s remove-pkg [options] [ ...] -(Specify the --help global option for a list of other help options) - -%s: error: Please specify a tag and at least one package -""" % (progname, progname) - self.assertMultiLineEqual(actual_stdout, expected_stdout) - self.assertMultiLineEqual(actual_stderr, expected_stderr) + self.assert_system_exit( + handle_remove_pkg, + self.options, self.session, arguments, + stderr=self.format_error_message('Please specify a tag and at least one package'), + stdout='', + activate_session=None, + exit_code=2) # Finally, assert that things were called as we expected. - activate_session_mock.assert_not_called() - session.getTag.assert_not_called() - session.listPackages.assert_not_called() - session.packageListRemove.assert_not_called() + self.activate_session_mock.assert_not_called() + self.session.getTag.assert_not_called() + self.session.listPackages.assert_not_called() + self.session.packageListRemove.assert_not_called() if __name__ == '__main__': diff --git a/tests/test_cli/test_set_task_priority.py b/tests/test_cli/test_set_task_priority.py index 15de222..fb2c23a 100644 --- a/tests/test_cli/test_set_task_priority.py +++ b/tests/test_cli/test_set_task_priority.py @@ -4,78 +4,89 @@ import six import unittest from koji_cli.commands import handle_set_task_priority + +import koji from . import utils class TestSetTaskPriority(utils.CliTestCase): - # Show long diffs in error output... - maxDiff = None - def setUp(self): + # Show long diffs in error output... + self.maxDiff = None + self.options = mock.MagicMock() + self.options.debug = False + self.session = mock.MagicMock() + self.session.getAPIVersion.return_value = koji.API_VERSION + self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start() self.error_format = """Usage: %s set-task-priority [options] --priority= [ ...] (Specify the --help global option for a list of other help options) %s: error: {message} """ % (self.progname, self.progname) + @mock.patch('sys.stderr', new_callable=six.StringIO) @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('koji_cli.commands.activate_session') - def test_handle_set_task_priority( - self, - activate_session_mock, - stdout): + def test_handle_set_task_priority(self, stdout, stderr): """Test handle_set_task_priority function""" - session = mock.MagicMock() - options = mock.MagicMock() arguments = ['--priority', '10', '1', '11', '121', '1331'] # Case 1. no task id error - expected = self.format_error_message( - "You must specify at least one task id") - self.assert_system_exit( handle_set_task_priority, - options, - session, - [], - stderr=expected, + self.options, self.session, [], + stderr=self.format_error_message("You must specify at least one task id"), activate_session=None) - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() # Case 2. no --priority is specified - expected = self.format_error_message( - "You must specify --priority") - self.assert_system_exit( handle_set_task_priority, - options, - session, - ['1'], - stderr=expected, + self.options, self.session, ['1'], + stderr=self.format_error_message("You must specify --priority"), activate_session=None) - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() # Case 3 . Wrong task id (not integer format) for case in ['1.0', '0.1', 'abc']: - expected = self.format_error_message( - "Task numbers must be integers") - self.assert_system_exit( handle_set_task_priority, - options, - session, - [case, '--priority', '10'], - stderr=expected, + self.options, self.session, [case, '--priority', '10'], + stderr=self.format_error_message("Task numbers must be integers"), activate_session=None) - activate_session_mock.assert_not_called() + self.activate_session_mock.assert_not_called() calls = [mock.call(int(tid), 10, False) for tid in arguments[2:]] - handle_set_task_priority(options, session, arguments) - activate_session_mock.assert_called_with(session, options) - session.setTaskPriority.assert_has_calls(calls) + handle_set_task_priority(self.options, self.session, arguments) + self.activate_session_mock.assert_called_with(self.session, self.options) + self.session.setTaskPriority.assert_has_calls(calls) self.assert_console_message(stdout, '') + # Case 4. User doesn't have admin perm + self.session.hasPerm.return_value = False + self.session.getLoggedInUser.return_value = { + 'authtype': 2, + 'id': 1, + 'krb_principal': None, + 'krb_principals': [], + 'name': 'testuser', + 'status': 0, + 'usertype': 0 + } + self.assert_system_exit( + handle_set_task_priority, + self.options, self.session, ['--priority', '10', '1', '2'], + stderr="admin permission required (logged in as testuser)\n", + activate_session=None, + exit_code=1) + + # Case 5. Task is closed + self.session.hasPerm.return_value = True + self.session.setTaskPriority.side_effect = koji.GenericError + expected_warn = "Can't update task priority on closed task: 1\n" + handle_set_task_priority(self.options, self.session, ['--priority', '10', '1']) + self.assert_console_message(stderr, expected_warn) + def test_handle_set_task_priority_help(self): self.assert_help( handle_set_task_priority,