From 0f06d749ef9062cc9f910f937ae803d6d5024590 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Jul 22 2025 14:19:10 +0000 Subject: unit tests --- diff --git a/tests/test_cli/data/list-commands-admin.txt b/tests/test_cli/data/list-commands-admin.txt index 1928c1b..84f3180 100644 --- a/tests/test_cli/data/list-commands-admin.txt +++ b/tests/test_cli/data/list-commands-admin.txt @@ -49,7 +49,8 @@ admin commands: regen-repo Generate a current repo if there is not one remove-external-repo Remove an external repo from a tag or tags, or remove entirely remove-group Remove group from tag - remove-group-pkg Remove a package from a group's package listing + remove-group-pkg Remove packages from a group's package listing + remove-group-req Remove entries from a group's requirement listing remove-host-from-channel Remove a host from a channel remove-pkg Remove a package from the listing for tag remove-sig Remove signed RPMs from db and disk @@ -65,6 +66,7 @@ admin commands: set-pkg-owner Set the owner for a package set-pkg-owner-global Set the owner for a package globally set-task-priority Set task priority + unblock-group Unblock a group from tag unblock-group-pkg Unblock a package from a group's package listing unblock-group-req Unblock a group's requirement listing unblock-pkg Unblock a package in the listing for tag diff --git a/tests/test_cli/data/list-commands.txt b/tests/test_cli/data/list-commands.txt index 809229d..9671bba 100644 --- a/tests/test_cli/data/list-commands.txt +++ b/tests/test_cli/data/list-commands.txt @@ -49,7 +49,8 @@ admin commands: regen-repo Generate a current repo if there is not one remove-external-repo Remove an external repo from a tag or tags, or remove entirely remove-group Remove group from tag - remove-group-pkg Remove a package from a group's package listing + remove-group-pkg Remove packages from a group's package listing + remove-group-req Remove entries from a group's requirement listing remove-host-from-channel Remove a host from a channel remove-pkg Remove a package from the listing for tag remove-sig Remove signed RPMs from db and disk @@ -65,6 +66,7 @@ admin commands: set-pkg-owner Set the owner for a package set-pkg-owner-global Set the owner for a package globally set-task-priority Set task priority + unblock-group Unblock a group from tag unblock-group-pkg Unblock a package from a group's package listing unblock-group-req Unblock a group's requirement listing unblock-pkg Unblock a package in the listing for tag diff --git a/tests/test_cli/test_block_group.py b/tests/test_cli/test_block_group.py index 2b5f499..41ebade 100644 --- a/tests/test_cli/test_block_group.py +++ b/tests/test_cli/test_block_group.py @@ -56,10 +56,11 @@ class TestBlockGroup(utils.CliTestCase): def test_handle_block_group_nonexistent_group(self): tag = 'tag' + tagID = 100 group = 'group' arguments = [tag, group] self.session.hasPerm.return_value = True - self.session.getTag.return_value = tag + self.session.getTag.return_value = {'name': tag, 'id': tagID} self.session.getTagGroups.return_value = [] # Run it and check immediate output @@ -75,18 +76,19 @@ class TestBlockGroup(utils.CliTestCase): 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.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) self.session.groupListBlock.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) def test_handle_block_group(self, stdout): tag = 'tag' + tagID = 100 group = 'group' arguments = [tag, group] self.session.hasPerm.return_value = True - self.session.getTag.return_value = tag + self.session.getTag.return_value = {'name': tag, 'id': tagID} self.session.getTagGroups.return_value = [ - {'name': 'group', 'group_id': 'groupId'}] + {'name': 'group', 'group_id': 'groupId', 'blocked': False}] # Run it and check immediate output rv = handle_block_group(self.options, self.session, arguments) @@ -98,10 +100,34 @@ class TestBlockGroup(utils.CliTestCase): 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.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) self.session.groupListBlock.assert_called_once_with(tag, group) self.assertEqual(rv, None) + def test_handle_group_already_blocked(self): + tag = 'tag' + tagID = 100 + group = 'group' + arguments = [tag, group] + self.session.hasPerm.return_value = True + self.session.getTag.return_value = {'name': tag, 'id': tagID} + self.session.getTagGroups.return_value = [ + {'name': 'group', 'group_id': 'groupId', 'blocked': True}] + + # Run it and check immediate output + self.assert_system_exit( + handle_block_group, + self.options, self.session, arguments, + stderr='Group group is already blocked in this tag\n', + stdout='', + exit_code=1) + + # Finally, assert that things were called as we expected. + self.session.hasPerm.assert_called_once_with('admin') + self.session.getTag.assert_called_once_with(tag) + self.session.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) + self.session.groupListBlock.assert_not_called() + def test_handle_block_group_error_handling(self): expected = self.format_error_message( "Please specify a tag name and a group name") diff --git a/tests/test_cli/test_remove_group.py b/tests/test_cli/test_remove_group.py index a6b058f..a4e1638 100644 --- a/tests/test_cli/test_remove_group.py +++ b/tests/test_cli/test_remove_group.py @@ -54,12 +54,13 @@ class TestRemoveGroup(utils.CliTestCase): @mock.patch('koji_cli.commands.activate_session') def test_handle_remove_group_nonexistent_group(self, activate_session_mock, stdout, stderr): tag = 'tag' + tagID = 100 group = 'group' arguments = [tag, group] # Mock out the xmlrpc server self.session.hasPerm.return_value = True - self.session.getTag.return_value = tag + self.session.getTag.return_value = {'name': tag, 'id': tagID} self.session.getTagGroups.return_value = [] with self.assertRaises(SystemExit): @@ -69,7 +70,59 @@ class TestRemoveGroup(utils.CliTestCase): 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.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) + self.session.groupListRemove.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_group_blocked_group(self, activate_session_mock, stdout, stderr): + tag = 'tag' + tagID = 100 + group = 'group' + arguments = [tag, group] + + # Mock out the xmlrpc server + self.session.hasPerm.return_value = True + self.session.getTag.return_value = {'name': tag, 'id': tagID} + self.session.getTagGroups.return_value = [{'name': 'group', 'tag_id': tagID, + 'blocked': True}] + + with self.assertRaises(SystemExit): + handle_remove_group(self.options, self.session, arguments) + + # assert that things were called as we expected. + 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(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) + self.session.groupListRemove.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_group_inherited_group(self, activate_session_mock, stdout, stderr): + tag = 'tag' + tagID = 100 + parentID = 99 + group = 'group' + arguments = [tag, group] + + # Mock out the xmlrpc server + self.session.hasPerm.return_value = True + self.session.getTag.return_value = {'name': tag, 'id': tagID} + self.session.getTagGroups.return_value = [{'name': 'group', 'tag_id': parentID, + 'blocked': False}] + + with self.assertRaises(SystemExit): + handle_remove_group(self.options, self.session, arguments) + + # assert that things were called as we expected. + activate_session_mock.assert_called_once_with(self.session, self.options) + self.session.hasPerm.assert_called_once_with('admin') + self.session.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) + expected_calls = [mock.call(tag), mock.call(parentID)] + self.assertEqual(self.session.getTag.call_args_list, expected_calls) self.session.groupListRemove.assert_not_called() @mock.patch('sys.stdout', new_callable=six.StringIO) @@ -77,14 +130,16 @@ class TestRemoveGroup(utils.CliTestCase): @mock.patch('koji_cli.commands.activate_session') def test_handle_remove_group(self, activate_session_mock, stdout, stderr): tag = 'tag' + tagID = 100 group = 'group' arguments = [tag, group] # Mock out the xmlrpc server self.session.hasPerm.return_value = True - self.session.getTag.return_value = tag + self.session.getTag.return_value = {'name': tag, 'id': tagID} self.session.getTagGroups.return_value = [ - {'name': 'group', 'group_id': 'groupId'}] + {'name': 'group', 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID}] + # so case where group is present and directly in the tag rv = handle_remove_group(self.options, self.session, arguments) @@ -92,7 +147,7 @@ class TestRemoveGroup(utils.CliTestCase): 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.getTagGroups.assert_called_once_with(tagID, incl_pkgs=False, incl_reqs=False, incl_blocked=True) self.session.groupListRemove.assert_called_once_with(tag, group) self.assertEqual(rv, None) diff --git a/tests/test_cli/test_remove_group_pkg.py b/tests/test_cli/test_remove_group_pkg.py index 62277a6..df167b0 100644 --- a/tests/test_cli/test_remove_group_pkg.py +++ b/tests/test_cli/test_remove_group_pkg.py @@ -25,6 +25,9 @@ class TestRemoveGroupPkg(utils.CliTestCase): %s: error: {message} """ % (self.progname, self.progname) + def tearDown(self): + mock.patch.stopall() + def test_handle_remove_pkg_not_existing_tag(self): tag = 'tag' package = 'package' @@ -68,12 +71,17 @@ class TestRemoveGroupPkg(utils.CliTestCase): @mock.patch('sys.stderr', new_callable=six.StringIO) def test_handle_remove_pkg(self, stderr, stdout): tag = 'tag' - dsttag = {'name': tag, 'id': 1} + tagID = 1 + dsttag = {'name': tag, 'id': tagID} package = 'package' group = 'group' args = [tag, group, package] self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'packagelist': [{'package': package, 'blocked': False, 'tag_id': tagID}] + }] self.session.groupPackageListRemove.return_value = None handle_remove_group_pkg(self.options, self.session, args) actual = stderr.getvalue() @@ -86,24 +94,99 @@ class TestRemoveGroupPkg(utils.CliTestCase): self.activate_session_mock.assert_called_once_with(self.session, self.options) self.session.getTag.assert_called_once_with(tag) - @mock.patch('sys.stdout', new_callable=six.StringIO) - @mock.patch('sys.stderr', new_callable=six.StringIO) - def test_handle_remove_pkg_with_force(self, stderr, stdout): + def test_handle_group_not_present(self): tag = 'tag' - dsttag = {'name': tag, 'id': 1} + tagID = 1 + dsttag = {'name': tag, 'id': tagID} package = 'package' group = 'group' - args = [tag, group, package, '--force'] + args = [tag, group, package] self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [] self.session.groupPackageListRemove.return_value = None - handle_remove_group_pkg(self.options, self.session, args) - actual = stderr.getvalue() - expected = '' - self.assertMultiLineEqual(actual, expected) - 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.assert_system_exit( + handle_remove_group_pkg, + self.options, self.session, args, + stderr='Group group is not present in tag tag\n', + stdout='', + exit_code=1) + + self.session.getTag.assert_called_once_with(tag) + + def test_handle_package_not_included(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + package = 'package' + group = 'group' + args = [tag, group, package] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'packagelist': [] + }] + self.session.groupPackageListRemove.return_value = None + + self.assert_system_exit( + handle_remove_group_pkg, + self.options, self.session, args, + stdout='Package package is not included in this group\n', + stderr='Invalid parameters\n', + exit_code=1) + + self.session.getTag.assert_called_once_with(tag) + + def test_handle_package_blocked(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + package = 'package' + group = 'group' + args = [tag, group, package] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'packagelist': [{'package': package, 'blocked': True, 'tag_id': tagID}] + }] + self.session.groupPackageListRemove.return_value = None + + self.assert_system_exit( + handle_remove_group_pkg, + self.options, self.session, args, + stdout='Package package is blocked in this group. ' + 'You could use unblock-group-pkg to unblock it\n', + stderr='Invalid parameters\n', + exit_code=1) + self.session.getTag.assert_called_once_with(tag) + + def test_handle_package_inherited(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + parentID = 20 + ptag = {'name': 'parent', 'id': parentID} + package = 'package' + group = 'group' + args = [tag, group, package] + + self.session.getTag.side_effect = [dsttag, ptag] + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'packagelist': [{'package': package, 'blocked': False, 'tag_id': parentID}] + }] + self.session.groupPackageListRemove.return_value = None + + self.assert_system_exit( + handle_remove_group_pkg, + self.options, self.session, args, + stdout='The entry for package package is inherited from parent. You could use block-group-pkg to prevent this\n', + stderr='Invalid parameters\n', + exit_code=1) + + +# the end diff --git a/tests/test_cli/test_remove_group_req.py b/tests/test_cli/test_remove_group_req.py new file mode 100644 index 0000000..7970639 --- /dev/null +++ b/tests/test_cli/test_remove_group_req.py @@ -0,0 +1,198 @@ +from __future__ import absolute_import + +import mock +import six + +from koji_cli.commands import handle_remove_group_req + +import koji +from . import utils + + +class TestRemoveGroupReq(utils.CliTestCase): + + 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 remove-group-req [options] [ ...] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + + def tearDown(self): + mock.patch.stopall() + + def test_wrong_count_args(self): + tag = 'tag' + group = 'group' + args = [tag, group] + expected_error = self.format_error_message( + 'You must specify a tag name, group name, and one or more requirement names') + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stderr=expected_error, + stdout='', + activate_session=None, + exit_code=2) + # Finally, assert that things were called as we expected. + self.activate_session_mock.assert_not_called() + self.session.getTag.assert_not_called() + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + def test_no_such_tag(self): + tag = 'tag' + group = 'group' + req = 'other_group' + args = [tag, group, req] + self.session.getTag.return_value = None + + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stderr='No such tag: tag\n', + stdout='', + activate_session=None, + exit_code=1) + + # Finally, assert that things were called as we expected. + self.session.getTag.assert_called_once() + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + def test_success(self, stderr, stdout): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + group = 'group' + req = 'other_group' + args = [tag, group, req] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'grouplist': [{'name': req, 'blocked': False, 'tag_id': tagID}] + }] + + handle_remove_group_req(self.options, self.session, args) + + actual = stderr.getvalue() + expected = '' + self.assertMultiLineEqual(actual, expected) + 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.multicall.assert_called_once() + + def test_handle_group_not_present(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + group = 'group' + req = 'other_group' + args = [tag, group, req] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [] + + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stderr='Group group is not present in tag tag\n', + stdout='', + exit_code=1) + + self.session.getTag.assert_called_once_with(tag) + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + def test_handle_req_not_included(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + group = 'group' + req = 'other_group' + args = [tag, group, req] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'grouplist': [] + }] + + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stdout='Req other_group is not included in this group\n', + stderr='Invalid parameters\n', + exit_code=1) + + self.session.getTag.assert_called_once_with(tag) + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + def test_handle_req_blocked(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + group = 'group' + req = 'other_group' + args = [tag, group, req] + + self.session.getTag.return_value = dsttag + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'grouplist': [{'name': req, 'blocked': True, 'tag_id': tagID}] + }] + + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stdout='Req other_group is blocked in this group. ' + 'You could use unblock-group-req to unblock it\n', + stderr='Invalid parameters\n', + exit_code=1) + + self.session.getTag.assert_called_once_with(tag) + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + def test_handle_req_inherited(self): + tag = 'tag' + tagID = 1 + dsttag = {'name': tag, 'id': tagID} + parentID = 20 + ptag = {'name': 'parent', 'id': parentID} + group = 'group' + req = 'other_group' + args = [tag, group, req] + + self.session.getTag.side_effect = [dsttag, ptag] + self.session.getTagGroups.return_value = [ + {'name': group, 'group_id': 'groupId', 'blocked': False, 'tag_id': tagID, + 'grouplist': [{'name': req, 'blocked': False, 'tag_id': parentID}] + }] + + self.assert_system_exit( + handle_remove_group_req, + self.options, self.session, args, + stdout='The entry for req other_group is inherited from parent. You could use block-group-req to prevent this\n', + stderr='Invalid parameters\n', + exit_code=1) + self.session.groupReqListRemove.assert_not_called() + self.session.multicall.assert_not_called() + + +# the end diff --git a/tests/test_cli/test_unblock_group.py b/tests/test_cli/test_unblock_group.py new file mode 100644 index 0000000..797527a --- /dev/null +++ b/tests/test_cli/test_unblock_group.py @@ -0,0 +1,74 @@ +from __future__ import absolute_import + +try: + from unittest import mock +except ImportError: + import mock +import six +import koji + +from koji_cli.commands import handle_unblock_group +from . import utils + + +class TestBlockGroup(utils.CliTestCase): + # Show long diffs in error output... + 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 unblock-group [options] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + + def tearDown(self): + mock.patch.stopall() + + def test_handle_unblock_group_badargs(self): + tag = 'tag' + group = 'group' + arguments = [tag, group, 'extra_arg'] + self.session.hasPerm.return_value = True + self.session.getTag.return_value = None + + expected = self.format_error_message( + "You must specify a tag name and group name") + # Run it and check immediate output + self.assert_system_exit( + handle_unblock_group, + self.options, self.session, arguments, + stderr=expected, + stdout='', + activate_session=None, + exit_code=2) + + # Finally, assert that things were called as we expected. + self.activate_session_mock.assert_not_called() + self.session.groupListUnblock.assert_not_called() + + @mock.patch('sys.stdout', new_callable=six.StringIO) + def test_handle_unblock_group(self, stdout): + tag = 'tag' + group = 'group' + arguments = [tag, group] + + # Run it and check immediate output + rv = handle_unblock_group(self.options, self.session, arguments) + 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.groupListUnblock.assert_called_once_with(tag, group) + self.assertEqual(rv, None) + + +# the end