#3270 Increase CLI test cases
Merged 2 years ago by tkopecek. Opened 2 years ago by jcupova.

Increase CLI test cases
Jana Cupova • 2 years ago  
@@ -44,7 +44,9 @@ 

              args,

              stderr=self.format_error_message(

                  "This command takes two arguments: <src-tag> <dst-tag>"),

-             activate_session=None)

+             activate_session=None,

+             exit_code=2

+         )

          self.activate_session.assert_not_called()

  

      def test_handle_clone_tag_not_admin(self):
@@ -55,9 +57,10 @@ 

              self.options,

              self.session,

              args,

-             stderr=self.format_error_message(

-                 "This action requires tag or admin privileges"),

-             activate_session=None)

+             stderr=self.format_error_message("This action requires tag or admin privileges"),

+             activate_session=None,

+             exit_code=2

+         )

          self.activate_session.assert_called_once()

          self.session.hasPerm.assert_has_calls([call('admin'), call('tag')])

  
@@ -68,9 +71,9 @@ 

              self.options,

              self.session,

              args,

-             stderr=self.format_error_message(

-                 "Source and destination tags must be different."),

-             activate_session=None)

+             stderr=self.format_error_message("Source and destination tags must be different."),

+             activate_session=None,

+             exit_code=2)

          self.activate_session.assert_called_once()

  

      def test_handle_clone_tag_invalid_batch(self):
@@ -80,9 +83,9 @@ 

              self.options,

              self.session,

              args,

-             stderr=self.format_error_message(

-                 "batch size must be bigger than zero"),

-             activate_session=None)

+             stderr=self.format_error_message("batch size must be bigger than zero"),

+             activate_session=None,

+             exit_code=2)

          self.activate_session.assert_called_once()

  

      def test_handle_clone_tag_no_srctag(self):
@@ -94,17 +97,15 @@ 

              self.session,

              args,

              stderr=self.format_error_message("No such src-tag: src-tag"),

-             activate_session=None)

+             activate_session=None,

+             exit_code=2)

          self.activate_session.assert_called_once()

-         self.activate_session.getTag.has_called([call('src-tag'),

-                                                  call('dst-tag')])

+         self.activate_session.getTag.has_called([call('src-tag'), call('dst-tag')])

  

      def test_handle_clone_tag_locked(self):

          args = ['src-tag', 'dst-tag']

-         self.session.getTag.side_effect = [{'id': 1,

-                                             'locked': True},

-                                            {'id': 2,

-                                             'locked': False}]

+         self.session.getTag.side_effect = [{'id': 1, 'locked': True},

+                                            {'id': 2, 'locked': False}]

          self.assert_system_exit(

              handle_clone_tag,

              self.options,
@@ -113,13 +114,12 @@ 

              stderr=self.format_error_message(

                  "Error: You are attempting to clone from or to a tag which is locked.\n"

                  "Please use --force if this is what you really want to do."),

-             activate_session=None)

+             activate_session=None,

+             exit_code=2)

          self.activate_session.assert_called_once()

-         self.activate_session.getTag.has_called([call('src-tag'),

-                                                  call('dst-tag')])

+         self.activate_session.getTag.has_called([call('src-tag'), call('dst-tag')])

  

-         self.activate_session.getTag.has_called([call('src-tag'),

-                                                  call('dst-tag')])

+         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):

@@ -15,6 +15,10 @@ 

      maxDiff = None

  

      def setUp(self):

+         self.options = mock.MagicMock()

+         self.options.quiet = False

+         self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

          self.error_format = """Usage: %s disable-channel [options] <channelname> [<channelname> ...]

  (Specify the --help global option for a list of other help options)

  
@@ -33,70 +37,62 @@ 

              m._result = (result,)

          return m

  

-     @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_disable_channel(self, activate_session_mock, stdout, stderr):

+     def test_handle_disable_channel_no_such_channel(self):

          """Test disable-channel function"""

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         mcall = session.multicall.return_value.__enter__.return_value

- 

+         mcall = self.session.multicall.return_value.__enter__.return_value

          mcall.getChannel.return_value = self.__vm(None)

  

          arguments = ['test-channel']

-         with self.assertRaises(SystemExit) as ex:

-             handle_disable_channel(options, session, arguments)

-         self.assertExitCode(ex, 1)

-         activate_session_mock.assert_called_once()

-         session.multicall.assert_called_once()

-         session.disableChannel.assert_not_called()

          expect = ''

          for host in arguments:

              expect += "No such channel: %s\n" % host

          stderr_exp = "No changes made. Please correct the command line.\n"

-         self.assert_console_message(stdout, expect)

-         self.assert_console_message(stderr, stderr_exp)

+         self.assert_system_exit(

+             handle_disable_channel,

+             self.options, self.session, arguments,

+             stdout=expect,

+             stderr=stderr_exp,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once()

+         self.session.multicall.assert_called_once()

+         self.session.disableChannel.assert_not_called()

  

-         # reset session mocks

-         activate_session_mock.reset_mock()

-         session.disableChannel.reset_mock()

-         session.multicall.reset_mock()

-         mcall = session.multicall.return_value.__enter__.return_value

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_disable_channel_valid(self, stdout):

+         """Test disable-channel function"""

+         mcall = self.session.multicall.return_value.__enter__.return_value

  

          mcall.getChannel.return_value = self.__vm(self.channelinfo)

  

          arguments = ['test-channel', '--comment', 'enable channel test']

-         handle_disable_channel(options, session, arguments)

-         activate_session_mock.assert_called_once()

-         self.assertEqual(2, session.multicall.call_count)

+         handle_disable_channel(self.options, self.session, arguments)

+         self.activate_session_mock.assert_called_once()

+         self.assertEqual(2, self.session.multicall.call_count)

          self.assert_console_message(stdout, '')

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_disable_host_no_argument(self, activate_session_mock, stdout):

+     def test_handle_disable_host_no_argument(self):

          """Test disable-channel function without arguments"""

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         session.getChannel.return_value = None

-         session.multicall.return_value = [[None]]

-         session.disableChannel.return_value = True

+         self.session.getChannel.return_value = None

+         self.session.multicall.return_value = [[None]]

+         self.session.disableChannel.return_value = True

  

          expected = self.format_error_message("At least one channel must be specified")

          self.assert_system_exit(

              handle_disable_channel,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

-             activate_session=None)

- 

-         activate_session_mock.assert_not_called()

-         session.getChannel.assert_not_called()

-         session.multicall.assert_not_called()

-         session.disableChannel.assert_not_called()

+             activate_session=None,

+             exit_code=2

+         )

+ 

+         self.activate_session_mock.assert_not_called()

+         self.session.getChannel.assert_not_called()

+         self.session.multicall.assert_not_called()

+         self.session.disableChannel.assert_not_called()

  

      def test_handle_disable_channel_help(self):

          """Test disable-channel help message"""

@@ -10,33 +10,22 @@ 

  

  class TestDisableHost(utils.CliTestCase):

  

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.options = mock.MagicMock()

+         self.options.quiet = False

+         self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

          self.error_format = """Usage: %s disable-host [options] <hostname> [<hostname> ...]

  (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_disable_host(

-             self,

-             activate_session_mock,

-             stdout,

-             stderr):

+     def test_handle_disable_host_no_such_host(self):

          """Test %s function""" % handle_disable_host.__name__

-         arguments = []

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         session.getHost.return_value = None

-         session.disableHost.return_value = True

-         session.editHost.return_value = True

+         self.session.getHost.return_value = None

+         self.session.disableHost.return_value = True

+         self.session.editHost.return_value = True

  

          #

          # session.multiCall returns:
@@ -55,70 +44,66 @@ 

          #     'name': 'kbuilder02' ...}]

          #

  

-         session.multiCall.return_value = [[None], [None]]

- 

+         self.session.multiCall.return_value = [[None], [None]]

          arguments = ['host1', 'host2']

-         with self.assertRaises(SystemExit) as ex:

-             handle_disable_host(options, session, arguments)

-         self.assertExitCode(ex, 1)

-         activate_session_mock.assert_called_once()

-         session.getHost.assert_has_calls([call('host1'), call('host2')])

-         session.multiCall.assert_called_once()

-         session.disableHost.assert_not_called()

-         session.editHost.assert_not_called()

          expect = ''

          for host in arguments:

              expect += "No such host: %s\n" % host

-         self.assert_console_message(stdout, expect)

-         self.assert_console_message(stderr, "No changes made. Please correct the command line.\n")

- 

-         # reset session mocks

-         activate_session_mock.reset_mock()

-         session.multiCall.reset_mock()

-         session.disableHost.reset_mock()

-         session.editHost.reset_mock()

+         stderr_exp = "No changes made. Please correct the command line.\n"

+         self.assert_system_exit(

+             handle_disable_host,

+             self.options, self.session, arguments,

+             stdout=expect,

+             stderr=stderr_exp,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once()

+         self.session.getHost.assert_has_calls([call('host1'), call('host2')])

+         self.session.multiCall.assert_called_once()

+         self.session.disableHost.assert_not_called()

+         self.session.editHost.assert_not_called()

  

-         session.multiCall.return_value = [

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_disable_host_valid(self, stdout):

+         self.session.multiCall.return_value = [

              [{'id': 1, 'name': 'host1'}], [{'id': 2, 'name': 'host2'}]

          ]

  

          arguments = ['host1', 'host2', '--comment', 'disable host test']

-         handle_disable_host(options, session, arguments)

-         activate_session_mock.assert_called_once()

-         session.getHost.assert_has_calls([call('host1'), call('host2')])

-         self.assertEqual(2, session.multiCall.call_count)

-         session.disableHost.assert_has_calls([call('host1'), call('host2')])

-         session.editHost.assert_has_calls(

+         handle_disable_host(self.options, self.session, arguments)

+         self.activate_session_mock.assert_called_once()

+         self.session.getHost.assert_has_calls([call('host1'), call('host2')])

+         self.assertEqual(2, self.session.multiCall.call_count)

+         self.session.disableHost.assert_has_calls([call('host1'), call('host2')])

+         self.session.editHost.assert_has_calls(

              [call('host1', comment='disable host test'),

               call('host2', comment='disable host test')])

          self.assert_console_message(stdout, '')

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_disable_host_no_argument(self, activate_session_mock, stdout):

+     def test_handle_disable_host_no_argument(self):

          """Test %s function without arguments""" % handle_disable_host.__name__

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         session.getHost.return_value = None

-         session.multiCall.return_value = [[None]]

-         session.disableHost.return_value = True

-         session.editHost.return_value = True

+         self.session.getHost.return_value = None

+         self.session.multiCall.return_value = [[None]]

+         self.session.disableHost.return_value = True

+         self.session.editHost.return_value = True

  

          expected = self.format_error_message("At least one host must be specified")

          self.assert_system_exit(

              handle_disable_host,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

-             activate_session=None)

- 

-         activate_session_mock.assert_not_called()

-         session.getHost.assert_not_called()

-         session.multiCall.assert_not_called()

-         session.disableHost.assert_not_called()

-         session.editHost.assert_not_called()

+             activate_session=None,

+             exit_code=2

+         )

+ 

+         self.activate_session_mock.assert_not_called()

+         self.session.getHost.assert_not_called()

+         self.session.multiCall.assert_not_called()

+         self.session.disableHost.assert_not_called()

+         self.session.editHost.assert_not_called()

  

      def test_handle_disable_host_help(self):

          """Test %s help message""" % handle_disable_host.__name__

@@ -13,49 +13,53 @@ 

      maxDiff = None

  

      def setUp(self):

+         self.options = mock.MagicMock()

+         self.options.quiet = False

+         self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.username = 'user'

          self.error_format = """Usage: %s disable-user <username>

  (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_disable_user(

-             self,

-             activate_session_mock,

-             stdout):

+     def test_handle_disable_user_no_argument(self):

          """Test handle_disable_user function"""

-         session = mock.MagicMock()

-         options = mock.MagicMock()

-         username = 'user'

- 

-         # Case 1. no argument error

          expected = self.format_error_message(

              "You must specify the username of the user to disable")

          self.assert_system_exit(

              handle_disable_user,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

-             activate_session=None)

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

  

-         # Case 2. Too many argument error

+     def test_handle_disable_user_many_arguments(self):

+         """Test handle_disable_user function"""

          expected = self.format_error_message(

              "This command only accepts one argument (username)")

          self.assert_system_exit(

              handle_disable_user,

-             options,

-             session,

+             self.options,

+             self.session,

              ['user-1', 'user-2', 'user-3'],

              stderr=expected,

-             activate_session=None)

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

  

-         # Case 3. Disable user test

-         handle_disable_user(options, session, [username])

-         session.disableUser.assert_called_with(username)

-         activate_session_mock.assert_called_with(session, options)

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_disable_user_valid(self, stdout):

+         handle_disable_user(self.options, self.session, [self.username])

+         self.session.disableUser.assert_called_with(self.username)

+         self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.assert_console_message(stdout, '')

  

      def test_handle_disable_user_help(self):

          self.assert_help(

@@ -14,6 +14,11 @@ 

          self.options.debug = False

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.error_format = """Usage: %s download-build [options] <n-v-r | build_id | package>

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

  

          self.build_templ = {

              'package_name': 'bash',
@@ -37,19 +42,46 @@ 

                             'size': 7030,

                             'nvr': 'test-rpm-1.1-11'

                             }

+         self.listbuilds = [{'build_id': 1,

+                             'epoch': 17,

+                             'extra': None,

+                             'name': 'test-build',

+                             'nvr': 'test-build-1-11.f35',

+                             'owner_id': 1,

+                             'owner_name': 'testuser',

+                             'package_id': 4,

+                             'package_name': 'test-build',

+                             'release': '11.f35',

+                             'state': 1,

+                             'task_id': 3,

+                             'version': '1', }]

          self.sigkey = 'testkey'

          self.tag = 'test-tag'

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_download_build_without_option(self, stderr):

-         expected = "Usage: %s download-build [options] <n-v-r | build_id | package>\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Please specify a package N-V-R or build ID\n" \

-                    % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_download_build(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+     def test_download_build_without_argument(self):

+         expected = self.format_error_message("Please specify a package N-V-R or build ID")

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             [],

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+ 

+     def test_download_build_more_arguments(self):

+         expected = self.format_error_message(

+             "Only a single package N-V-R or build ID may be specified")

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             ['1', '2'],

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

  

      def __vm(self, result):

          m = koji.VirtualCall('mcall_method', [], {})
@@ -73,50 +105,86 @@ 

          self.assertEqual(rv, None)

          self.assert_console_message(stderr, expected)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_download_build_without_rpm(self, stderr):

+     def test_download_build_without_rpm(self):

          build_id = '1'

          expected = "No such rpm: %s\n" % build_id

          self.session.getRPM.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_download_build(self.options, self.session, ['--rpm', build_id])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             ['--rpm', build_id],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_download_build_no_build(self, stderr):

+     def test_download_build_no_build(self):

          build_id = '1'

          expected = "No such build: %s\n" % build_id

          self.session.getRPM.return_value = self.getrpminfo

          self.session.getBuild.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_download_build(self.options, self.session, [build_id])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             [build_id],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_download_build_latest_from_no_build(self, stderr):

+     def test_download_build_latest_from_no_build(self):

          nvr = self.build_templ['nvr']

          expected = "%s has no builds of %s\n" % (self.tag, nvr)

          self.session.getRPM.return_value = self.getrpminfo

          self.session.listTagged.return_value = []

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_download_build(self.options, self.session, [nvr, '--latestfrom', self.tag])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             [nvr, '--latestfrom', self.tag],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

  

+     def test_download_build_latest_from_build_id(self):

+         build_id = '1'

+         expected = self.format_error_message(

+             "--latestfrom not compatible with build IDs, specify a package name.")

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             [build_id, '--latestfrom', self.tag],

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

      @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_download_build_latest_from_build_id(self, stderr):

+     def test_download_task_id(self, stderr, stdout):

          build_id = '1'

-         expected = "Usage: %s download-build [options] <n-v-r | build_id | package>\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: --latestfrom not compatible with build IDs, " \

-                    "specify a package name.\n" % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_download_build(self.options, self.session, [build_id, '--latestfrom',

-                                                                     self.tag])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.session.listBuilds.return_value = self.listbuilds

+         anon_handle_download_build(self.options, self.session, ['--task-id', build_id])

+         self.assert_console_message(stdout, "")

+         self.assert_console_message(stderr, "")

+ 

+     def test_download_no_asociated_build_task(self):

+         build_id = '1'

+         self.session.listBuilds.return_value = []

+         self.assert_system_exit(

+             anon_handle_download_build,

+             self.options,

+             self.session,

+             ['--task-id', build_id],

+             stderr='No associated builds for task %s\n' % build_id,

+             stdout='',

+             activate_session=None,

+             exit_code=1

+         )

  

      def test_handle_add_volume_help(self):

          self.assert_help(

@@ -4,7 +4,6 @@ 

  import unittest

  

  import mock

- import six

  

  import koji

  from koji_cli.commands import handle_edit_channel
@@ -25,6 +24,12 @@ 

              'description': self.description,

          }

          self.maxDiff = None

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.error_format = """Usage: %s edit-channel [options] <old-name>

+ (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()
@@ -43,82 +48,90 @@ 

    --comment=COMMENT     Comment of channel

  """ % self.progname)

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_channel_without_args(self, activate_session_mock, stderr):

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_channel(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         actual = stderr.getvalue()

-         expected_stderr = """Usage: %s edit-channel [options] <old-name>

- (Specify the --help global option for a list of other help options)

- 

- %s: error: Incorrect number of arguments

- """ % (self.progname, self.progname)

-         self.assertMultiLineEqual(actual, expected_stderr)

-         activate_session_mock.assert_not_called()

+     def test_handle_edit_channel_without_args(self):

+         expected = self.format_error_message("Incorrect number of arguments")

+         self.assert_system_exit(

+             handle_edit_channel,

+             self.options,

+             self.session,

+             [],

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getChannel.assert_not_called()

+         self.session.editChannel.assert_not_called()

+         self.session.getKojiVersion.assert_not_called()

  

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_channel(self, activate_session_mock):

+     def test_handle_edit_channel(self):

          handle_edit_channel(self.options, self.session,

                              [self.channel_old, '--name', self.channel_new,

                               '--description', self.description])

-         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.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new,

                                                           description=self.description)

+         self.session.getChannel.assert_called_once_with(self.channel_old)

+         self.session.getKojiVersion.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_channel_older_hub(self, activate_session_mock, stderr):

+     def test_handle_edit_channel_older_hub(self):

          expected_api = 'Invalid method: editChannel'

          expected = 'editChannel 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.editChannel.side_effect = koji.GenericError(expected_api)

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_channel(self.options, self.session,

-                                 [self.channel_old, '--name', self.channel_new,

-                                  '--description', self.description])

-         self.assertExitCode(ex, 1)

-         actual = stderr.getvalue()

-         self.assertMultiLineEqual(actual, expected)

-         activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.assert_system_exit(

+             handle_edit_channel,

+             self.options,

+             self.session,

+             [self.channel_old, '--name', self.channel_new, '--description', self.description],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

          self.session.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new,

                                                           description=self.description)

+         self.session.getChannel.assert_called_once_with(self.channel_old)

+         self.session.getKojiVersion.assert_called_once_with()

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_channel_non_exist_channel(self, activate_session_mock, stderr):

+     def test_handle_edit_channel_non_exist_channel(self):

          expected = 'No such channel: %s\n' % self.channel_old

          channel_info = None

          self.session.getChannel.return_value = channel_info

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_channel(self.options, self.session,

-                                 [self.channel_old, '--name', self.channel_new,

-                                  '--description', self.description])

-         self.assertExitCode(ex, 1)

-         actual = stderr.getvalue()

-         self.assertMultiLineEqual(actual, expected)

-         activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.assert_system_exit(

+             handle_edit_channel,

+             self.options,

+             self.session,

+             [self.channel_old, '--name', self.channel_new, '--description', self.description],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

          self.session.editChannel.assert_not_called()

+         self.session.getChannel.assert_called_once_with(self.channel_old)

+         self.session.getKojiVersion.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_channel_non_result(self, activate_session_mock, stderr):

+     def test_handle_edit_channel_non_result(self):

          expected = 'No changes made, please correct the command line\n'

          self.session.getChannel.return_value = self.channel_info

          self.session.editChannel.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_channel(self.options, self.session,

-                                 [self.channel_old, '--name', self.channel_new,

-                                  '--description', self.description])

-         self.assertExitCode(ex, 1)

-         actual = stderr.getvalue()

-         self.assertMultiLineEqual(actual, expected)

-         activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.assert_system_exit(

+             handle_edit_channel,

+             self.options,

+             self.session,

+             [self.channel_old, '--name', self.channel_new, '--description', self.description],

+             stderr=expected,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

          self.session.editChannel.assert_called_once_with(self.channel_old, name=self.channel_new,

                                                           description=self.description)

+         self.session.getChannel.assert_called_once_with(self.channel_old)

+         self.session.getKojiVersion.assert_not_called()

  

  

  if __name__ == '__main__':

@@ -17,20 +17,14 @@ 

      def setUp(self):

          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 edit-external-repo [options] <name>

  (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('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_external_repo_error(

-             self,

-             activate_session_mock,

-             stderr,

-             stdout):

+     def test_handle_edit_external_repo_error(self):

          """Test handle_edit_external_repo function"""

          # [(expected, args),...]

          items = [
@@ -54,6 +48,13 @@ 

                  stderr=self.format_error_message(expected),

                  activate_session=None)

  

+         self.activate_session_mock.assert_not_called()

+         self.session.editExternalRepo.assert_not_called()

+         self.session.editTagExternalRepo.assert_not_called()

+ 

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     @mock.patch('sys.stderr', new_callable=six.StringIO)

+     def test_handle_edit_external_repo_ext_repo_only(self, stderr, stdout):

          # edit ext-repo only

          handle_edit_external_repo(self.options, self.session,

                                    ['ext_repo', '--name', 'newname', '--url', 'https://newurl'])
@@ -62,9 +63,12 @@ 

          self.session.editExternalRepo.assert_called_once_with('ext_repo',

                                                                name='newname', url='https://newurl')

          self.session.editTagExternalRepo.assert_not_called()

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

  

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     @mock.patch('sys.stderr', new_callable=six.StringIO)

+     def test_handle_edit_external_repo_tag_repo_only(self, stderr, stdout):

          # edit tag-repo only

-         self.session.reset_mock()

          handle_edit_external_repo(self.options, self.session,

                                    ['ext_repo', '-t', 'tag', '-p', '0', '-m', 'koji', '-a', 'i386'])

          self.assert_console_message(stdout, "")
@@ -75,6 +79,7 @@ 

                                                                   priority=0,

                                                                   merge_mode='koji',

                                                                   arches='i386')

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

  

      def test_handle_edit_external_repo_help(self):

          self.assert_help(

file modified
+110 -142
@@ -1,134 +1,121 @@ 

  from __future__ import absolute_import

  import mock

- import os

  import six

- import sys

  import unittest

+ import koji

  

  from mock import call

  

  from koji_cli.commands import handle_edit_host

  from . import utils

  

+ 

  class TestEditHost(utils.CliTestCase):

+     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 edit-host <hostname> [<hostname> ...] [options]

+ (Specify the --help global option for a list of other help options)

  

-     # Show long diffs in error output...

-     maxDiff = None

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.host = 'host'

+         self.arches = 'arch1 arch2'

+         self.capacity = 0.22

+         self.description = 'description'

+         self.comment = 'comment'

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_host(self, activate_session_mock, stdout):

-         host = 'host'

+     def test_handle_edit_host(self, stdout):

          host_info = mock.ANY

-         arches = 'arch1 arch2'

-         capacity = 0.22

-         description = 'description'

-         comment = 'comment'

-         args = [host]

-         args.append('--arches=' + arches)

-         args.append('--capacity=' + str(capacity))

-         args.append('--description=' + description)

-         args.append('--comment=' + comment)

-         kwargs = {'arches': arches,

-                   'capacity': capacity,

-                   'description': description,

-                   'comment': comment}

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

-         session.multiCall.side_effect = [[[host_info]], [[True]]]

+         args = [self.host]

+         args.append('--arches=' + self.arches)

+         args.append('--capacity=' + str(self.capacity))

+         args.append('--description=' + self.description)

+         args.append('--comment=' + self.comment)

+         kwargs = {'arches': self.arches,

+                   'capacity': self.capacity,

+                   'description': self.description,

+                   'comment': self.comment}

+ 

+         self.session.multiCall.side_effect = [[[host_info]], [[True]]]

          # Run it and check immediate output

          # args: host, --arches='arch1 arch2', --capacity=0.22,

          # --description=description, --comment=comment

          # expected: success

-         rv = handle_edit_host(options, session, args)

+         rv = handle_edit_host(self.options, self.session, args)

          actual = stdout.getvalue()

          expected = 'Edited host\n'

          self.assertMultiLineEqual(actual, expected)

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_called_once_with(session, options)

-         session.getHost.assert_called_once_with(host)

-         session.editHost.assert_called_once_with(host, **kwargs)

-         self.assertEqual(session.multiCall.call_count, 2)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getHost.assert_called_once_with(self.host)

+         self.session.editHost.assert_called_once_with(self.host, **kwargs)

+         self.assertEqual(self.session.multiCall.call_count, 2)

          self.assertNotEqual(rv, 1)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_host_failed(self, activate_session_mock, stdout):

-         host = 'host'

+     def test_handle_edit_host_failed(self, stdout):

          host_info = mock.ANY

-         arches = 'arch1 arch2'

-         capacity = 0.22

-         description = 'description'

-         comment = 'comment'

-         args = [host]

-         args.append('--arches=' + arches)

-         args.append('--capacity=' + str(capacity))

-         args.append('--description=' + description)

-         args.append('--comment=' + comment)

-         kwargs = {'arches': arches,

-                   'capacity': capacity,

-                   'description': description,

-                   'comment': comment}

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

-         session.multiCall.side_effect = [[[host_info]], [[False]]]

+         args = [self.host]

+         args.append('--arches=' + self.arches)

+         args.append('--capacity=' + str(self.capacity))

+         args.append('--description=' + self.description)

+         args.append('--comment=' + self.comment)

+         kwargs = {'arches': self.arches,

+                   'capacity': self.capacity,

+                   'description': self.description,

+                   'comment': self.comment}

+ 

+         self.session.multiCall.side_effect = [[[host_info]], [[False]]]

          # Run it and check immediate output

          # args: host, --arches='arch1 arch2', --capacity=0.22,

          # --description=description, --comment=comment

          # expected: failed - session.editHost == False

-         rv = handle_edit_host(options, session, args)

+         rv = handle_edit_host(self.options, self.session, args)

          actual = stdout.getvalue()

          expected = 'No changes made to host\n'

          self.assertMultiLineEqual(actual, expected)

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_called_once_with(session, options)

-         session.getHost.assert_called_once_with(host)

-         session.editHost.assert_called_once_with(host, **kwargs)

-         self.assertEqual(session.multiCall.call_count, 2)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getHost.assert_called_once_with(self.host)

+         self.session.editHost.assert_called_once_with(self.host, **kwargs)

+         self.assertEqual(self.session.multiCall.call_count, 2)

          self.assertNotEqual(rv, 1)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_multi_host(self, activate_session_mock, stdout):

+     def test_handle_edit_multi_host(self, stdout):

          hosts = ['host1', 'host2']

          host_infos = [mock.ANY, mock.ANY]

-         arches = 'arch1 arch2'

-         capacity = 0.22

-         description = 'description'

-         comment = 'comment'

          args = hosts

-         args.append('--arches=' + arches)

-         args.append('--capacity=' + str(capacity))

-         args.append('--description=' + description)

-         args.append('--comment=' + comment)

-         kwargs = {'arches': arches,

-                   'capacity': capacity,

-                   'description': description,

-                   'comment': comment}

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

-         session.multiCall.side_effect = [[[info]

-                                           for info in host_infos], [[True], [True]]]

+         args.append('--arches=' + self.arches)

+         args.append('--capacity=' + str(self.capacity))

+         args.append('--description=' + self.description)

+         args.append('--comment=' + self.comment)

+         kwargs = {'arches': self.arches,

+                   'capacity': self.capacity,

+                   'description': self.description,

+                   'comment': self.comment}

+ 

+         self.session.multiCall.side_effect = [[[info]

+                                                for info in host_infos], [[True], [True]]]

          # Run it and check immediate output

          # args: host1, host2, --arches='arch1 arch2', --capacity=0.22,

          # --description=description, --comment=comment

          # expected: success

-         rv = handle_edit_host(options, session, args)

+         rv = handle_edit_host(self.options, self.session, args)

          actual = stdout.getvalue()

          expected = 'Edited host1\nEdited host2\n'

          self.assertMultiLineEqual(actual, expected)

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_called_once_with(session, options)

-         self.assertEqual(session.mock_calls,

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getHost.assert_has_calls([call(hosts[0]), call(hosts[1])])

+         self.session.editHost.assert_has_calls(

+             [call(hosts[0], **kwargs), call(hosts[1], **kwargs)])

+         self.assertEqual(self.session.mock_calls,

                           [call.getHost(hosts[0]),

                            call.getHost(hosts[1]),

                               call.multiCall(strict=True),
@@ -139,79 +126,60 @@ 

                               call.multiCall(strict=True)])

          self.assertNotEqual(rv, 1)

  

-     @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_edit_host_no_arg(

-             self, activate_session_mock, stderr, stdout):

-         args = []

-         options = mock.MagicMock()

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

-         progname = os.path.basename(sys.argv[0]) or 'koji'

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

+     def test_handle_edit_host_no_arg(self):

          # Run it and check immediate output

          # args: _empty_

          # expected: failed - should specify host

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_host(options, session, args)

-         self.assertExitCode(ex, 2)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = ''

-         expected_stderr = """Usage: %s edit-host <hostname> [<hostname> ...] [options]

- (Specify the --help global option for a list of other help options)

- 

- %s: error: Please specify a hostname

- """ % (progname, progname)

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+         expected = self.format_error_message("Please specify a hostname")

+         self.assert_system_exit(

+             handle_edit_host,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

  

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.getHost.assert_not_called()

-         session.editHost.assert_not_called()

-         session.multiCall.assert_not_called()

- 

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_host_no_host(self, activate_session_mock, stderr):

-         host = 'host'

+         self.activate_session_mock.assert_not_called()

+         self.session.getHost.assert_not_called()

+         self.session.editHost.assert_not_called()

+         self.session.multiCall.assert_not_called()

+ 

+     def test_handle_edit_host_no_host(self):

          host_info = None

-         arches = 'arch1 arch2'

-         capacity = 0.22

-         description = 'description'

-         comment = 'comment'

-         args = [host]

-         args.append('--arches=' + arches)

-         args.append('--capacity=' + str(capacity))

-         args.append('--description=' + description)

-         args.append('--comment=' + comment)

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

-         session.multiCall.return_value = [[host_info]]

+         args = [self.host]

+         args.append('--arches=' + self.arches)

+         args.append('--capacity=' + str(self.capacity))

+         args.append('--description=' + self.description)

+         args.append('--comment=' + self.comment)

+ 

+         self.session.multiCall.return_value = [[host_info]]

          # Run it and check immediate output

          # args: host, --arches='arch1 arch2', --capacity=0.22,

          # --description=description, --comment=comment

          # expected: failed -- getHost() == None

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_host(options, session, args)

-         self.assertExitCode(ex, 1)

-         actual = stderr.getvalue()

          expected = """No such host: %s

  No changes made, please correct the command line

- """ % host

-         self.assertMultiLineEqual(actual, expected)

+ """ % self.host

+         self.assert_system_exit(

+             handle_edit_host,

+             self.options,

+             self.session,

+             args,

+             stdout='',

+             stderr=expected,

+             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.getHost.assert_called_once_with(host)

-         session.editHost.assert_not_called()

-         self.assertEqual(session.multiCall.call_count, 1)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getHost.assert_called_once_with(self.host)

+         self.session.editHost.assert_not_called()

+         self.assertEqual(self.session.multiCall.call_count, 1)

+ 

  

  if __name__ == '__main__':

      unittest.main()

@@ -1,8 +1,6 @@ 

  from __future__ import absolute_import

  import koji

  import mock

- import unittest

- from six.moves import StringIO

  

  from koji_cli.commands import handle_edit_notification

  from . import utils
@@ -14,108 +12,150 @@ 

          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 edit-notification [options] <notification_id>

+ (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_edit_notification(self, activate_session_mock):

+     def test_handle_edit_notification(self):

          self.session.getPackageID.return_value = 1234

          self.session.getTagID.return_value = 4321

          self.session.getBuildNotification.return_value = {'id': 2345}

  

          handle_edit_notification(self.options, self.session,

-             ['--package', 'pkg_a', '--tag', 'tag_a', '--success-only', '2345'])

+                                  ['--package', 'pkg_a', '--tag', 'tag_a',

+                                   '--success-only', '2345'])

  

+         self.session.getBuildNotification.assert_called_once_with(2345)

          self.session.getPackageID.assert_called_once_with('pkg_a')

          self.session.getTagID.assert_called_once_with('tag_a', strict=True)

          self.session.updateNotification.assert_called_once_with(2345, 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_edit_notification_no_pkg(self, activate_session_mock):

+     def test_handle_edit_notification_no_pkg(self):

          self.session.getBuildNotification.return_value = \

              {'id': 2345, 'package_id': 135, 'success_only': False}

  

-         handle_edit_notification(self.options, self.session,

-             ['--tag', '*', '2345'])

+         handle_edit_notification(self.options, self.session, ['--tag', '*', '2345'])

  

          self.session.getPackageID.assert_not_called()

          self.session.getTagID.assert_not_called()

          self.session.updateNotification.assert_called_once_with(2345, 135, None, False)

          self.session.getBuildNotification.assert_called_once_with(2345)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

  

- 

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_notification_no_tag(self, activate_session_mock):

+     def test_handle_edit_notification_no_tag(self):

          self.session.getBuildNotification.return_value = \

              {'id': 2345, 'tag_id': 135, 'success_only': True}

  

          handle_edit_notification(self.options, self.session,

-             ['--package', '*', '--no-success-only', '2345'])

+                                  ['--package', '*', '--no-success-only', '2345'])

  

          self.session.getPackageID.assert_not_called()

          self.session.getTagID.assert_not_called()

          self.session.updateNotification.assert_called_once_with(2345, None, 135, False)

          self.session.getBuildNotification.assert_called_once_with(2345)

- 

- 

-     @mock.patch('sys.exit')

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_edit_notification_bogus(self, sys_stderr, sys_exit):

-         sys_exit.side_effect = SystemExit()

- 

-         with self.assertRaises(SystemExit):

-             handle_edit_notification(self.options, self.session, ['bogus'])

- 

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+ 

+     def test_handle_edit_notification_bogus(self):

+         expected = self.format_error_message("Notification ID has to be numeric")

+         self.assert_system_exit(

+             handle_edit_notification,

+             self.options,

+             self.session,

+             ['bogus'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

          self.session.updateNotification.assert_not_called()

- 

- 

-     @mock.patch('sys.exit')

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_edit_notification_no_id(self, sys_stderr, sys_exit):

-         sys_exit.side_effect = SystemExit()

- 

-         with self.assertRaises(SystemExit):

-             handle_edit_notification(self.options, self.session, [])

+         self.session.getPackageID.assert_not_called()

+         self.session.getTagID.assert_not_called()

+         self.session.getBuildNotification.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+ 

+     def test_handle_edit_notification_no_id(self):

+         expected = self.format_error_message("Only argument is notification ID")

+         self.assert_system_exit(

+             handle_edit_notification,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

  

          self.session.updateNotification.assert_not_called()

- 

- 

-     @mock.patch('sys.exit')

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_edit_notification_no_opts(self, sys_stderr, sys_exit):

-         sys_exit.side_effect = SystemExit()

- 

-         with self.assertRaises(SystemExit):

-             handle_edit_notification(self.options, self.session, ['123'])

+         self.session.getPackageID.assert_not_called()

+         self.session.getTagID.assert_not_called()

+         self.session.getBuildNotification.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+ 

+     def test_handle_edit_notification_no_opts(self):

+         expected = self.format_error_message("Command need at least one option")

+         self.assert_system_exit(

+             handle_edit_notification,

+             self.options,

+             self.session,

+             ['123'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

  

          self.session.updateNotification.assert_not_called()

+         self.session.getPackageID.assert_not_called()

+         self.session.getTagID.assert_not_called()

+         self.session.getBuildNotification.assert_not_called()

+         self.activate_session_mock.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_edit_notification_non_exist_tag(self, stderr):

+     def test_handle_edit_notification_non_exist_tag(self):

          tag = 'test-tag'

-         expected = "Usage: %s edit-notification [options] <notification_id>\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)

+         expected = self.format_error_message("No such tag: %s" % tag)

  

          self.session.getBuildNotification.return_value = \

              {'id': 2345, 'package_id': 135, 'success_only': False}

          self.session.getTagID.side_effect = koji.GenericError

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_notification(self.options, self.session, ['--tag', tag, '2345'])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_edit_notification,

+             self.options,

+             self.session,

+             ['--tag', tag, '2345'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getPackageID.assert_not_called()

+         self.session.getTagID.assert_called_once_with(tag, strict=True)

+         self.session.getBuildNotification.assert_called_once_with(2345)

+         self.session.updateNotification.assert_not_called()

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_edit_notification_non_exist_pkg(self, stderr):

+     def test_handle_edit_notification_non_exist_pkg(self):

          pkg = 'test-pkg'

-         expected = "Usage: %s edit-notification [options] <notification_id>\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)

+         expected = self.format_error_message("No such package: %s" % pkg)

          self.session.getBuildNotification.return_value = \

              {'id': 2345, 'package_id': 135, 'success_only': False}

          self.session.getPackageID.return_value = None

- 

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_notification(self.options, self.session, ['--package', pkg, '2345'])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_edit_notification,

+             self.options,

+             self.session,

+             ['--package', pkg, '2345'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getPackageID.assert_called_once_with(pkg)

+         self.session.getTagID.assert_not_called()

+         self.session.getBuildNotification.assert_called_once_with(2345)

+         self.session.updateNotification.assert_not_called()

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

@@ -1,6 +1,7 @@ 

  from __future__ import absolute_import

  import mock

  import koji

+ import six

  

  from koji_cli.commands import handle_edit_permission

  from . import utils
@@ -26,8 +27,7 @@ 

          self.description = 'test-description'

  

      def test_handle_edit_permission_argument_error(self):

-         expected = self.format_error_message(

-             "Please specify a permission and a description")

+         expected = self.format_error_message("Please specify a permission and a description")

          for args in [[], [self.perm]]:

              self.assert_system_exit(

                  handle_edit_permission,
@@ -37,9 +37,13 @@ 

                  stderr=expected,

                  activate_session=None)

          self.activate_session_mock.assert_not_called()

-         self.session.grantPermission.assert_not_called()

+         self.session.editPermission.assert_not_called()

  

-     def test_handle_edit_permission_with_new_and_description(self):

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_edit_permission_with_new_and_description(self, stdout):

          handle_edit_permission(self.options, self.session, [self.perm, self.description])

+         actual = stdout.getvalue()

+         expected = ''

+         self.assertMultiLineEqual(actual, expected)

          self.session.editPermission.assert_called_once_with(self.perm, self.description)

          self.activate_session_mock.assert_called_once_with(self.session, self.options)

file modified
+97 -95
@@ -1,118 +1,106 @@ 

  from __future__ import absolute_import

  import mock

- import os

  import six

- import sys

+ import koji

  

  from koji_cli.commands import handle_edit_tag

  from . import utils

  

- progname = os.path.basename(sys.argv[0]) or 'koji'

- 

  

  class TestEditTag(utils.CliTestCase):

-     # Show long diffs in error output...

-     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 edit-tag [options] <name>

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.tag = 'tag'

+         self.arches = 'arch1 arch2'

+         self.perm = 'perm'

+         self.locked = True

+         self.rename = 'tag2'

+         self.maven_support = True

+         self.maven_include_all = True

+         self.extra = {'extraA': 'A', 'extraB': True}

+         self.remove_extra = ['extraC', 'extraD']

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_tag(self, activate_session_mock, stdout):

-         tag = 'tag'

-         arches = 'arch1 arch2'

-         perm = 'perm'

-         locked = True

-         rename = 'tag2'

-         maven_support = True

-         maven_include_all = True

-         extra = {'extraA': 'A', 'extraB': True}

-         remove_extra = ['extraC', 'extraD']

-         args = [tag]

-         args.append('--arches=' + arches)

-         args.append('--perm=' + perm)

+     def test_handle_edit_tag_1(self, stdout):

+         args = [self.tag]

+         args.append('--arches=' + self.arches)

+         args.append('--perm=' + self.perm)

          args.append('--lock')

-         args.append('--rename=' + rename)

+         args.append('--rename=' + self.rename)

          args.append('--maven-support')

          args.append('--include-all')

-         for k, x in six.iteritems(extra):

+         for k, x in six.iteritems(self.extra):

              args.append('-x')

              args.append(k + '=' + str(x))

-         for r in remove_extra:

+         for r in self.remove_extra:

              args.append('-r')

              args.append(r)

-         opts = {'arches': arches,

-                 'perm': perm,

-                 'locked': locked,

-                 'name': rename,

-                 'maven_support': maven_support,

-                 'maven_include_all': maven_include_all,

-                 'extra': extra,

+         opts = {'arches': self.arches,

+                 'perm': self.perm,

+                 'locked': self.locked,

+                 'name': self.rename,

+                 'maven_support': self.maven_support,

+                 'maven_include_all': self.maven_include_all,

+                 'extra': self.extra,

                  'block_extra': [],

-                 'remove_extra': remove_extra}

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

+                 'remove_extra': self.remove_extra}

  

          # Run it and check immediate output

          # args: tag --arches='arch1 arch2' --perm --lock

          # --rename=tag2 --maven-support --include-all

          # -x extraA=A -x extraB=True -r extraC -r extraD

          # expected: success

-         rv = handle_edit_tag(options, session, args)

+         rv = handle_edit_tag(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.editTag2.assert_called_once_with(tag, **opts)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.editTag2.assert_called_once_with(self.tag, **opts)

          self.assertEqual(rv, None)

  

-         stdout.seek(0)

-         stdout.truncate()

-         session.reset_mock()

-         activate_session_mock.reset_mock()

-         args = [tag]

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_edit_tag_2(self, stdout):

+         args = [self.tag]

          args.append('--no-perm')

          args.append('--unlock')

          args.append('--no-maven-support')

          args.append('--no-include-all')

          opts = {'perm': None,

-                 'locked': not locked,

-                 'maven_support': not maven_support,

+                 'locked': not self.locked,

+                 'maven_support': not self.maven_support,

                  'block_extra': [],

                  'remove_extra': [],

-                 'maven_include_all': not maven_include_all}

+                 'maven_include_all': not self.maven_include_all}

          # Run it and check immediate output

          # args: tag --no-perm --unlock --no-maven-support --no-include-all

          # expected: success

-         rv = handle_edit_tag(options, session, args)

+         rv = handle_edit_tag(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.editTag2.assert_called_once_with(tag, **opts)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.editTag2.assert_called_once_with(self.tag, **opts)

          self.assertEqual(rv, None)

  

-     @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_edit_tag_help(self, activate_session_mock, stderr, stdout):

-         args = ['--help']

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

+     def test_handle_edit_tag_help(self):

          # Run it and check immediate output

          # args: --help

          # expected: failed, help info shows

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_tag(options, session, args)

-         self.assertExitCode(ex, 0)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = """Usage: %s edit-tag [options] <name>

+         self.assert_help(

+             handle_edit_tag,

+             """Usage: %s edit-tag [options] <name>

  (Specify the --help global option for a list of other help options)

  

  Options:
@@ -135,40 +123,54 @@ 

                          Remove tag extra option

    -b key, --block-extra=key

                          Block inherited tag extra option

- """ % progname

-         expected_stderr = ''

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

-         # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.editTag2.assert_not_called()

+ """ % self.progname)

  

-     @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_edit_tag_no_arg(self, activate_session_mock, stderr, stdout):

-         args = []

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

+         # Finally, assert that things were called as we expected.

+         self.activate_session_mock.assert_not_called()

+         self.session.editTag2.assert_not_called()

  

+     def test_handle_edit_tag_no_arg(self):

          # Run it and check immediate output

          # args: --help

          # expected: failed, help info shows

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_tag(options, session, args)

-         self.assertExitCode(ex, 2)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = ''

-         expected_stderr = """Usage: %(progname)s edit-tag [options] <name>

- (Specify the --help global option for a list of other help options)

+         expected = self.format_error_message("Please specify a name for the tag")

+         self.assert_system_exit(

+             handle_edit_tag,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         # Finally, assert that things were called as we expected.

+         self.activate_session_mock.assert_not_called()

+         self.session.editTag2.assert_not_called()

  

- %(progname)s: error: Please specify a name for the tag

- """ % {'progname': progname}

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+     def test_handle_edit_tag_duplicate_extra(self):

+         args = [self.tag]

+         for k, x in six.iteritems(self.extra):

+             args.append('-x')

+             args.append(k + '=' + str(x))

+         # duplicate item in dict extra

+         args.append('-x')

+         args.append('extraA=duplicateA')

+ 

+         # Run it and check immediate output

+         # args: tag -x extraA=A -x extraB=True -x extraA=duplicateA

+         # expected: failed

+         expected = self.format_error_message("Duplicate extra key: extraA")

+         self.assert_system_exit(

+             handle_edit_tag,

+             self.options,

+             self.session,

+             args,

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.editTag2.assert_not_called()

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.editTag2.assert_not_called()

@@ -1,7 +1,7 @@ 

  from __future__ import absolute_import

  

  import mock

- from six.moves import StringIO

+ from mock import call

  

  import koji

  from koji_cli.commands import handle_edit_tag_inheritance
@@ -14,36 +14,25 @@ 

          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 edit-tag-inheritance [options] <tag> <parent> <priority>

+ (Specify the --help global option for a list of other help options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_tag_inheritance_without_option(self, stderr):

-         expected = "Usage: %s edit-tag-inheritance [options] <tag> <parent> <priority>\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: This command takes at least one argument: " \

-                    "a tag name or ID\n" % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_tag_inheritance(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_tag_inheritance_non_exist_tag(self, stderr):

-         tag = 'test-tag'

-         parent_tag = 'parent-test-tag'

-         priority = '99'

-         expected = "Usage: %s edit-tag-inheritance [options] <tag> <parent> <priority>\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)

-         self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_tag_inheritance(self.options, self.session,

-                                         [tag, parent_tag, priority])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_tag_inheritance_non_exist_parent_tag(self, stderr):

-         side_effect_result = [{'arches': 'x86_64',

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.tag = 'test-tag'

+         self.parent_tag = 'parent-test-tag'

+         self.priority = '99'

+         self.new_priority = '15'

+         self.tag_inheritance = {'child_id': 1,

+                                 'intransitive': False,

+                                 'maxdepth': None,

+                                 'name': self.tag,

+                                 'noconfig': False,

+                                 'parent_id': 2,

+                                 'pkg_filter': '',

+                                 'priority': self.priority}

+         self.child_tag_info = {'arches': 'x86_64',

                                 'extra': {},

                                 'id': 1,

                                 'locked': False,
@@ -51,17 +40,230 @@ 

                                 'maven_support': False,

                                 'name': 'test-tag',

                                 'perm': None,

-                                'perm_id': None},

-                               None]

-         tag = 'test-tag'

-         parent_tag = 'parent-test-tag'

-         priority = '99'

-         expected = "Usage: %s edit-tag-inheritance [options] <tag> <parent> <priority>\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)

-         self.session.getTag.side_effect = side_effect_result

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_tag_inheritance(self.options, self.session,

-                                         [tag, parent_tag, priority])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+                                'perm_id': None}

+         self.parent_tag_info = {'arches': 'x86_64',

+                                 'extra': {},

+                                 'id': 2,

+                                 'locked': False,

+                                 'maven_include_all': False,

+                                 'maven_support': False,

+                                 'name': 'parent-test-tag',

+                                 'perm': None,

+                                 'perm_id': None}

+ 

+     def test_edit_tag_inheritance_without_option(self):

+         expected = self.format_error_message(

+             "This command takes at least one argument: a tag name or ID")

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_non_exist_tag(self):

+         self.session.getTag.return_value = None

+         expected = self.format_error_message("No such tag: %s" % self.tag)

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_non_exist_parent_tag(self):

+         self.session.getTag.side_effect = [self.child_tag_info, None]

+         expected = self.format_error_message("No such tag: %s" % self.parent_tag)

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_more_arguments(self):

+         expected = self.format_error_message(

+             "This command takes at most three argument: a tag name or ID, "

+             "a parent tag name or ID, and a priority")

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             ['arg1', 'arg2', 'arg3', 'arg4'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_non_exist_inheritance(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = []

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr='No inheritance link found to remove.  Please check your arguments\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_multi_inheritance_without_parent(self):

+         self.session.getTag.return_value = self.child_tag_info

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag],

+             stdout='Multiple matches for tag.\n',

+             stderr='Please specify a parent on the command line.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_multi_inheritance_without_priority(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag],

+             stdout='Multiple matches for tag.\n',

+             stderr='Please specify a priority on the command line.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_multi_inheritance(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='Multiple matches for tag.\n',

+             stderr='Error: Key constraints may be broken.  Exiting.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_already_active_inheritance(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.side_effect = [[self.tag_inheritance],

+                                                        [self.tag_inheritance]]

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority, '--priority', self.priority],

+             stdout='',

+             stderr='Error: There is already an active inheritance with that priority on %s, '

+                    'please specify a different priority with --priority.\n' % self.tag,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_has_calls([call(1), call(1)])

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_edit_tag_inheritance_valid_maxdepth_digit(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.side_effect = [[self.tag_inheritance],

+                                                        [self.tag_inheritance]]

+         handle_edit_tag_inheritance(self.options, self.session,

+                                     ['--priority', self.new_priority, '--maxdepth', '123',

+                                      '--intransitive', '--noconfig', '--pkg-filter',

+                                      self.tag, self.parent_tag])

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.parent_tag)

+         self.session.getInheritanceData.assert_has_calls([call(1), call(1)])

+         self.session.setInheritanceData.assert_called_once_with(

+             1, [{'child_id': 1, 'intransitive': True, 'maxdepth': 123, 'name': self.tag,

+                  'noconfig': True, 'parent_id': 2, 'pkg_filter': self.tag,

+                  'priority': int(self.new_priority)}])

+ 

+     def test_edit_tag_inheritance_valid_maxdepth_none(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.side_effect = [[self.tag_inheritance],

+                                                        [self.tag_inheritance]]

+         handle_edit_tag_inheritance(self.options, self.session,

+                                     ['--priority', self.new_priority, '--maxdepth', "None",

+                                      '--intransitive', '--noconfig', '--pkg-filter',

+                                      self.tag, self.parent_tag])

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.parent_tag)

+         self.session.getInheritanceData.assert_has_calls([call(1), call(1)])

+         self.session.setInheritanceData.assert_called_once_with(

+             1, [{'child_id': 1, 'intransitive': True, 'maxdepth': None, 'name': self.tag,

+                  'noconfig': True, 'parent_id': 2, 'pkg_filter': self.tag,

+                  'priority': int(self.new_priority)}])

+ 

+     def test_edit_tag_inheritance_valid_maxdepth_invalid(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.side_effect = [[self.tag_inheritance],

+                                                        [self.tag_inheritance]]

+         self.assert_system_exit(

+             handle_edit_tag_inheritance,

+             self.options,

+             self.session,

+             ['--priority', self.new_priority, '--maxdepth', 'wrong-maxdepth', '--intransitive',

+              '--noconfig', '--pkg-filter', self.tag, self.parent_tag],

+             stdout='',

+             stderr='Invalid maxdepth: wrong-maxdepth\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.parent_tag)

+         self.session.getInheritanceData.assert_has_calls([call(1), call(1)])

+         self.session.setInheritanceData.assert_not_called()

@@ -16,6 +16,12 @@ 

          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 edit-target [options] <name>

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

          self.build_target_info = {'build_tag': 444,

                                    'build_tag_name': 'test-tag',

                                    'dest_tag': 445,
@@ -30,132 +36,157 @@ 

                                 'extra': {},

                                 'id': 1,

                                 'name': 'new-build-tag'}

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_target_without_option(self, stderr):

-         expected = "Usage: %s edit-target [options] <name>\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Please specify a build target\n" % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_target(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.target = 'test-target'

+         self.dest_tag = 'test-dest-tag'

+         self.new_target_name = 'new-test-target'

+         self.new_dest_tag = 'new-dest-tag'

+         self.new_build_tag = 'new-build-tag'

+ 

+     def test_edit_target_without_option(self):

+         expected = self.format_error_message("Please specify a build target")

+         self.assert_system_exit(

+             handle_edit_target,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getBuildTarget.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.editBuildTarget.assert_not_called()

  

      def test_edit_target_non_exist_target(self):

-         target = 'test-target'

-         expected = "No such build target: %s" % target

+         expected = "No such build target: %s" % self.target

          self.session.getBuildTarget.return_value = None

          with self.assertRaises(koji.GenericError) as cm:

-             handle_edit_target(self.options, self.session, [target])

+             handle_edit_target(self.options, self.session, [self.target])

          self.assertEqual(expected, str(cm.exception))

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.getTag.assert_not_called()

          self.session.editBuildTarget.assert_not_called()

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_target_non_exist_dest_tag(self, stderr):

-         target = 'test-target'

-         dest_tag = 'test-dest-tag'

-         expected = "No such destination tag: %s\n" % dest_tag

+     def test_edit_target_non_exist_dest_tag(self):

          self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_target(self.options, self.session, ['--dest-tag', dest_tag, target])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_edit_target,

+             self.options,

+             self.session,

+             ['--dest-tag', self.dest_tag, self.target],

+             stdout='',

+             stderr="No such destination tag: %s\n" % self.dest_tag,

+             activate_session=None,

+             exit_code=1

+         )

+         self.session.getBuildTarget.assert_called_once_with(self.target)

+         self.session.getTag.assert_called_once_with(self.dest_tag)

          self.session.editBuildTarget.assert_not_called()

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_target_without_perms(self, stderr):

+     def test_edit_target_without_perms(self):

          side_effect_result = [False, False]

- 

-         target = 'test-target'

          self.session.hasPerm.side_effect = side_effect_result

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_target(self.options, self.session, [target])

-         self.assertExitCode(ex, 2)

-         expected_msg = """Usage: %s edit-target [options] <name>

- (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)

+         expected = self.format_error_message("This action requires target or admin privileges")

+         self.assert_system_exit(

+             handle_edit_target,

+             self.options,

+             self.session,

+             [self.target],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

          self.session.editBuildTarget.assert_not_called()

+         self.session.getTag.assert_not_called()

          self.session.getBuildTarget.assert_not_called()

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_edit_target_new_name(self, stdout):

-         target = 'test-target'

-         new_target_name = 'new-test-target'

          self.session.getBuildTarget.return_value = self.build_target_info

-         rv = handle_edit_target(self.options, self.session, ['--rename', new_target_name, target])

+         rv = handle_edit_target(self.options, self.session, ['--rename', self.new_target_name,

+                                                              self.target])

          self.assertEqual(rv, None)

          expected_msg = ''

          self.assert_console_message(stdout, expected_msg)

          self.session.getTag.assert_not_called()

-         self.session.getBuildTarget.assert_called_once_with(target)

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.editBuildTarget.assert_called_once_with(

-             self.build_target_info['orig_name'], new_target_name,

+             self.build_target_info['orig_name'], self.new_target_name,

              self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name'])

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_edit_target_dest_tag(self, stdout):

-         target = 'test-target'

-         new_dest_tag = 'new-dest-tag'

          self.session.getBuildTarget.return_value = self.build_target_info

          self.session.getTag.return_value = self.dest_tag_info

-         rv = handle_edit_target(self.options, self.session, ['--dest-tag', new_dest_tag, target])

+         rv = handle_edit_target(self.options, self.session, ['--dest-tag', self.new_dest_tag,

+                                                              self.target])

          self.assertEqual(rv, None)

          expected_msg = ''

          self.assert_console_message(stdout, expected_msg)

-         self.session.getTag.assert_called_once_with(new_dest_tag)

-         self.session.getBuildTarget.assert_called_once_with(target)

+         self.session.getTag.assert_called_once_with(self.new_dest_tag)

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.editBuildTarget.assert_called_once_with(

              self.build_target_info['orig_name'], self.build_target_info['name'],

              self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name'])

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_target_non_exist_build_tag(self, stderr):

-         target = 'test-target'

-         new_build_tag = 'new-build-tag'

+     def test_edit_target_non_exist_build_tag(self):

          self.session.getBuildTarget.return_value = self.build_target_info

          self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target])

-         self.assertExitCode(ex, 1)

-         expected_msg = "No such tag: %s\n" % new_build_tag

-         self.assert_console_message(stderr, expected_msg)

-         self.session.getTag.assert_called_once_with(new_build_tag)

-         self.session.getBuildTarget.assert_called_once_with(target)

+         self.assert_system_exit(

+             handle_edit_target,

+             self.options,

+             self.session,

+             ['--build-tag', self.new_build_tag, self.target],

+             stdout='',

+             stderr="No such tag: %s\n" % self.new_build_tag,

+             activate_session=None,

+             exit_code=1

+         )

+         self.session.getTag.assert_called_once_with(self.new_build_tag)

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.editBuildTarget.assert_not_called()

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_edit_target_tag_arch_none(self, stderr):

-         target = 'test-target'

-         new_build_tag = 'new-build-tag'

+     def test_edit_target_tag_arch_none(self):

          build_tag_info = copy.deepcopy(self.build_tag_info)

          build_tag_info['arches'] = ''

          self.session.getBuildTarget.return_value = self.build_target_info

          self.session.getTag.return_value = build_tag_info

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target])

-         self.assertExitCode(ex, 1)

-         expected_msg = "Build tag has no arches: %s\n" % new_build_tag

-         self.assert_console_message(stderr, expected_msg)

-         self.session.getTag.assert_called_once_with(new_build_tag)

-         self.session.getBuildTarget.assert_called_once_with(target)

+         self.assert_system_exit(

+             handle_edit_target,

+             self.options,

+             self.session,

+             ['--build-tag', self.new_build_tag, self.target],

+             stdout='',

+             stderr="Build tag has no arches: %s\n" % self.new_build_tag,

+             activate_session=None,

+             exit_code=1

+         )

+         self.session.getTag.assert_called_once_with(self.new_build_tag)

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.editBuildTarget.assert_not_called()

+         self.activate_session_mock.assert_called_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_edit_target_build_tag_valid(self, stdout):

-         target = 'test-target'

-         new_build_tag = 'new-build-tag'

          self.session.getBuildTarget.return_value = self.build_target_info

          self.session.getTag.return_value = self.build_tag_info

-         rv = handle_edit_target(self.options, self.session, ['--build-tag', new_build_tag, target])

+         rv = handle_edit_target(self.options, self.session, ['--build-tag', self.new_build_tag,

+                                                              self.target])

          self.assertEqual(rv, None)

          expected_msg = ''

          self.assert_console_message(stdout, expected_msg)

-         self.session.getTag.assert_called_once_with(new_build_tag)

-         self.session.getBuildTarget.assert_called_once_with(target)

+         self.session.getTag.assert_called_once_with(self.new_build_tag)

+         self.session.getBuildTarget.assert_called_once_with(self.target)

          self.session.editBuildTarget.assert_called_once_with(

              self.build_target_info['orig_name'], self.build_target_info['name'],

              self.build_target_info['build_tag_name'], self.build_target_info['dest_tag_name'])

+         self.activate_session_mock.assert_called_with(self.session, self.options)

@@ -1,76 +1,61 @@ 

  from __future__ import absolute_import

  

  import unittest

- import os

- import sys

  

  import six

  import mock

+ import koji

  

  

  from koji_cli.commands import handle_edit_user

  from . import utils

  

- progname = os.path.basename(sys.argv[0]) or 'koji'

- 

  

  class TestEditUser(utils.CliTestCase):

-     # Show long diffs in error output...

-     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 edit-user <username> [options]

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.user = 'user'

+         self.rename = 'user2'

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_edit_user(self, activate_session_mock, stdout):

-         user = 'user'

-         rename = 'user2'

-         args = [user]

-         args.append('--rename=' + rename)

+     def test_handle_edit_user(self, stdout):

+         args = [self.user]

+         args.append('--rename=' + self.rename)

          args.append('--add-krb=addedkrb')

          args.append('--remove-krb=removedkrb')

          args.append('--edit-krb=oldkrb=newkrb')

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

  

          # Run it and check immediate output

          # args: user --rename=user --krb=krb

          # expected: success

-         rv = handle_edit_user(options, session, args)

+         rv = handle_edit_user(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.editUser.assert_called_once_with(user, rename,

-                                                  [{'new': 'newkrb', 'old': 'oldkrb'},

-                                                   {'new': 'addedkrb', 'old': None},

-                                                   {'new': None, 'old': 'removedkrb'}])

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.editUser.assert_called_once_with(self.user, self.rename,

+                                                       [{'new': 'newkrb', 'old': 'oldkrb'},

+                                                        {'new': 'addedkrb', 'old': None},

+                                                        {'new': None, 'old': 'removedkrb'}])

          self.assertEqual(rv, None)

  

-         stdout.seek(0)

-         stdout.truncate()

-         session.reset_mock()

-         activate_session_mock.reset_mock()

- 

-     @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_edit_user_help(self, activate_session_mock, stderr, stdout):

-         args = ['--help']

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

+     def test_handle_edit_user_help(self):

          # Run it and check immediate output

          # args: --help

          # expected: failed, help info shows

-         with self.assertRaises(SystemExit) as cm:

-             handle_edit_user(options, session, args)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = """Usage: %s edit-user <username> [options]

+         self.assert_help(

+             handle_edit_user,

+             """Usage: %s edit-user <username> [options]

  (Specify the --help global option for a list of other help options)

  

  Options:
@@ -79,74 +64,49 @@ 

    --edit-krb=OLD=NEW  Change kerberos principal of the user

    --add-krb=KRB       Add kerberos principal of the user

    --remove-krb=KRB    Remove kerberos principal of the user

- """ % progname

-         expected_stderr = ''

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+ """ % self.progname)

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.editUser.assert_not_called()

-         self.assertEqual(cm.exception.code, 0)

- 

-     @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_edit_user_no_arg(self, activate_session_mock, stderr, stdout):

-         args = []

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

+         self.activate_session_mock.assert_not_called()

+         self.session.editUser.assert_not_called()

  

+     def test_handle_edit_user_no_arg(self):

          # Run it and check immediate output

          # args: --help

          # expected: failed, help info shows

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_user(options, session, args)

-         self.assertExitCode(ex, 2)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = ''

-         expected_stderr = """Usage: %(progname)s edit-user <username> [options]

- (Specify the --help global option for a list of other help options)

- 

- %(progname)s: error: You must specify the username of the user to edit

- """ % {'progname': progname}

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+         expected = self.format_error_message("You must specify the username of the user to edit")

+         self.assert_system_exit(

+             handle_edit_user,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.editUser.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+         self.session.editUser.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_edit_user_more_arg(self, activate_session_mock, stderr, stdout):

+     def test_handle_edit_user_more_arg(self):

          args = ['user', 'user2']

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

- 

          # Run it and check immediate output

          # args: --help

          # expected: failed, help info shows

-         with self.assertRaises(SystemExit) as ex:

-             handle_edit_user(options, session, args)

-         self.assertExitCode(ex, 2)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = ''

-         expected_stderr = """Usage: %(progname)s edit-user <username> [options]

- (Specify the --help global option for a list of other help options)

- 

- %(progname)s: error: This command only accepts one argument (username)

- """ % {'progname': progname}

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+         expected = self.format_error_message("This command only accepts one argument (username)")

+         self.assert_system_exit(

+             handle_edit_user,

+             self.options,

+             self.session,

+             args,

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

          # Finally, assert that things were called as we expected.

-         activate_session_mock.assert_not_called()

-         session.editUser.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+         self.session.editUser.assert_not_called()

  

  

  if __name__ == '__main__':

@@ -4,8 +4,8 @@ 

  

  import mock

  import six

- 

  import koji

+ 

  from koji_cli.commands import handle_enable_channel

  from . import utils

  
@@ -15,6 +15,11 @@ 

      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 enable-channel [options] <channelname> [<channelname> ...]

  (Specify the --help global option for a list of other help options)

  
@@ -33,70 +38,61 @@ 

              m._result = (result,)

          return m

  

-     @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_enable_channel(self, activate_session_mock, stdout, stderr):

+     def test_handle_enable_channel_no_such_channel(self):

          """Test enable-channel function"""

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         mcall = session.multicall.return_value.__enter__.return_value

+         mcall = self.session.multicall.return_value.__enter__.return_value

  

          mcall.getChannel.return_value = self.__vm(None)

  

          arguments = ['channel1', 'channel2']

-         with self.assertRaises(SystemExit) as ex:

-             handle_enable_channel(options, session, arguments)

-         self.assertExitCode(ex, 1)

-         activate_session_mock.assert_called_once()

-         session.multicall.assert_called_once()

-         session.enableChannel.assert_not_called()

          expect = ''

          for host in arguments:

              expect += "No such channel: %s\n" % host

          stderr_exp = "No changes made. Please correct the command line.\n"

-         self.assert_console_message(stdout, expect)

-         self.assert_console_message(stderr, stderr_exp)

- 

-         # reset session mocks

-         activate_session_mock.reset_mock()

-         session.multicall.reset_mock()

-         session.enableChannel.reset_mock()

-         mcall = session.multicall.return_value.__enter__.return_value

+         self.assert_system_exit(

+             handle_enable_channel,

+             self.options,

+             self.session,

+             arguments,

+             stdout=expect,

+             stderr=stderr_exp,

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once()

+         self.session.multicall.assert_called_once()

+         self.session.enableChannel.assert_not_called()

  

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_enable_channel(self, stdout):

+         mcall = self.session.multicall.return_value.__enter__.return_value

          mcall.getChannel.return_value = self.__vm(self.channelinfo)

  

          arguments = ['channel1', 'channel2', '--comment', 'enable channel test']

-         handle_enable_channel(options, session, arguments)

-         activate_session_mock.assert_called_once()

-         self.assertEqual(2, session.multicall.call_count)

+         handle_enable_channel(self.options, self.session, arguments)

+         self.activate_session_mock.assert_called_once()

+         self.assertEqual(2, self.session.multicall.call_count)

          self.assert_console_message(stdout, '')

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_enable_host_no_argument(self, activate_session_mock, stdout):

+     def test_handle_enable_host_no_argument(self):

          """Test enable-channel function without arguments"""

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         session.getChannel.return_value = None

-         session.multicall.return_value = [[None]]

-         session.enableChannel.return_value = True

+         self.session.getChannel.return_value = None

+         self.session.multicall.return_value = [[None]]

+         self.session.enableChannel.return_value = True

  

          expected = self.format_error_message("At least one channel must be specified")

          self.assert_system_exit(

              handle_enable_channel,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

              activate_session=None)

  

-         activate_session_mock.assert_not_called()

-         session.getChannel.assert_not_called()

-         session.multicall.assert_not_called()

-         session.enableChannel.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+         self.session.getChannel.assert_not_called()

+         self.session.multicall.assert_not_called()

+         self.session.enableChannel.assert_not_called()

  

      def test_handle_enable_channel_help(self):

          """Test enable-channel help message"""

@@ -2,6 +2,7 @@ 

  import mock

  import six

  import unittest

+ import koji

  

  from mock import call

  from koji_cli.commands import handle_enable_host
@@ -9,33 +10,24 @@ 

  

  

  class TestEnableHost(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     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 enable-host [options] <hostname> [<hostname> ...]

  (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_enable_host(

-             self,

-             activate_session_mock,

-             stdout,

-             stderr):

+     def test_handle_enable_host_no_such_host(self):

          """Test %s function""" % handle_enable_host.__name__

-         arguments = []

-         options = mock.MagicMock()

-         session = mock.MagicMock()

  

-         session.getHost.return_value = None

-         session.enableHost.return_value = True

-         session.editHost.return_value = True

+         self.session.getHost.return_value = None

+         self.session.enableHost.return_value = True

+         self.session.editHost.return_value = True

  

          #

          # session.multiCall returns:
@@ -54,71 +46,66 @@ 

          #     'name': 'kbuilder02' ...}]

          #

  

-         session.multiCall.return_value = [[None], [None]]

+         self.session.multiCall.return_value = [[None], [None]]

  

          arguments = ['host1', 'host2']

-         with self.assertRaises(SystemExit) as ex:

-             handle_enable_host(options, session, arguments)

-         self.assertExitCode(ex, 1)

-         activate_session_mock.assert_called_once()

-         session.getHost.assert_has_calls([call('host1'), call('host2')])

-         session.multiCall.assert_called_once()

-         session.enableHost.assert_not_called()

-         session.editHost.assert_not_called()

          expect = ''

          for host in arguments:

              expect += "No such host: %s\n" % host

          stderr_exp = "No changes made. Please correct the command line.\n"

-         self.assert_console_message(stdout, expect)

-         self.assert_console_message(stderr, stderr_exp)

- 

-         # reset session mocks

-         activate_session_mock.reset_mock()

-         session.multiCall.reset_mock()

-         session.disableHost.reset_mock()

-         session.editHost.reset_mock()

+         self.assert_system_exit(

+             handle_enable_host,

+             self.options,

+             self.session,

+             arguments,

+             stdout=expect,

+             stderr=stderr_exp,

+             activate_session=None,

+             exit_code=1

+         )

+         self.session.getHost.assert_has_calls([call('host1'), call('host2')])

+         self.session.multiCall.assert_called_once()

+         self.session.enableHost.assert_not_called()

+         self.session.editHost.assert_not_called()

  

-         session.multiCall.return_value = [

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_handle_enable_host_valid(self, stdout):

+         self.session.multiCall.return_value = [

              [{'id': 1, 'name': 'host1'}], [{'id': 2, 'name': 'host2'}]

          ]

  

          arguments = ['host1', 'host2', '--comment', 'disable host test']

-         handle_enable_host(options, session, arguments)

-         activate_session_mock.assert_called_once()

-         session.getHost.assert_has_calls([call('host1'), call('host2')])

-         self.assertEqual(2, session.multiCall.call_count)

-         session.enableHost.assert_has_calls([call('host1'), call('host2')])

-         session.editHost.assert_has_calls(

+         handle_enable_host(self.options, self.session, arguments)

+         self.activate_session_mock.assert_called_once()

+         self.session.getHost.assert_has_calls([call('host1'), call('host2')])

+         self.assertEqual(2, self.session.multiCall.call_count)

+         self.session.enableHost.assert_has_calls([call('host1'), call('host2')])

+         self.session.editHost.assert_has_calls(

              [call('host1', comment='disable host test'),

               call('host2', comment='disable host test')])

          self.assert_console_message(stdout, '')

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_enable_host_no_argument(self, activate_session_mock, stdout):

+     def test_handle_enable_host_no_argument(self):

          """Test %s function without arguments""" % handle_enable_host.__name__

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

-         session.getHost.return_value = None

-         session.multiCall.return_value = [[None]]

-         session.enableHost.return_value = True

-         session.editHost.return_value = True

+         self.session.getHost.return_value = None

+         self.session.multiCall.return_value = [[None]]

+         self.session.enableHost.return_value = True

+         self.session.editHost.return_value = True

  

          expected = self.format_error_message("At least one host must be specified")

          self.assert_system_exit(

              handle_enable_host,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

              activate_session=None)

  

-         activate_session_mock.assert_not_called()

-         session.getHost.assert_not_called()

-         session.multiCall.assert_not_called()

-         session.enableHost.assert_not_called()

-         session.editHost.assert_not_called()

+         self.activate_session_mock.assert_not_called()

+         self.session.getHost.assert_not_called()

+         self.session.multiCall.assert_not_called()

+         self.session.enableHost.assert_not_called()

+         self.session.editHost.assert_not_called()

  

      def test_handle_enable_host_help(self):

          """Test %s help message""" % handle_enable_host.__name__

@@ -1,61 +1,58 @@ 

  from __future__ import absolute_import

  import mock

- import six

  import unittest

+ import koji

  

  from koji_cli.commands import handle_enable_user

  from . import utils

  

  

  class TestEnableUser(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     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 enable-user <username>

  (Specify the --help global option for a list of other help options)

  

  %s: error: {message}

  """ % (self.progname, self.progname)

+         self.username = 'user'

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_enable_user(

-             self,

-             activate_session_mock,

-             stdout):

+     def test_handle_enable_user_no_argument(self):

          """Test handle_enable_user function"""

-         session = mock.MagicMock()

-         options = mock.MagicMock()

-         username = 'user'

- 

-         # Case 1. no argument error

-         expected = self.format_error_message(

-             "You must specify the username of the user to enable")

+         expected = self.format_error_message("You must specify the username of the user to enable")

          self.assert_system_exit(

              handle_enable_user,

-             options,

-             session,

+             self.options,

+             self.session,

              [],

              stderr=expected,

              activate_session=None)

+         self.activate_session_mock.assert_not_called()

+         self.session.enableUser.assert_not_called()

  

-         # Case 2. Too many argument error

-         expected = self.format_error_message(

-             "This command only accepts one argument (username)")

+     def test_handle_enable_user_to_many_arguments(self):

+         """Test handle_enable_user function"""

+         expected = self.format_error_message("This command only accepts one argument (username)")

          self.assert_system_exit(

              handle_enable_user,

-             options,

-             session,

+             self.options,

+             self.session,

              ['user-1', 'user-2', 'user-3'],

              stderr=expected,

              activate_session=None)

+         self.activate_session_mock.assert_not_called()

+         self.session.enableUser.assert_not_called()

  

-         # Case 3. Enable user test

-         handle_enable_user(options, session, [username])

-         session.enableUser.assert_called_with(username)

-         activate_session_mock.assert_called_with(session, options)

+     def test_handle_enable_user_valid(self):

+         """Test handle_enable_user function"""

+         handle_enable_user(self.options, self.session, [self.username])

+         self.session.enableUser.assert_called_with(self.username)

+         self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.enableUser.assert_called_with(self.username)

  

      def test_handle_enable_user_help(self):

          self.assert_help(

@@ -10,7 +10,7 @@ 

  

      def setUp(self):

          self.options = mock.MagicMock()

-         self.options.maxDiff = None

+         self.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] <task_id> [<task_id> ...]
@@ -19,30 +19,37 @@ 

  %s: error: {message}

  """ % (self.progname, self.progname)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_free_task_without_arg(self, stderr):

+     def test_free_task_without_arg(self):

          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):

+         self.assert_system_exit(

+             handle_free_task,

+             self.options, self.session, [],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.freeTask.assert_not_called()

+ 

+     def test_free_task_id_string_chars(self):

          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)

+         self.assert_system_exit(

+             handle_free_task,

+             self.options, self.session, ['1abc'],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.freeTask.assert_not_called()

  

      @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)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.freeTask.assert_has_calls([mock.call(1), mock.call(2), mock.call(3)])

  

      def test_handle_free_task_help(self):

          self.assert_help(

@@ -1,6 +1,5 @@ 

  from __future__ import absolute_import

  import mock

- import six

  import unittest

  

  from koji_cli.commands import handle_grant_cg_access
@@ -9,57 +8,60 @@ 

  

  class TestGrantCGAccess(utils.CliTestCase):

  

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

          self.error_format = """Usage: %s grant-cg-access <user> <content generator>

  (Specify the --help global option for a list of other help options)

  

  %s: error: {message}

  """ % (self.progname, self.progname)

+         self.maxDiff = None

+         self.options = mock.MagicMock()

+         self.options.quiet = False

+         self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.cg = 'cg'

+         self.user = 'user'

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_grant_cg_access(

-             self,

-             activate_session_mock,

-             stdout):

+     def test_handle_grant_cg_access_arg_error(self):

          """Test handle_grant_cg_access function"""

-         session = mock.MagicMock()

-         options = mock.MagicMock()

-         cg = 'cg'

-         user = 'user'

- 

-         # Case 1. argument error

-         expected = self.format_error_message(

-             "Please specify a user and content generator")

-         for args in [[], [user]]:

+         expected = self.format_error_message("Please specify a user and content generator")

+         for args in [[], [self.user]]:

              self.assert_system_exit(

                  handle_grant_cg_access,

-                 options,

-                 session,

+                 self.options,

+                 self.session,

                  args,

                  stderr=expected,

-                 activate_session=None)

+                 activate_session=None,

+                 exit_code=2)

+         self.activate_session_mock.assert_not_called()

+         self.session.grantCGAccess.assert_not_called()

  

-         # Case 2. user not exists

-         expected = self.format_error_message(

-             "No such user: %s" % user)

-         session.getUser.return_value = None

+     def test_handle_grant_cg_access_non_exist_user(self):

+         """Test handle_grant_cg_access function"""

+         expected = self.format_error_message("No such user: %s" % self.user)

+         self.session.getUser.return_value = None

          self.assert_system_exit(

              handle_grant_cg_access,

-             options,

-             session,

-             [user, cg],

-             stderr=expected)

+             self.options,

+             self.session,

+             [self.user, self.cg],

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getUser.assert_called_once_with(self.user)

+         self.session.grantCGAccess.assert_not_called()

  

-         # Case 3. grant permission with --new

+     def test_handle_grant_cg_access_valid(self):

+         """Test handle_grant_cg_access function"""

          cg = 'content-generator'

-         session.getUser.return_value = {'id': 101, 'name': user}

-         handle_grant_cg_access(options, session, [user, cg, '--new'])

-         calls = [mock.call(user, cg, create=True)]

-         session.grantCGAccess.assert_has_calls(calls)

+         self.session.getUser.return_value = {'id': 101, 'name': self.user}

+         handle_grant_cg_access(self.options, self.session, [self.user, cg, '--new'])

+         calls = [mock.call(self.user, cg, create=True)]

+         self.session.grantCGAccess.assert_has_calls(calls)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getUser.assert_called_once_with(self.user)

  

      def test_handle_grant_cg_access_help(self):

          self.assert_help(

file modified
+37 -35
@@ -27,74 +27,76 @@ 

  

  

  class TestHello(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

+         self.options = mock.MagicMock()

+         self.options.quiet = False

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.error_format = """Usage: %s moshimoshi [options]

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

          self.huburl = "https://%s.local/%shub" % (self.progname, self.progname)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

      @mock.patch('koji_cli.commands._printable_unicode')

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_moshimoshi(

-             self,

-             activate_session_mock,

-             print_unicode_mock,

-             stderr,

-             stdout):

+     def test_handle_moshimoshi(self, print_unicode_mock, stdout):

          """Test handle_moshimoshi function"""

          user = {'name': self.progname,

                  'krb_principal': '%s@localhost' % self.progname}

          cert = '/etc/pki/user.cert'

-         options = mock.MagicMock()

-         # Mock out the xmlrpc server

          session = mock.MagicMock(baseurl=self.huburl, authtype=None)

+         # Mock out the xmlrpc server

          session.getLoggedInUser.return_value = None

          session.krb_principal = user['krb_principal']

          print_unicode_mock.return_value = "Hello"

  

-         expect = """Usage: %s moshimoshi [options]

- (Specify the --help global option for a list of other help options)

- 

- %s: error: This command takes no arguments

- """ % (self.progname, self.progname)

- 

          self.assert_system_exit(

              handle_moshimoshi,

-             options,

-             session,

-             ['argument'],

-             stderr=expect,

-             activate_session=None)

- 

+             self.options, session, ['argument'],

+             stderr=self.format_error_message('This command takes no arguments'),

+             activate_session=None,

+             exit_code=2)

+         self.activate_session_mock.assert_not_called()

+         session.getLoggedInUser.assert_not_called()

+ 

+         # annonymous user

+         message = "Not authenticated\n" + "Hello, anonymous user!"

+         hubinfo = "You are using the hub at %s" % self.huburl

+         handle_moshimoshi(self.options, session, [])

+         self.assert_console_message(stdout, "{0}\n\n{1}\n".format(message, hubinfo))

+         self.activate_session_mock.assert_called_once_with(session, self.options)

+         session.getLoggedInUser.assert_called_once_with()

+         self.activate_session_mock.reset_mock()

+         session.getLoggedInUser.reset_mock()

+ 

+         # valid authentication

          auth_tests = {

              koji.AUTHTYPE_NORMAL: 'Authenticated via password',

              koji.AUTHTYPE_GSSAPI: 'Authenticated via GSSAPI',

              koji.AUTHTYPE_KERB: 'Authenticated via Kerberos principal %s' %

                                  user['krb_principal'],

              koji.AUTHTYPE_SSL: 'Authenticated via client certificate %s' %

-                                 cert

+                                cert

          }

- 

-         message = "Not authenticated\n" + "Hello, anonymous user!"

          hubinfo = "You are using the hub at %s" % self.huburl

-         handle_moshimoshi(options, session, [])

-         self.assert_console_message(

-             stdout, "{0}\n\n{1}\n".format(message, hubinfo))

- 

          session.getLoggedInUser.return_value = user

          message = "Hello, %s!" % self.progname

-         options.cert = cert

+         self.options.cert = cert

          for authtype, authinfo in auth_tests.items():

              session.authtype = authtype

              print_unicode_mock.reset_mock()

              print_unicode_mock.return_value = "Hello"

-             handle_moshimoshi(options, session, [])

+             handle_moshimoshi(self.options, session, [])

              print_unicode_mock.assert_called_once()

              self.assert_console_message(

                  stdout, "{0}\n\n{1}\n{2}\n".format(message, hubinfo, authinfo))

+         mock_call_activate = mock.call(session, self.options)

+         self.activate_session_mock.assert_has_calls([mock_call_activate, mock_call_activate,

+                                                      mock_call_activate, mock_call_activate])

+         session.getLoggedInUser.assert_has_calls([mock.call(), mock.call(), mock.call(),

+                                                   mock.call()])

  

      def test_handle_moshimoshi_help(self):

          self.assert_help(

file modified
+74 -32
@@ -4,6 +4,7 @@ 

  import time

  import locale

  from six.moves import StringIO

+ import copy

  

  import koji

  from koji_cli.commands import anon_handle_hostinfo
@@ -13,6 +14,7 @@ 

  class TestHostinfo(utils.CliTestCase):

      def setUp(self):

          # force locale to compare 'expect' value

+         self.maxDiff = None

          locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))

          self.options = mock.MagicMock()

          self.options.debug = False
@@ -23,16 +25,22 @@ 

          time.tzset()

          self.hostinfo = {'arches': 'x86_64',

                           'capacity': 2.0,

-                          'comment': None,

-                          'description': None,

                           'enabled': True,

                           'id': 1,

                           'name': 'kojibuilder',

                           'ready': True,

                           'task_load': 0.0,

-                          'user_id': 2}

+                          'user_id': 2,

+                          'comment': 'test-comment',

+                          'description': 'test-description'}

          self.last_update = 1615875554.862938

          self.list_channels = [{'id': 1, 'name': 'default'}, {'id': 2, 'name': 'createrepo'}]

+         self.error_format = """Usage: %s hostinfo [options] <hostname> [<hostname> ...]

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

  

      def tearDown(self):

          locale.resetlocale()
@@ -42,16 +50,18 @@ 

              os.environ['TZ'] = self.original_timezone

              time.tzset()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_hostinfo_without_option(self, stderr):

-         expected = "Usage: %s hostinfo [options] <hostname> [<hostname> ...]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Please specify a host\n" % (self.progname, self.progname)

+     def test_hostinfo_without_option(self):

          self.session.getChannel.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_hostinfo(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_hostinfo,

+             self.options, self.session, [],

+             stderr=self.format_error_message('Please specify a host'),

+             exit_code=2,

+             activate_session=None)

+         self.session.getHost.assert_not_called()

+         self.session.getLastHostUpdate.assert_not_called()

+         self.session.listChannels.assert_not_called()

+         self.ensure_connection_mock.assert_not_called()

  

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_hostinfo_valid(self, stdout):
@@ -60,8 +70,8 @@ 

  Arches: x86_64

  Capacity: 2.0

  Task Load: 0.00

- Description:

- Comment:

+ Description: test-description

+ Comment: test-comment

  Enabled: yes

  Ready: yes

  Last Update: Tue, 16 Mar 2021 06:19:14 UTC
@@ -78,11 +88,13 @@ 

          self.session.getHost.assert_called_once_with(self.hostinfo['name'])

          self.session.getLastHostUpdate.assert_called_once_with(self.hostinfo['id'], ts=True)

          self.session.listChannels.assert_called_once_with(hostID=self.hostinfo['id'])

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

          self.assertEqual(self.session.listBuildroots.call_count, 3)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     @mock.patch('sys.stdout', new_callable=StringIO)

-     def test_hostinfo_more_hosts_with_non_exit_host(self, stdout, stderr):

+     def test_hostinfo_more_hosts_with_non_exit_host(self):

+         hostinfo = copy.deepcopy(self.hostinfo)

+         hostinfo['description'] = None

+         hostinfo['comment'] = None

          hostname = 'kojibuilder'

          non_exist_hostname = 'testhost'

          expected_stdout = """Name: kojibuilder
@@ -99,28 +111,58 @@ 

  Active Buildroots:

  None

  """

-         expected_error = "No such host: %s\n\n" % non_exist_hostname

-         self.session.getHost.side_effect = [None, self.hostinfo]

+         self.session.getHost.side_effect = [None, hostinfo]

          self.session.getLastHostUpdate.return_value = self.last_update

          self.session.listChannels.return_value = self.list_channels

          self.session.listBuildroots.return_value = []

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_hostinfo(self.options, self.session, [non_exist_hostname, hostname])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stdout, expected_stdout)

-         self.assert_console_message(stderr, expected_error)

+         self.assert_system_exit(

+             anon_handle_hostinfo,

+             self.options, self.session, [non_exist_hostname, hostname],

+             stderr="No such host: %s\n\n" % non_exist_hostname,

+             stdout=expected_stdout,

+             exit_code=1,

+             activate_session=None)

          self.assertEqual(self.session.getHost.call_count, 2)

          self.session.getLastHostUpdate.assert_called_once_with(self.hostinfo['id'], ts=True)

          self.session.listChannels.assert_called_once_with(hostID=self.hostinfo['id'])

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

          self.assertEqual(self.session.listBuildroots.call_count, 3)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_hostinfo_non_exist_host(self, stderr):

-         hostname = 'testhost'

-         expected = "No such host: %s\n\n" % hostname

+     def test_hostinfo_non_exist_host(self):

+         hostname = '1111'

          self.session.getHost.return_value = None

          self.session.getLastHostUpdate.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_hostinfo(self.options, self.session, [hostname])

-         self.assertExitCode(ex, 1)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_hostinfo,

+             self.options, self.session, [hostname],

+             stderr="No such host: %s\n\n" % hostname,

+             stdout='',

+             exit_code=1,

+             activate_session=None)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_hostinfo_valid_param_error(self, stdout):

+         expected = """Name: kojibuilder

+ ID: 1

+ Arches: x86_64

+ Capacity: 2.0

+ Task Load: 0.00

+ Description: test-description

+ Comment: test-comment

+ Enabled: yes

+ Ready: yes

+ Last Update: Tue, 16 Mar 2021 06:19:14 UTC

+ Channels: default createrepo

+ Active Buildroots:

+ None

+ """

+         self.session.getHost.return_value = self.hostinfo

+         self.session.getLastHostUpdate.side_effect = [koji.ParameterError, self.last_update]

+         self.session.listChannels.return_value = self.list_channels

+         rv = anon_handle_hostinfo(self.options, self.session, [self.hostinfo['name']])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getHost.assert_called_once_with(self.hostinfo['name'])

+         self.session.listChannels.assert_called_once_with(hostID=self.hostinfo['id'])

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.assertEqual(self.session.listBuildroots.call_count, 3)

@@ -58,6 +58,7 @@ 

      "wait": None,

  }

  

+ 

  def mock_open():

      """Return the right patch decorator for open"""

      if six.PY2:
@@ -73,11 +74,8 @@ 

  

  

  class TestBuildImageOz(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.task_options = Options(TASK_OPTIONS)

          self.session = mock.MagicMock()

          self.options = mock.MagicMock()
@@ -190,37 +188,27 @@ 

      def test_build_image_oz_exception(self):

          self.session.getBuildTarget.return_value = {}

          with self.assertRaises(koji.GenericError) as cm:

-             _build_image_oz(

-                 self.options, self.task_options, self.session, self.args)

-         self.assertEqual(

-             str(cm.exception), 'No such build target: %s' % self.args[2])

+             _build_image_oz(self.options, self.task_options, self.session, self.args)

+         self.assertEqual(str(cm.exception), 'No such build target: %s' % self.args[2])

  

          self.session.getBuildTarget.return_value = self.target_info

          self.session.getTag.return_value = {}

          with self.assertRaises(koji.GenericError) as cm:

-             _build_image_oz(

-                 self.options, self.task_options, self.session, self.args)

-         self.assertEqual(

-             str(cm.exception),

-             'No such destination tag: %s' % self.target_info['dest_tag_name'])

+             _build_image_oz(self.options, self.task_options, self.session, self.args)

+         self.assertEqual(str(cm.exception),

+                          'No such destination tag: %s' % self.target_info['dest_tag_name'])

  

          self.session.getTag.return_value = self.tag_info

          with self.assertRaises(koji.GenericError) as cm:

              self.task_options.ksurl = None

              self.task_options.scratch = False

-             _build_image_oz(

-                 self.options, self.task_options, self.session, self.args)

-         self.assertEqual(

-             str(cm.exception),

-             'Non-scratch builds must provide ksurl')

+             _build_image_oz(self.options, self.task_options, self.session, self.args)

+         self.assertEqual(str(cm.exception), 'Non-scratch builds must provide ksurl')

  

  

  class TestImageBuild(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.options = mock.MagicMock()

          self.session = mock.MagicMock()

          self.configparser = mock.patch('six.moves.configparser.ConfigParser').start()
@@ -236,37 +224,37 @@ 

      def tearDown(self):

          mock.patch.stopall()

  

-     @mock.patch('koji_cli.commands._build_image_oz')

-     def test_handle_image_build_with_config(self, build_image_oz_mock):

-         """Test handle_image_build argument with --config cases"""

- 

-         # Case 1, config file not exist case

+     def test_handle_image_build_with_config_error(self):

+         """Test handle_image_build argument with --config, config error"""

          with self.assertRaises(koji.ConfigurationError) as cm:

              handle_image_build(self.options,

                                 self.session,

                                 ['--config', '/nonexistent-file-755684354'])

          self.assertEqual(cm.exception.args[0],

                           "Config file /nonexistent-file-755684354 can't be opened.")

+         self.session.activate_session_mock.assert_not_called()

  

- 

-         # Case 2, no image-build section in config file

+     def test_handle_image_build_with_config_no_image_section(self):

+         """Test handle_image_build argument with --config, no image section"""

          expected = "single section called [%s] is required" % "image-build"

  

          self.configparser.return_value = ConfigParser()

  

          self.assert_system_exit(

              handle_image_build,

-             self.options,

-             self.session,

-             ['--config',

-              os.path.join(os.path.dirname(__file__),

-                           'data/image-build-config-empty.conf')],

+             self.options, self.session, ['--config',

+                                          os.path.join(os.path.dirname(__file__),

+                                                       'data/image-build-config-empty.conf')],

              stderr=self.format_error_message(expected),

-             activate_session=None)

+             activate_session=None,

+             exit_code=2)

+         self.session.activate_session_mock.assert_not_called()

  

-         config_file = os.path.join(os.path.dirname(__file__),

-                                    'data/image-build-config.conf')

-         # Case 3, normal

+     @mock.patch('koji_cli.commands._build_image_oz')

+     def test_handle_image_build_with_config_valid_with_config(self, build_image_oz_mock):

+         """Test handle_image_build."""

+         config_file = os.path.join(os.path.dirname(__file__), 'data/image-build-config.conf')

+         self.configparser.return_value = ConfigParser()

          handle_image_build(

              self.options,

              self.session,
@@ -275,52 +263,53 @@ 

          args, kwargs = build_image_oz_mock.call_args

          TASK_OPTIONS['config'] = config_file

          self.assertDictEqual(TASK_OPTIONS, args[1].__dict__)

+         self.session.activate_session_mock.assert_not_called()

  

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_image_build_argument_error_without_config(

-             self,

-             activate_session_mock):

-         """Test handle_image_build argument errors, no --config cases"""

- 

-         # Case 1, empty argument error

+     def test_handle_image_build_argument_error_without_config_arg_error(self):

+         """Test handle_image_build argument errors, no --config, arguments error"""

          expected = "At least five arguments are required: a name, " + \

                     "a version, a build target, a URL to an " + \

                     "install tree, and 1 or more architectures."

  

          self.assert_system_exit(

-                 handle_image_build,

-                 self.options,

-                 self.session,

-                 [],

-                 stderr=self.format_error_message(expected),

-                 activate_session=None)

- 

-         # Case 2, not kickstart options (--ksurl, kickstart)

+             handle_image_build,

+             self.options,

+             self.session,

+             [],

+             stderr=self.format_error_message(expected),

+             activate_session=None,

+             exit_code=2)

+         self.session.activate_session_mock.assert_not_called()

+ 

+     def test_handle_image_build_argument_error_without_config_without_kickstart_option(self):

+         """Test handle_image_build argument errors, no --config cases,

+         without kickstart option (--ksurl, kickstart)"""

          expected = "You must specify --kickstart"

  

          self.assert_system_exit(

-                 handle_image_build,

-                 self.options,

-                 self.session,

-                 ['name', 'version', 'target', 'install-tree-url', 'arch'],

-                 stderr=self.format_error_message(expected),

-                 activate_session=None)

- 

-         # Case 3, no --distro

+             handle_image_build,

+             self.options,

+             self.session,

+             ['name', 'version', 'target', 'install-tree-url', 'arch'],

+             stderr=self.format_error_message(expected),

+             activate_session=None,

+             exit_code=2)

+         self.session.activate_session_mock.assert_not_called()

+ 

+     def test_handle_image_build_argument_error_without_config_without_distro_option(self):

+         """Test handle_image_build argument errors, no --config cases, without distro option"""

          expected = "You must specify --distro. Examples: Fedora-16, RHEL-6.4, " + \

                     "SL-6.4 or CentOS-6.4"

  

          self.assert_system_exit(

-                 handle_image_build,

-                 self.options,

-                 self.session,

-                 ['name', 'version', 'target', 'install-tree-url', 'arch',

-                  '--kickstart', 'kickstart.ks'],

-                 stderr=self.format_error_message(expected),

-                 activate_session=None)

- 

-         # activate_session() should not be called

-         activate_session_mock.assert_not_called()

+             handle_image_build,

+             self.options,

+             self.session,

+             ['name', 'version', 'target', 'install-tree-url', 'arch',

+              '--kickstart', 'kickstart.ks'],

+             stderr=self.format_error_message(expected),

+             activate_session=None,

+             exit_code=2)

  

      def test_handle_image_build_help(self):

          """Test handle_image_build help message"""

@@ -38,11 +38,8 @@ 

  

  

  class TestBuildImageIndirection(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.task_id = 1001

          self.weburl = 'https://web.url'

          self.options = mock.MagicMock()
@@ -188,11 +185,8 @@ 

  

  

  class TestImageBuildIndirection(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.options = mock.MagicMock()

          self.session = mock.MagicMock()

  

@@ -8,18 +8,17 @@ 

  from koji_cli.commands import handle_import

  from . import utils

  

+ 

  def md5_to_bytes(s):

      if six.PY2:

          return bytearray.fromhex(unicode(s))

      else:

          return bytearray.fromhex(s)

  

- class TestImport(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

  

+ class TestImport(utils.CliTestCase):

      def setUp(self):

+         self.maxDiff = None

          self.huburl = "https://%s.local/%shub" % (self.progname, self.progname)

          self.md5 = '00112233445566778899aabbccddeeff'

          self.fake_srv_dir = '/path/to/server/import'
@@ -133,7 +132,7 @@ 

      @mock.patch('sys.stderr', new_callable=six.StringIO)

      @mock.patch('koji_cli.commands.activate_session')

      def __skip_import_test(self, options, session, arguments, activate_session_mock,

-                            stderr, stdout,  **kwargs):

+                            stderr, stdout, **kwargs):

          expected = kwargs.get('expected', None)

          expected_warn = kwargs.get('expected_warn', None)

          rpm_header = kwargs.get('rpm_header', {})

@@ -1,7 +1,6 @@ 

  from __future__ import absolute_import

  

  import mock

- from six.moves import StringIO

  

  import koji

  from koji_cli.commands import handle_import_archive
@@ -10,6 +9,7 @@ 

  

  class TestImportArchive(utils.CliTestCase):

      def setUp(self):

+         self.maxDiff = None

          self.options = mock.MagicMock()

          self.options.debug = False

          self.session = mock.MagicMock()
@@ -23,120 +23,197 @@ 

  %s: error: {message}

  """ % (self.progname, self.progname)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_without_option(self, stderr):

+     def test_import_archive_without_option(self):

          expected = self.format_error_message(

              "You must specify a build ID or N-V-R and an archive to import")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, [],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_not_called()

+         self.session.hasPerm.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_wrong_type(self, stderr):

+     def test_import_archive_wrong_type(self):

          archive_type = 'test-type'

          expected = self.format_error_message("Unsupported archive type: %s" % archive_type)

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session, ['--type', archive_type,

-                                                                self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_without_type(self, stderr):

-         expected = self.format_error_message("You must specify an archive type")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session, [self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+ 

+     def test_import_archive_without_type(self):

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, [self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("You must specify an archive type"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_maven_without_perm(self, stderr):

+     def test_import_archive_type_maven_without_perm(self):

          archive_type = 'maven'

          self.session.hasPerm.side_effect = [False, False]

-         expected = self.format_error_message("This action requires the maven-import privilege")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("This action requires the maven-import privilege"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('maven-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_maven_without_type_info(self, stderr):

+     def test_import_archive_type_maven_without_type_info(self):

          archive_type = 'maven'

          self.session.hasPerm.side_effect = [False, True]

          expected = self.format_error_message(

              "--type-info must point to a .pom file when importing Maven archives")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('maven-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_win_without_perm(self, stderr):

+     def test_import_archive_type_win_without_perm(self):

          archive_type = 'win'

          self.session.hasPerm.side_effect = [False, False]

-         expected = self.format_error_message("This action requires the win-import privilege")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("This action requires the win-import privilege"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('win-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_win_without_type_info(self, stderr):

+     def test_import_archive_type_win_without_type_info(self):

          archive_type = 'win'

          self.session.hasPerm.side_effect = [False, True]

-         expected = self.format_error_message("--type-info must be specified")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("--type-info must be specified"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('win-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_win_wrong_type_info(self, stderr):

+     def test_import_archive_type_win_wrong_type_info(self):

          archive_type = 'win'

          type_info = 'archive-type'

          self.session.hasPerm.side_effect = [False, True]

          expected = self.format_error_message(

              "--type-info must be in relpath:platforms[:flags] format")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, '--type-info', type_info,

-                                    self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session,

+             ['--type', archive_type, '--type-info', type_info, self.build_id, self.archive_path],

+             stdout='',

+             stderr=expected,

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('win-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_image_without_perm(self, stderr):

+     def test_import_archive_type_image_without_perm(self):

          archive_type = 'image'

          self.session.hasPerm.side_effect = [False, False]

-         expected = self.format_error_message("This action requires the image-import privilege")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("This action requires the image-import privilege"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('image-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_import_archive_type_image_without_type_info(self, stderr):

+     def test_import_archive_type_image_without_type_info(self):

          archive_type = 'image'

          self.session.hasPerm.side_effect = [False, True]

-         expected = self.format_error_message("--type-info must be specified")

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_archive(self.options, self.session,

-                                   ['--type', archive_type, self.build_id, self.archive_path])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             handle_import_archive,

+             self.options, self.session, ['--type', archive_type, self.build_id, self.archive_path],

+             stdout='',

+             stderr=self.format_error_message("--type-info must be specified"),

+             exit_code=2,

+             activate_session=None)

          self.activate_session_mock.assert_called_with(self.session, self.options)

+         self.session.hasPerm.assert_has_calls([mock.call('image-import'), mock.call('admin')])

+         self.session.getBuild.assert_not_called()

+         self.session.createMavenBuild.assert_not_called()

+         self.session.createWinBuild.assert_not_called()

+         self.session.createImageBuild.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.importArchive.assert_not_called()

@@ -12,18 +12,22 @@ 

  

  

  class TestImportCG(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def mock_os_path_exists(self, filepath):

          if filepath in self.custom_os_path_exists:

              return self.custom_os_path_exists[filepath]

          return self.os_path_exists(filepath)

  

      def setUp(self):

+         self.maxDiff = None

+         self.options = mock.MagicMock()

+         self.session = mock.MagicMock()

          self.custom_os_path_exists = {}

          self.os_path_exists = os.path.exists

+         self.unique_path_mock = mock.patch('koji_cli.commands.unique_path').start()

+         self.running_in_bg = mock.patch('koji_cli.commands._running_in_bg').start()

+         self.running_in_bg.return_value = False

+         self.linked_upload_mock = mock.patch('koji_cli.commands.linked_upload').start()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

          self.error_format = """Usage: %s import-cg [options] <metadata_file> <files_dir>

  (Specify the --help global option for a list of other help options)

  
@@ -32,24 +36,10 @@ 

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

      @mock.patch('koji_cli.commands._progress_callback')

-     @mock.patch('koji_cli.commands.unique_path')

-     @mock.patch('koji_cli.commands._running_in_bg', return_value=False)

-     @mock.patch('koji_cli.commands.linked_upload')

-     @mock.patch('koji_cli.commands.activate_session')

      @mock.patch('koji.json')

-     def test_handle_import_cg(

-             self,

-             json_mock,

-             activate_session_mock,

-             linked_upload_mock,

-             running_in_bg_mock,

-             unique_path_mock,

-             progress_callback_mock,

-             stdout):

+     def test_handle_import_cg(self, json_mock, progress_callback_mock, stdout):

          """Test handle_import_cg function"""

          arguments = ['fake-metafile', '/path/to/files/']

-         options = mock.MagicMock()

-         session = mock.MagicMock()

          expected = ''

          fake_srv_path = '/path/to/server/cli-import'

  
@@ -82,51 +72,51 @@ 

              return calls, expect

  

          json_mock.load.return_value = metadata

-         unique_path_mock.return_value = fake_srv_path

+         self.unique_path_mock.return_value = fake_srv_path

  

          # Case 1, running in fg, progress on

          with mock.patch(utils.get_builtin_open()):

-             handle_import_cg(options, session, arguments)

+             handle_import_cg(self.options, self.session, arguments)

  

          calls, expected = gen_value("Uploading %s\n", progress_callback_mock)

          self.assert_console_message(stdout, expected)

-         linked_upload_mock.assert_not_called()

-         session.uploadWrapper.assert_has_calls(calls)

-         session.CGImport.assert_called_with(metadata, fake_srv_path, None)

+         self.linked_upload_mock.assert_not_called()

+         self.session.uploadWrapper.assert_has_calls(calls)

+         self.session.CGImport.assert_called_with(metadata, fake_srv_path, None)

  

          # Case 2, running in fg, progress off

          with mock.patch(utils.get_builtin_open()):

-             handle_import_cg(options, session, arguments + ['--noprogress'])

+             handle_import_cg(self.options, self.session, arguments + ['--noprogress'])

  

          calls, expected = gen_value("Uploading %s", None)

          self.assert_console_message(stdout, expected)

-         linked_upload_mock.assert_not_called()

-         session.uploadWrapper.assert_has_calls(calls)

-         session.CGImport.assert_called_with(metadata, fake_srv_path, None)

+         self.linked_upload_mock.assert_not_called()

+         self.session.uploadWrapper.assert_has_calls(calls)

+         self.session.CGImport.assert_called_with(metadata, fake_srv_path, None)

  

          # reset mocks

-         linked_upload_mock.reset_mock()

-         session.uploadWrapper.reset_mock()

-         session.CGImport.reset_mock()

+         self.linked_upload_mock.reset_mock()

+         self.session.uploadWrapper.reset_mock()

+         self.session.CGImport.reset_mock()

  

          # Case 3, --test option

          with mock.patch(utils.get_builtin_open()):

-             handle_import_cg(options, session, arguments + ['--test'])

+             handle_import_cg(self.options, self.session, arguments + ['--test'])

  

-         linked_upload_mock.assert_not_called()

-         session.uploadWrapper.assert_not_called()

-         session.CGImport.assert_not_called()

+         self.linked_upload_mock.assert_not_called()

+         self.session.uploadWrapper.assert_not_called()

+         self.session.CGImport.assert_not_called()

  

          calls = [call("%(relpath)s/%(filename)s" % item, item['relpath'])

                   for item in metadata['output']]

  

          # Case 4, --link option

          with mock.patch(utils.get_builtin_open()):

-             handle_import_cg(options, session, arguments + ['--link'])

+             handle_import_cg(self.options, self.session, arguments + ['--link'])

  

-         linked_upload_mock.assert_has_calls(calls)

-         session.uploadWrapper.assert_not_called()

-         session.CGImport.assert_called_with(metadata, fake_srv_path, None)

+         self.linked_upload_mock.assert_has_calls(calls)

+         self.session.uploadWrapper.assert_not_called()

+         self.session.CGImport.assert_called_with(metadata, fake_srv_path, None)

  

          # make sure there is no message on output

          self.assert_console_message(stdout, '')
@@ -137,19 +127,12 @@ 

      def test_handle_import_argument_test(self):

          """Test handle_import_cg function without arguments"""

          arguments = ['fake-metafile', '/path/to/files/']

-         options = mock.MagicMock()

-         session = mock.MagicMock()

  

          # Case 1. empty argument

-         expected = self.format_error_message(

-             "Please specify metadata files directory")

- 

          self.assert_system_exit(

              handle_import_cg,

-             options,

-             session,

-             [],

-             stderr=expected,

+             self.options, self.session, [],

+             stderr=self.format_error_message("Please specify metadata files directory"),

              activate_session=None)

  

          # Case 2. JSON module does not exist
@@ -173,26 +156,20 @@ 

  

                      # Case 3. metafile doesn't have output section

                      json_mock.load.return_value = {}

-                     expected = "Metadata contains no output\n"

                      self.assert_system_exit(

                          handle_import_cg,

-                         options,

-                         session,

-                         arguments,

-                         stderr=expected,

+                         self.options, self.session, arguments,

+                         stderr="Metadata contains no output\n",

                          exit_code=1)

  

                      # Case 4. path not exist

                      file_path = '%(relpath)s/%(filename)s' % metadata['output'][1]

                      json_mock.load.return_value = metadata

-                     expected = self.format_error_message(

-                         "No such file: %s" % file_path)

                      self.assert_system_exit(

                          handle_import_cg,

-                         options,

-                         session,

-                         arguments,

-                         stderr=expected)

+                         self.options, self.session, arguments,

+                         stderr=self.format_error_message("No such file: %s" % file_path),

+                         exit_code=2)

  

      def test_handle_import_cg_help(self):

          """Test handle_import_cg help message"""

@@ -5,6 +5,7 @@ 

  import unittest

  import json

  import pytest

+ import koji

  

  import mock

  import six
@@ -24,19 +25,27 @@ 

  

  

  class TestImportComps(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.mock_activate_session = mock.patch('koji_cli.commands.activate_session').start()

+         self.error_format = """Usage: %s import-comps [options] <file> <tag>

+ (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.libcomps')

-     @mock.patch('koji_cli.commands.activate_session')

      @mock.patch('koji_cli.commands._import_comps')

      @mock.patch('koji_cli.commands._import_comps_alt')

      def test_handle_import_comps_libcomps(

              self,

              mock_import_comps_alt,

              mock_import_comps,

-             mock_activate_session,

              libcomps,

              stdout):

          filename = './data/comps-example.xml'
@@ -45,39 +54,33 @@ 

          force = None

          args = [filename, tag]

          kwargs = {'force': force}

-         options = mock.MagicMock()

  

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

-         session.getTag.return_value = tag_info

+         self.session.getTag.return_value = tag_info

  

          # Run it and check immediate output

          # args: ./data/comps-example.xml, tag

          # expected: success

-         rv = handle_import_comps(options, session, args)

+         rv = handle_import_comps(self.options, self.session, args)

          actual = stdout.getvalue()

          expected = ''

          self.assertMultiLineEqual(actual, expected)

  

          # Finally, assert that things were called as we expected.

-         mock_activate_session.assert_called_once_with(session, options)

-         session.getTag.assert_called_once_with(tag)

-         mock_import_comps.assert_called_once_with(

-             session, filename, tag, kwargs)

+         self.mock_activate_session.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(tag)

+         mock_import_comps.assert_called_once_with(self.session, filename, tag, kwargs)

          mock_import_comps_alt.assert_not_called()

          self.assertNotEqual(rv, 1)

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

      @mock.patch('koji_cli.commands.libcomps', new=None)

      @mock.patch('koji_cli.commands.yumcomps', create=True)

-     @mock.patch('koji_cli.commands.activate_session')

      @mock.patch('koji_cli.commands._import_comps')

      @mock.patch('koji_cli.commands._import_comps_alt')

      def test_handle_import_comps_yumcomps(

              self,

              mock_import_comps_alt,

              mock_import_comps,

-             mock_activate_session,

              yumcomps,

              stdout):

          filename = './data/comps-example.xml'
@@ -86,140 +89,95 @@ 

          force = True

          args = ['--force', filename, tag]

          local_options = {'force': force}

-         options = mock.MagicMock()

  

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

-         session.getTag.return_value = tag_info

+         self.session.getTag.return_value = tag_info

  

          # Run it and check immediate output

          # args: --force, ./data/comps-example.xml, tag

          # expected: success

-         rv = handle_import_comps(options, session, args)

+         rv = handle_import_comps(self.options, self.session, args)

          actual = stdout.getvalue()

          expected = ''

          self.assertMultiLineEqual(actual, expected)

  

          # Finally, assert that things were called as we expected.

-         mock_activate_session.assert_called_once_with(session, options)

-         session.getTag.assert_called_once_with(tag)

+         self.mock_activate_session.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(tag)

          mock_import_comps.assert_not_called()

-         mock_import_comps_alt.assert_called_once_with(

-             session, filename, tag, local_options)

+         mock_import_comps_alt.assert_called_once_with(self.session, filename, tag, local_options)

          self.assertNotEqual(rv, 1)

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

      @mock.patch('koji_cli.commands.libcomps', new=None)

      @mock.patch('koji_cli.commands.yumcomps', new=None, create=True)

-     @mock.patch('koji_cli.commands.activate_session')

      @mock.patch('koji_cli.commands._import_comps')

      @mock.patch('koji_cli.commands._import_comps_alt')

-     def test_handle_import_comps_comps_na(

-             self,

-             mock_import_comps_alt,

-             mock_import_comps,

-             mock_activate_session,

-             stderr):

+     def test_handle_import_comps_comps_na(self, mock_import_comps_alt, mock_import_comps):

          filename = './data/comps-example.xml'

          tag = 'tag'

          tag_info = {'name': tag, 'id': 1}

          args = ['--force', filename, tag]

-         options = mock.MagicMock()

  

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

-         session.getTag.return_value = tag_info

+         self.session.getTag.return_value = tag_info

  

          # Run it and check immediate output

          # args: --force, ./data/comps-example.xml, tag

          # expected: failed, no comps available

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_comps(options, session, args)

-         self.assertExitCode(ex, 1)

-         actual = stderr.getvalue()

-         expected = 'comps module not available\n'

-         self.assertMultiLineEqual(actual, expected)

+         self.assert_system_exit(

+             handle_import_comps,

+             self.options, self.session, args,

+             stderr='comps module not available\n',

+             exit_code=1,

+             activate_session=None)

  

          # Finally, assert that things were called as we expected.

-         mock_activate_session.assert_called_once_with(session, options)

-         session.getTag.assert_called_once_with(tag)

+         self.mock_activate_session.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(tag)

          mock_import_comps.assert_not_called()

          mock_import_comps_alt.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

      @mock.patch('koji_cli.commands._import_comps')

      @mock.patch('koji_cli.commands._import_comps_alt')

-     def test_handle_import_comps_tag_not_exists(

-             self,

-             mock_import_comps_alt,

-             mock_import_comps,

-             mock_activate_session,

-             stderr):

+     def test_handle_import_comps_tag_not_exists(self, mock_import_comps_alt, mock_import_comps):

          filename = './data/comps-example.xml'

          tag = 'tag'

          tag_info = None

          args = [filename, tag]

-         options = mock.MagicMock()

  

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

-         session.getTag.return_value = tag_info

+         self.session.getTag.return_value = tag_info

  

          # Run it and check immediate output

          # args: ./data/comps-example.xml, tag

          # expected: failed: tag does not exist

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_comps(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_import_comps,

+             self.options, self.session, args,

+             stderr='No such tag: %s\n' % tag,

+             exit_code=1,

+             activate_session=None)

  

          # Finally, assert that things were called as we expected.

-         mock_activate_session.assert_called_once_with(session, options)

-         session.getTag.assert_called_once_with(tag)

+         self.mock_activate_session.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(tag)

          mock_import_comps.assert_not_called()

          mock_import_comps_alt.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._import_comps')

-     @mock.patch('koji_cli.commands._import_comps_alt')

-     def test_handle_import_comps_help(

-             self,

-             mock_import_comps_alt, mock_import_comps,

-             mock_activate_session,

-             stderr,

-             stdout):

+     def test_handle_import_comps_empty_args(self):

          args = []

-         progname = os.path.basename(sys.argv[0]) or 'koji'

-         options = mock.MagicMock()

- 

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

  

          # Run it and check immediate output

-         with self.assertRaises(SystemExit) as ex:

-             handle_import_comps(options, session, args)

-         self.assertExitCode(ex, 2)

-         actual_stdout = stdout.getvalue()

-         actual_stderr = stderr.getvalue()

-         expected_stdout = ''

-         expected_stderr = """Usage: %s import-comps [options] <file> <tag>

- (Specify the --help global option for a list of other help options)

- 

- %s: error: Incorrect number of arguments

- """ % (progname, progname)

-         self.assertMultiLineEqual(actual_stdout, expected_stdout)

-         self.assertMultiLineEqual(actual_stderr, expected_stderr)

+         self.assert_system_exit(

+             handle_import_comps,

+             self.options, self.session, args,

+             stdout='',

+             stderr=self.format_error_message('Incorrect number of arguments'),

+             exit_code=2,

+             activate_session=None)

  

          # Finally, assert that things were called as we expected.

-         mock_activate_session.assert_not_called()

-         session.getTag.assert_not_called()

-         session.getTagGroups.assert_not_called()

-         session.groupListAdd.assert_not_called()

+         self.mock_activate_session.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.getTagGroups.assert_not_called()

+         self.session.groupListAdd.assert_not_called()

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

      def _test_import_comps_libcomps(self, stdout):
@@ -297,16 +255,13 @@ 

              calls_file,

              stdout):

          tag = 'tag'

-         options = mock.MagicMock()

-         options.force = None

  

-         # Mock out the xmlrpc server

-         session = mock.MagicMock()

+         self.options.force = None

  

          # Run it and check immediate output

          # args: comps.xml, tag

          # expected: success

-         rv = method.__call__(session, comps_file, tag, options)

+         rv = method.__call__(self.session, comps_file, tag, self.options)

          expected = ''

          with open(stdout_file, 'rb') as f:

              expected = f.read().decode('ascii')
@@ -317,10 +272,10 @@ 

          for c in json.load(open(calls_file, 'rt')):

              expected.append(getattr(mock.call, c[0]).__call__(*c[1], **c[2]))

  

-         if hasattr(session, 'assertHasCalls'):

-             session.assertHasCalls(expected)

+         if hasattr(self.session, 'assertHasCalls'):

+             self.session.assertHasCalls(expected)

          else:

-             session.assert_has_calls(expected)

+             self.session.assert_has_calls(expected)

          self.assertNotEqual(rv, 1)

  

  

@@ -16,10 +16,6 @@ 

  

  

  class TestImportSIG(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def md5sum(self, message):

          md5 = hashlib.md5()

          md5.update(message.encode('utf-8'))
@@ -31,6 +27,10 @@ 

          return self.os_path_exists(filepath)

  

      def setUp(self):

+         self.maxDiff = None

+         self.options = mock.MagicMock()

+         self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

          self.custom_os_path_exists = {}

          self.os_path_exists = os.path.exists

  
@@ -81,18 +81,15 @@ 

      @mock.patch('koji.rip_rpm_sighdr')

      @mock.patch('koji.get_sigpacket_key_id')

      @mock.patch('koji.get_header_fields')

-     @mock.patch('koji_cli.commands.activate_session')

      def test_handle_import_sig(

              self,

-             activate_session_mock,

              get_header_fields_mock,

              get_sigpacket_key_id_mock,

              rip_rpm_sighdr_mock,

              stdout, stderr):

          """Test handle_import_sig function"""

          arguments = ['/path/to/bash', '/path/to/less', '/path/to/sed']

-         options = mock.MagicMock()

-         session = mock.MagicMock()

+ 

          expected = ''

          fake_sigkey = '00112233445566778899aAbBcCdDeEfF'

  
@@ -102,8 +99,7 @@ 

          self.custom_os_path_exists = dict((f, True) for f in arguments)

  

          # setup and start os.path.exists patch

-         os_path_exists_patch = mock.patch('os.path.exists',

-                                           new=self.mock_os_path_exists)

+         os_path_exists_patch = mock.patch('os.path.exists', new=self.mock_os_path_exists)

          os_path_exists_patch.start()

  

          # Case 1, Unsigned pkg test (without ----with-unsigned)
@@ -114,12 +110,12 @@ 

          get_header_fields_mock.side_effect = copy.deepcopy(self.rpm_headers)

  

          # Run

-         handle_import_sig(options, session, arguments)

+         handle_import_sig(self.options, self.session, arguments)

  

          self.assert_console_message(stdout, expected)

-         activate_session_mock.assert_called_once()

+         self.activate_session_mock.assert_called_once()

          rip_rpm_sighdr_mock.assert_not_called()

-         session.getRPM.assert_not_called()

+         self.session.getRPM.assert_not_called()

  

          # Case 2, No RPM in system

          # result: import skipped
@@ -136,14 +132,14 @@ 

  

          get_header_fields_mock.side_effect = copy.deepcopy(self.rpm_headers)

          get_sigpacket_key_id_mock.return_value = fake_sigkey

-         session.getRPM.return_value = {}

+         self.session.getRPM.return_value = {}

  

          # Run

-         handle_import_sig(options, session, arguments)

+         handle_import_sig(self.options, self.session, arguments)

  

          self.assert_console_message(stdout, expected)

          rip_rpm_sighdr_mock.assert_not_called()

-         session.queryRPMSigs.assert_not_called()

+         self.session.queryRPMSigs.assert_not_called()

  

          # Case 3, Find external repo RPM

          # result: import skipped
@@ -159,14 +155,14 @@ 

              expected += "Skipping external rpm: %(name)s-%(version)s-%(release)s.%(arch)s@%(external_repo_name)s" % data + "\n"

  

          get_header_fields_mock.side_effect = rinfo

-         session.getRPM.side_effect = rinfo

+         self.session.getRPM.side_effect = rinfo

  

          # Run

-         handle_import_sig(options, session, arguments)

+         handle_import_sig(self.options, self.session, arguments)

  

          self.assert_console_message(stdout, expected)

          rip_rpm_sighdr_mock.assert_not_called()

-         session.queryRPMSigs.assert_not_called()

+         self.session.queryRPMSigs.assert_not_called()

  

          # Case 4, has previous RPM signature

          # result: import skipped
@@ -196,12 +192,12 @@ 

              data['id'] = i + 1

  

          get_header_fields_mock.side_effect = copy.deepcopy(rinfo)

-         session.getRPM.side_effect = rinfo

+         self.session.getRPM.side_effect = rinfo

          rip_rpm_sighdr_mock.side_effect = sighdr

-         session.queryRPMSigs.side_effect = sigRpm

+         self.session.queryRPMSigs.side_effect = sigRpm

  

          # Run

-         handle_import_sig(options, session, arguments)

+         handle_import_sig(self.options, self.session, arguments)

  

          self.assert_console_message(stdout, expected)

          self.assert_console_message(stderr, expected_warn)
@@ -215,22 +211,22 @@ 

              expected += "Writing signed copy" + "\n"

  

          get_header_fields_mock.side_effect = copy.deepcopy(rinfo)

-         session.getRPM.side_effect = rinfo

+         self.session.getRPM.side_effect = rinfo

          rip_rpm_sighdr_mock.side_effect = sighdr

-         session.queryRPMSigs.side_effect = None

-         session.queryRPMSigs.return_value = []

+         self.session.queryRPMSigs.side_effect = None

+         self.session.queryRPMSigs.return_value = []

  

          # Run

-         handle_import_sig(options, session, arguments + ['--test'])

+         handle_import_sig(self.options, self.session, arguments + ['--test'])

  

          self.assert_console_message(stdout, expected)

-         session.addRPMSig.assert_not_called()

-         session.writeSignedRPM.assert_not_called()

+         self.session.addRPMSig.assert_not_called()

+         self.session.writeSignedRPM.assert_not_called()

  

          # Case 6, normal import

          # result: addRPMSig/writeSignedRPM should be called

          get_header_fields_mock.side_effect = copy.deepcopy(rinfo)

-         session.getRPM.side_effect = rinfo

+         self.session.getRPM.side_effect = rinfo

          rip_rpm_sighdr_mock.side_effect = sighdr

  

          add_sig_calls, write_sig_calls = [], []
@@ -239,36 +235,29 @@ 

              write_sig_calls.append(call(rinfo[i]['id'], fake_sigkey))

  

          # Run

-         handle_import_sig(options, session, arguments)

+         handle_import_sig(self.options, self.session, arguments)

  

          self.assert_console_message(stdout, expected)

-         session.addRPMSig.assert_has_calls(add_sig_calls)

-         session.writeSignedRPM.assert_has_calls(write_sig_calls)

+         self.session.addRPMSig.assert_has_calls(add_sig_calls)

+         self.session.writeSignedRPM.assert_has_calls(write_sig_calls)

  

          # restore os.path.exists patch

          os_path_exists_patch.stop()

  

-     @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_import_sig_sigkey_from_header_signed(

-             self,

-             activate_session_mock,

-             stdout, stderr):

+     def test_handle_import_sig_sigkey_from_header_signed(self, stdout):

          """Test sigkey computation from header-only signed rpm in handle_import_sig function"""

          data_path = os.path.abspath("tests/test_hub/data/rpms")

          arguments = [os.path.join(data_path, 'header-signed.rpm')]

          sigkey = '15f712be'

  

-         options = mock.MagicMock()

-         session = mock.MagicMock()

          expected = ''

  

          for pkg in arguments:

              expected += "Importing signature [key %s] from %s..." % (sigkey, pkg) + "\n"

              expected += "Writing signed copy" + "\n"

  

-         session.getRPM.side_effect = [

+         self.session.getRPM.side_effect = [

              {

                  'sourcepackage': 0,

                  'name': 'testpkg',
@@ -279,43 +268,32 @@ 

                  'id': 1,

              }

          ]

-         session.queryRPMSigs.side_effect = None

-         session.queryRPMSigs.return_value = []

+         self.session.queryRPMSigs.side_effect = None

+         self.session.queryRPMSigs.return_value = []

  

          # Run

-         handle_import_sig(options, session, arguments + ['--test'])

+         handle_import_sig(self.options, self.session, arguments + ['--test'])

  

          self.assert_console_message(stdout, expected)

-         session.addRPMSig.assert_not_called()

-         session.writeSignedRPM.assert_not_called()

+         self.session.addRPMSig.assert_not_called()

+         self.session.writeSignedRPM.assert_not_called()

  

      def test_handle_import_sig_argument_test(self):

          """Test handle_import_sig function without arguments"""

-         options = mock.MagicMock()

-         session = mock.MagicMock()

- 

          # Case 1. empty argument

-         expected = self.format_error_message(

-             "At least one package must be specified")

- 

          self.assert_system_exit(

              handle_import_sig,

-             options,

-             session,

-             [],

-             stderr=expected,

-             activate_session=None)

+             self.options, self.session, [],

+             stderr=self.format_error_message("At least one package must be specified"),

+             activate_session=None,

+             exit_code=2)

  

          # Case 2. File not exists test

          arguments = ['/bin/ls', '/tmp', '/path/to/file1', '/path/to/file2']

-         expected = self.format_error_message(

-             "No such file: %s" % arguments[2])

          self.assert_system_exit(

              handle_import_sig,

-             options,

-             session,

-             arguments,

-             stderr=expected,

+             self.options, self.session, arguments,

+             stderr=self.format_error_message("No such file: %s" % arguments[2]),

              activate_session=None)

  

      def test_handle_import_sig_help(self):

@@ -3,7 +3,6 @@ 

  import unittest

  

  import mock

- import six

  

  from koji_cli.commands import anon_handle_latest_build

  from . import utils
@@ -15,6 +14,8 @@ 

          self.maxDiff = None

          self.options = mock.MagicMock()

          self.session = mock.MagicMock()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.ensure_connection = mock.patch('koji_cli.commands.ensure_connection').start()

          self.tag_name = 'test-tag'

          self.pkg_name = 'test-pkg'

          self.expected_part_help = """Usage: %s latest-build [options] <tag> <package> [<package> ...]
@@ -28,58 +29,46 @@ 

  https://docs.pagure.org/koji/HOWTO/#package-organization

  (Specify the --help global option for a list of other help options)

  

- """ \

-                                   % (self.progname, self.progname)

+ """ % (self.progname, self.progname)

  

      def tearDown(self):

          mock.patch.stopall()

  

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_latest_build_without_args(self, activate_session_mock,

-                                               ensure_connection, stderr):

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_latest_build(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         actual = stderr.getvalue()

-         expected_stderr = \

-             self.expected_part_help + "%s: error: A tag name must be specified\n" % self.progname

-         self.assertMultiLineEqual(actual, expected_stderr)

-         activate_session_mock.assert_not_called()

-         ensure_connection.assert_not_called()

- 

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_latest_build_more_args(self, activate_session_mock, ensure_connection, stderr):

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_latest_build(self.options, self.session, [self.tag_name])

-         self.assertExitCode(ex, 2)

-         actual = stderr.getvalue()

-         expected_stderr = \

-             self.expected_part_help + "%s: error: A tag name and package name must " \

-                                       "be specified\n" % self.progname

-         self.assertMultiLineEqual(actual, expected_stderr)

-         activate_session_mock.assert_not_called()

-         ensure_connection.called_once()

- 

-     @mock.patch('sys.stderr', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_handle_latest_build_all_and_pkg(self, activate_session_mock, ensure_connection,

-                                              stderr):

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_latest_build(self.options, self.session,

-                                      ['--all', self.tag_name, self.pkg_name])

-         self.assertExitCode(ex, 2)

-         actual = stderr.getvalue()

-         expected_stderr = \

-             self.expected_part_help + "%s: error: A package name may not be combined " \

-                                       "with --all\n" % self.progname

-         self.assertMultiLineEqual(actual, expected_stderr)

-         activate_session_mock.assert_not_called()

-         ensure_connection.called_once()

+     def test_handle_latest_build_without_args(self):

+         expected = "%s: error: A tag name must be specified\n" % self.progname

+         self.assert_system_exit(

+             anon_handle_latest_build,

+             self.options, self.session, [],

+             stdout='',

+             stderr=self.expected_part_help + expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_not_called()

+         self.ensure_connection.assert_not_called()

+ 

+     def test_handle_latest_build_more_args(self):

+         expected = "%s: error: A tag name and package name must be specified\n" % self.progname

+         self.assert_system_exit(

+             anon_handle_latest_build,

+             self.options, self.session, [self.tag_name],

+             stdout='',

+             stderr=self.expected_part_help + expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_not_called()

+         self.ensure_connection.called_once()

+ 

+     def test_handle_latest_build_all_and_pkg(self):

+         expected = "%s: error: A package name may not be combined with --all\n" % self.progname

+         self.assert_system_exit(

+             anon_handle_latest_build,

+             self.options, self.session, ['--all', self.tag_name, self.pkg_name],

+             stdout='',

+             stderr=self.expected_part_help + expected,

+             exit_code=2,

+             activate_session=None)

+         self.activate_session_mock.assert_not_called()

+         self.ensure_connection.called_once()

  

      def test_handle_latest_build_help(self):

          self.assert_help(

file modified
+22 -25
@@ -8,29 +8,21 @@ 

  

  

  class TestListApi(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.error_format = """Usage: %s list-api [options] [method_name ...]

  (Specify the --help global option for a list of other help options)

  

  %s: error: {message}

  """ % (self.progname, self.progname)

+         self.session = mock.MagicMock()

+         self.options = mock.MagicMock()

+         self.ensure_connection = mock.patch('koji_cli.commands.ensure_connection').start()

  

      @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_anon_handle_list_api(

-             self,

-             ensure_connection_mock,

-             stdout):

+     def test_anon_handle_list_api_all_method(self, stdout):

          """Test anon_handle_list_api function"""

-         session = mock.MagicMock()

-         options = mock.MagicMock()

- 

-         # Case 1. list all methods

-         session._listapi.return_value = [

+         self.session._listapi.return_value = [

              {

                  'argdesc': '(tagInfo, **kwargs)',

                  'doc': 'Edit information for an existing tag.',
@@ -56,27 +48,32 @@ 

          expected += "editTag2(tagInfo, **kwargs)\n"

          expected += "  description: Edit information for an existing tag.\n"

          expected += "host.getID()\n"

-         anon_handle_list_api(options, session, [])

+         anon_handle_list_api(self.options, self.session, [])

          self.assert_console_message(stdout, expected)

+         self.ensure_connection.assert_called_once()

  

-         # Case 2. non-existent fake method

-         session.system.methodHelp.return_value = None

-         expected = self.format_error_message("Unknown method: non-existent-fake-method")

+     def test_anon_handle_list_api_fake_method(self):

+         """Test anon_handle_list_api function"""

+         self.session.system.methodHelp.return_value = None

          self.assert_system_exit(

              anon_handle_list_api,

-             options,

-             session,

+             self.options,

+             self.session,

              ['non-existent-fake-method'],

-             stderr=expected,

+             stderr=self.format_error_message("Unknown method: non-existent-fake-method"),

              activate_session=None)

+         self.ensure_connection.assert_called_once()

  

-         # Case 3. known method

-         session.system.methodHelp.return_value = "editTag2(tagInfo, **kwargs)\n" \

-                                           "  description: Edit information for an existing tag."

-         anon_handle_list_api(options, session, ['editTag2'])

+     @mock.patch('sys.stdout', new_callable=six.StringIO)

+     def test_anon_handle_list_api_specific_method(self, stdout):

+         """Test anon_handle_list_api function"""

+         self.session.system.methodHelp.return_value = \

+             "editTag2(tagInfo, **kwargs)\n  description: Edit information for an existing tag."

+         anon_handle_list_api(self.options, self.session, ['editTag2'])

          expected = "editTag2(tagInfo, **kwargs)\n"

          expected += "  description: Edit information for an existing tag.\n"

          self.assert_console_message(stdout, expected)

+         self.ensure_connection.assert_called_once()

  

      def test_anon_handle_list_api_help(self):

          self.assert_help(

@@ -16,32 +16,64 @@ 

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

          self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_buildroot_with_paths_option(self, stderr):

-         expected = """Usage: %s list-buildroot [options] <buildroot-id>

+         self.error_format = """Usage: %s list-buildroot [options] <buildroot-id>

  (Specify the --help global option for a list of other help options)

  

- %s: error: --paths option is deprecated and will be removed in 1.30

+ %s: error: {message}

  """ % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_buildroot(self.options, self.session, ['--paths', '1'])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

-         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_buildroot_without_args(self, stderr):

-         expected = """Usage: %s list-buildroot [options] <buildroot-id>

- (Specify the --help global option for a list of other help options)

+     def test_list_buildroot_with_paths_option(self):

+         expected = "--paths option is deprecated and will be removed in 1.30"

+         self.assert_system_exit(

+             anon_handle_list_buildroot,

+             self.options, self.session, ['--paths', '1'],

+             stderr=self.format_error_message(expected),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.listRPMs.assert_not_called()

  

- %s: error: Incorrect number of arguments

- """ % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_buildroot(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+     def test_list_buildroot_without_args(self):

+         self.assert_system_exit(

+             anon_handle_list_buildroot,

+             self.options, self.session, [],

+             stderr=self.format_error_message('Incorrect number of arguments'),

+             exit_code=2,

+             activate_session=None)

          self.ensure_connection_mock.assert_not_called()

+         self.session.listRPMs.assert_not_called()

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_buildroot_with_verbose(self, stdout):

+         expected_output = """testpackage-1.1-7.f33.noarch

+ testpkg-1.171-5.fc33.noarch [update]

+ tpkg-4.11-1.fc33.x86_64 [update]

+ """

+         list_rpms = [{'arch': 'noarch', 'is_update': True, 'nvr': 'testpkg-1.171-5.fc33'},

+                      {'arch': 'noarch', 'is_update': False, 'nvr': 'testpackage-1.1-7.f33'},

+                      {'arch': 'x86_64', 'is_update': True, 'nvr': 'tpkg-4.11-1.fc33'}]

+         self.session.listRPMs.return_value = list_rpms

+         rv = anon_handle_list_buildroot(self.options, self.session, ['--verbose', '1'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.listRPMs.assert_called_once_with(componentBuildrootID=1)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_buildroot_with_built(self, stdout):

+         expected_output = """testpackage-1.1-7.f33.x86_64

+ testpkg-1.171-5.fc33.noarch

+ tpkg-4.11-1.fc33.noarch

+ """

+         list_rpms = [{'arch': 'noarch', 'nvr': 'testpkg-1.171-5.fc33'},

+                      {'arch': 'x86_64', 'nvr': 'testpackage-1.1-7.f33'},

+                      {'arch': 'noarch', 'nvr': 'tpkg-4.11-1.fc33'}]

+         self.session.listRPMs.return_value = list_rpms

+         rv = anon_handle_list_buildroot(self.options, self.session, ['--built', '2'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.listRPMs.assert_called_once_with(buildrootID=2)

  

      def test_list_buildroot_help(self):

          self.assert_help(

file modified
+425 -188
@@ -15,279 +15,516 @@ 

          self.options.debug = False

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

          self.user_info = {'id': 1, 'name': 'kojiadmin', 'status': 0, 'usertype': 0,

                            'krb_principals': []}

+         self.owner = 'kojiadmin'

+         self.error_format = """Usage: %s list-builds [options]

+ (Specify the --help global option for a list of other help options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_without_option(self, stderr):

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Filter must be provided for list\n" % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.list_build = [

+             {'build_id': 1, 'epoch': 34, 'name': 'test-build', 'volume_id': 1,

+              'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin', 'task_id': None,

+              'release': '12', 'state': 1, 'version': '11', 'package_id': 1,

+              'source': 'test-source-1'},

+             {'build_id': 4, 'epoch': 34, 'name': 'test-build', 'volume_id': 0,

+              'nvr': 'test-build-8-12', 'owner_name': 'kojiadmin', 'task_id': 40,

+              'release': '12', 'state': 2, 'version': '8', 'package_id': 1,

+              'source': 'test-source-2'},

+             {'build_id': 2, 'epoch': 34, 'name': 'test-build', 'volume_id': 0,

+              'nvr': 'test-build-11-9', 'owner_name': 'kojitest', 'task_id': 20,

+              'release': '9', 'state': 1, 'version': '11', 'package_id': 1,

+              'source': 'test-source-3'},

+             {'build_id': 3, 'epoch': 34, 'name': 'test-build', 'volume_id': 0,

+              'nvr': 'test-build-10-12', 'owner_name': 'kojitest', 'task_id': None,

+              'release': '12', 'state': 4, 'version': '10', 'package_id': 1,

+              'source': 'test-source-4'},

+             {'build_id': 5, 'epoch': 34, 'name': 'test-zx-build', 'volume_id': 1,

+              'nvr': 'build-test-1-12', 'owner_name': 'kojiadmin', 'task_id': 50,

+              'release': '12', 'state': 4, 'version': '1', 'package_id': 2,

+              'source': 'test-source-5'}]

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_non_exist_pkg(self, stderr):

+     def test_list_buildroot_with_args(self):

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['arg'],

+             stderr=self.format_error_message('This command takes no arguments'),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_not_called()

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

+ 

+     def test_list_builds_without_option(self):

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, [],

+             stderr=self.format_error_message('Filter must be provided for list'),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

+ 

+     def test_list_builds_non_exist_pkg(self):

          pkg = 'test-pkg'

-         expected = "Usage: %s list-builds [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)

          self.session.getPackageID.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--package', pkg])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--package', pkg],

+             stderr=self.format_error_message('No such package: %s' % pkg),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_called_once_with(pkg)

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_non_exist_owner(self, stderr):

+     def test_list_builds_non_exist_owner(self):

          owner = 'test-owner'

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: No such user: %s\n" % (self.progname, self.progname, owner)

          self.session.getUser.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--owner', owner])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--owner', owner],

+             stderr=self.format_error_message('No such user: %s' % owner),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_non_exist_volume(self, stderr):

+     def test_list_builds_non_exist_volume(self):

          volume = 'test-volume'

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: No such volume: %s\n" % (self.progname, self.progname, volume)

          self.session.listVolumes.return_value = []

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--volume', volume])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--volume', volume],

+             stderr=self.format_error_message('No such volume: %s' % volume),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_called_once_with()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_invalid_state(self, stderr):

+     def test_list_builds_invalid_state(self):

          state = '6'

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Invalid state: %s\n" % (self.progname, self.progname, state)

-         self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--state', state])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--state', state],

+             stderr=self.format_error_message('Invalid state: %s' % state),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_invalid_state_string(self, stderr):

+     def test_list_builds_invalid_state_string(self):

          state = 'test-state'

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: Invalid state: %s\n" % (self.progname, self.progname, state)

-         self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--state', state])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--state', state],

+             stderr=self.format_error_message('Invalid state: %s' % state),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_builds_non_exist_build(self, stderr):

+     def test_list_builds_non_exist_build(self):

          build = 222

-         expected = "Usage: %s list-builds [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: No such build: '%s'\n" % (self.progname, self.progname, build)

          self.session.getBuild.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_builds(self.options, self.session,

-                                     ['--build', build])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--build', build],

+             stderr=self.format_error_message("No such build: '%s'" % build),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_called_once_with(build)

+         self.session.listBuilds.assert_not_called()

  

      @mock.patch('sys.stderr', new_callable=StringIO)

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_invalid_key(self, stdout, stderr):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-jx-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-ax-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-zx-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '11'}, ]

          test_key = 'test-key'

          expected_warn = "Invalid sort_key: %s." % test_key

          expected_output = """test-build-11-12                                         kojiadmin         COMPLETE

- test-jx-build-11-12                                      kojiadmin         COMPLETE

- test-ax-build-11-12                                      kojiadmin         CANCELED

- test-zx-build-11-12                                      kojiadmin         CANCELED

+ test-build-8-12                                          kojiadmin         DELETED

+ build-test-1-12                                          kojiadmin         CANCELED

  """

          self.session.getUser.return_value = self.user_info

-         self.session.listBuilds.return_value = list_build

-         rv = anon_handle_list_builds(self.options, self.session, ['--owner', 'kojiadmin',

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[1],

+                                                 self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--owner', self.owner,

                                                                    '--sort-key', test_key])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

          self.assert_console_message(stderr, "%s\n" % expected_warn)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(userID=1)

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_owner_sorted_nvr(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojiadmin',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

-         expected_output = """test-build-10-12                                         kojiadmin         CANCELED

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

  test-build-11-12                                         kojiadmin         COMPLETE

- test-build-11-9                                          kojiadmin         CANCELED

- test-build-8-12                                          kojiadmin         COMPLETE

+ test-build-8-12                                          kojiadmin         DELETED

  """

          self.session.getUser.return_value = self.user_info

-         self.session.listBuilds.return_value = list_build

-         rv = anon_handle_list_builds(self.options, self.session, ['--owner', 'kojiadmin',

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[1],

+                                                 self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--owner', self.owner,

                                                                    '--sort-key', 'nvr'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(userID=1)

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_owner_sorted_state(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojiadmin',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

          expected_output = """test-build-11-12                                         kojiadmin         COMPLETE

- test-build-8-12                                          kojiadmin         COMPLETE

- test-build-11-9                                          kojiadmin         CANCELED

- test-build-10-12                                         kojiadmin         CANCELED

+ test-build-8-12                                          kojiadmin         DELETED

+ build-test-1-12                                          kojiadmin         CANCELED

  """

          self.session.getUser.return_value = self.user_info

-         self.session.listBuilds.return_value = list_build

-         rv = anon_handle_list_builds(self.options, self.session, ['--owner', 'kojiadmin',

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[1],

+                                                 self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--owner', self.owner,

                                                                    '--sort-key', 'state'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(userID=1)

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_owner_sorted_state_nvr(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojiadmin',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

          expected_output = """test-build-11-12                                         kojiadmin         COMPLETE

- test-build-8-12                                          kojiadmin         COMPLETE

- test-build-10-12                                         kojiadmin         CANCELED

- test-build-11-9                                          kojiadmin         CANCELED

+ test-build-8-12                                          kojiadmin         DELETED

+ build-test-1-12                                          kojiadmin         CANCELED

  """

          self.session.getUser.return_value = self.user_info

-         self.session.listBuilds.return_value = list_build

-         rv = anon_handle_list_builds(self.options, self.session, ['--owner', 'kojiadmin',

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[1],

+                                                 self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--owner', self.owner,

                                                                    '--sort-key', 'state',

                                                                    '--sort-key', 'nvr'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(userID=1)

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_prefix_sorted_owner(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojitest',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojitest',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

          expected_output = """test-build-11-12                                         kojiadmin         COMPLETE

- test-build-10-12                                         kojiadmin         CANCELED

- test-build-8-12                                          kojitest          COMPLETE

- test-build-11-9                                          kojitest          CANCELED

+ test-build-8-12                                          kojiadmin         DELETED

+ build-test-1-12                                          kojiadmin         CANCELED

+ test-build-11-9                                          kojitest          COMPLETE

+ test-build-10-12                                         kojitest          CANCELED

  """

-         self.session.listBuilds.return_value = list_build

+         self.session.listBuilds.return_value = self.list_build

          rv = anon_handle_list_builds(self.options, self.session, ['--prefix', 'test-build',

                                                                    '--sort-key', 'owner_name'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(prefix='test-build')

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_prefix_sorted_owner_nvr(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojitest',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojitest',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

-         expected_output = """test-build-10-12                                         kojiadmin         CANCELED

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

  test-build-11-12                                         kojiadmin         COMPLETE

- test-build-11-9                                          kojitest          CANCELED

- test-build-8-12                                          kojitest          COMPLETE

+ test-build-8-12                                          kojiadmin         DELETED

+ test-build-10-12                                         kojitest          CANCELED

+ test-build-11-9                                          kojitest          COMPLETE

  """

-         self.session.listBuilds.return_value = list_build

+         self.session.listBuilds.return_value = self.list_build

          rv = anon_handle_list_builds(self.options, self.session, ['--prefix', 'test-build',

                                                                    '--sort-key', 'owner_name',

                                                                    '--sort-key', 'nvr'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

  

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(prefix='test-build')

+ 

      @mock.patch('sys.stdout', new_callable=StringIO)

      def test_list_builds_opt_owner_reverse(self, stdout):

-         list_build = [{'build_id': 1, 'epoch': 34, 'name': 'test-build',

-                        'nvr': 'test-build-11-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '11'},

-                       {'build_id': 4, 'epoch': 34, 'name': 'test-jx-build',

-                        'nvr': 'test-build-8-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 1, 'version': '8'},

-                       {'build_id': 2, 'epoch': 34, 'name': 'test-ax-build',

-                        'nvr': 'test-build-11-9', 'owner_name': 'kojiadmin',

-                        'release': '9', 'state': 4, 'version': '11'},

-                       {'build_id': 3, 'epoch': 34, 'name': 'test-zx-build',

-                        'nvr': 'test-build-10-12', 'owner_name': 'kojiadmin',

-                        'release': '12', 'state': 4, 'version': '10'}, ]

-         expected_output = """test-build-8-12                                          kojiadmin         COMPLETE

- test-build-11-9                                          kojiadmin         CANCELED

+         expected_output = """test-build-8-12                                          kojiadmin         DELETED

  test-build-11-12                                         kojiadmin         COMPLETE

- test-build-10-12                                         kojiadmin         CANCELED

+ build-test-1-12                                          kojiadmin         CANCELED

  """

          self.session.getUser.return_value = self.user_info

-         self.session.listBuilds.return_value = list_build

-         rv = anon_handle_list_builds(self.options, self.session, ['--owner', 'kojiadmin',

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[1],

+                                                 self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--owner', self.owner,

                                                                    '--reverse'])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(userID=1)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_opt_cg(self, stdout):

+         expected_output = """test-build-11-9                                          kojitest          COMPLETE

+ test-build-8-12                                          kojiadmin         DELETED

+ """

+         self.session.listBuilds.return_value = [self.list_build[1], self.list_build[2]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--cg', 'test-cg'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(cgID='test-cg')

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_pkg_not_int(self, stdout):

+         pkg = 'build-test'

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

+ """

+         self.session.getPackageID.return_value = 2

+         self.session.listBuilds.return_value = [self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--package', pkg])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_called_once_with(pkg)

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(packageID=2)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_pkg_int(self, stdout):

+         pkg = 2

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

+ """

+         self.session.listBuilds.return_value = [self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--package', str(pkg)])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(packageID=2)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_volume_not_int(self, stdout):

+         volume = 'test-volume'

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

+ test-build-11-12                                         kojiadmin         COMPLETE

+ """

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[4]]

+         self.session.listVolumes.return_value = [{'id': 0, 'name': 'DEFAULT'},

+                                                  {'id': 1, 'name': 'test-volume'}]

+         rv = anon_handle_list_builds(self.options, self.session, ['--volume', volume])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_called_once_with()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(volumeID=1)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_volume_int(self, stdout):

+         volume = 1

+         expected_output = """build-test-1-12                                          kojiadmin         CANCELED

+ test-build-11-12                                         kojiadmin         COMPLETE

+ """

+         self.session.listBuilds.return_value = [self.list_build[0], self.list_build[4]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--volume', volume])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(volumeID=1)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_state(self, stdout):

+         expected_output = """test-build-8-12                                          kojiadmin         DELETED

+ """

+         self.session.listBuilds.return_value = [self.list_build[1]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--state', '2'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(state=2)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_task_int(self, stdout):

+         expected_output = """test-build-11-9                                          kojitest          COMPLETE

+ """

+         self.session.listBuilds.return_value = [self.list_build[2]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--task', '20'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(taskID=20)

+ 

+     def test_list_builds_task_not_int(self):

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--task', 'task-id'],

+             stderr=self.format_error_message("Task id must be an integer"),

+             exit_code=2,

+             activate_session=None)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_not_called()

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_build_string(self, stdout):

+         expected_output = """test-build-11-9                                          kojitest          COMPLETE

+ """

+         self.session.getBuild.return_value = self.list_build[2]

+         rv = anon_handle_list_builds(self.options, self.session, ['--buildid', 'test-build-10-12'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_called_once_with('test-build-10-12')

+         self.session.listBuilds.assert_not_called()

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_builds_build_source_without_quiet(self, stdout):

+         self.options.quiet = False

+         expected_output = """Build                                                    Built by          State

+ -------------------------------------------------------  ----------------  ----------------

+ test-build-10-12                                         kojitest          CANCELED

+ """

+         self.session.listBuilds.return_value = [self.list_build[3]]

+         rv = anon_handle_list_builds(self.options, self.session, ['--source', 'test-source-4'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected_output)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(source='test-source-4')

+ 

+     def test_list_builds_pattern_option_error(self):

+         self.session.listBuilds.side_effect = koji.ParameterError("no option 'pattern'")

+         expected = "The hub doesn't support the 'pattern' argument, please try filtering " \

+                    "the result on your local instead."

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--pattern', 'pattern'],

+             stderr=self.format_error_message(expected),

+             exit_code=2,

+             activate_session=None)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(pattern='pattern')

+ 

+     def test_list_builds_cgid_option_error(self):

+         self.session.listBuilds.side_effect = koji.ParameterError("no option 'cgID'")

+         expected = "The hub doesn't support the 'cg' argument, please try filtering " \

+                    "the result on your local instead."

+         self.assert_system_exit(

+             anon_handle_list_builds,

+             self.options, self.session, ['--cg', 'test-cg'],

+             stderr=self.format_error_message(expected),

+             exit_code=2,

+             activate_session=None)

+ 

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.session.getPackageID.assert_not_called()

+         self.session.getUser.assert_not_called()

+         self.session.listVolumes.assert_not_called()

+         self.session.getBuild.assert_not_called()

+         self.session.listBuilds.assert_called_once_with(cgID='test-cg')

@@ -18,6 +18,7 @@ 

          self.options.quiet = True

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

          self.list_channels = [

              {'id': 1, 'name': 'default', 'enabled': True, 'comment': 'test-comment-1',

               'description': 'test-description-1'},
@@ -45,8 +46,7 @@ 

          ]

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_not_quiet(self, ensure_connection_mock, stdout):

+     def test_list_channels_not_quiet(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          args = []
@@ -55,51 +55,45 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = "Channel        Enabled  Ready Disbld   Load    Cap   Perc    \n" \

                     "default              3      1      0      1      6     22%\n" \

                     "test [disabled]      2      2      1      1      6     28%\n"

  

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_comment(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_comment(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          args = ['--comment']

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = 'default              3      1      0      1      6     22%   ' \

                     'test-comment-1                                    \n' \

                     'test [disabled]      2      2      1      1      6     28%   ' \

                     'test-comment-2                                    \n'

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_description(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_description(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          args = ['--description']

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = 'default              3      1      0      1      6     22%   ' \

                     'test-description-1                                \n' \

                     'test [disabled]      2      2      1      1      6     28%   ' \

                     'test-description-2                                \n'

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_comment_desc_not_quiet(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_comment_desc_not_quiet(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          args = ['--description', '--comment']
@@ -108,7 +102,6 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = "Channel        Enabled  Ready Disbld   Load    Cap   Perc    " \

                     "Description                                          " \

                     "Comment                                              \n" \
@@ -119,11 +112,10 @@ 

                     "test-description-2                                   " \

                     "test-comment-2                                    \n"

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_enabled_hub_without_enabled(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_enabled_hub_without_enabled(self, stdout):

          self.session.listChannels.side_effect = [koji.ParameterError,

                                                   self.list_channels_without_enabled]

          self.session.multiCall.return_value = self.list_hosts_mc
@@ -131,15 +123,13 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = 'default      3      1      0      1      6     22%\n' \

                     'test         2      2      1      1      6     28%\n'

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_enabled(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_enabled(self, stdout):

          list_channel_enabled = [

              {'id': 1, 'name': 'default', 'enabled': True, 'comment': 'test-comment-1',

               'description': 'test-description-1'},
@@ -157,14 +147,12 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = 'default      3      1      0      1      6     22%\n'

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_disabled(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_disabled(self, stdout):

          list_channel_disabled = [

              {'id': 2, 'name': 'test', 'enabled': False, 'comment': 'test-comment-2',

               'description': 'test-description-2'},
@@ -182,14 +170,12 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = 'test [disabled]      2      2      1      1      6     28%\n'

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_with_empty_channels(self, ensure_connection_mock, stdout):

+     def test_list_channels_with_empty_channels(self, stdout):

          list_channels = []

          list_hosts_mc = [[[]]]

          self.session.listChannels.return_value = list_channels
@@ -198,14 +184,12 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = ''

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_simple_without_quiet(self, ensure_connection_mock, stdout):

+     def test_list_channels_simple_without_quiet(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          self.options.quiet = False
@@ -214,17 +198,15 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = """Channel

  default

  test [disabled]

  """

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_channels_simple_with_quiet(self, ensure_connection_mock, stdout):

+     def test_list_channels_simple_with_quiet(self, stdout):

          self.session.listChannels.return_value = self.list_channels

          self.session.multiCall.return_value = self.list_hosts_mc

          args = ['--simple', '--quiet']
@@ -232,12 +214,11 @@ 

          anon_handle_list_channels(self.options, self.session, args)

  

          actual = stdout.getvalue()

-         print(actual)

          expected = """default

  test [disabled]

  """

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      def test_list_channels_help(self):

          self.assert_help(

@@ -17,13 +17,11 @@ 

          self.original_parser = cli.OptionParser

          cli.OptionParser = mock.MagicMock()

          self.parser = cli.OptionParser.return_value

+         self.maxDiff = None

  

      def tearDown(self):

          cli.OptionParser = self.original_parser

  

-     # Show long diffs in error output...

-     maxDiff = None

- 

      @mock.patch('sys.stdout', new_callable=six.StringIO)

      def test_list_commands(self, stdout):

          cli.list_commands()

@@ -9,15 +9,12 @@ 

  

  

  class TestListGroups(utils.CliTestCase):

- 

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

          self.session = mock.MagicMock()

          self.options = mock.MagicMock()

  

-         self.activate_session = mock.patch('koji_cli.commands.activate_session').start()

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

          self.event_from_opts = mock.patch('koji.util.eventFromOpts').start()

  

          self.error_format = """Usage: %s list-groups [options] <tag> [<group>]
@@ -29,26 +26,15 @@ 

      def tearDown(self):

          mock.patch.stopall()

  

-     @mock.patch('sys.stdout', new_callable=six.StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_anon_handle_list_groups_argument_error(

-             self,

-             ensure_connection_mock,

-             activate_session_mock,

-             stdout):

+     def test_anon_handle_list_groups_argument_error(self):

          """Test anon_handle_list_groups function"""

-         expected = self.format_error_message(

-             "Incorrect number of arguments")

          for arg in [[], ['tag', 'grp', 'etc']]:

              self.assert_system_exit(

                  anon_handle_list_groups,

-                 self.options,

-                 self.session,

-                 arg,

-                 stderr=expected,

+                 self.options, self.session, arg,

+                 stderr=self.format_error_message("Incorrect number of arguments"),

                  activate_session=None)

-             activate_session_mock.assert_not_called()

+             self.ensure_connection_mock.assert_not_called()

  

      def test_anon_handle_list_groups_list_all(self):

          self.event_from_opts.return_value = {}
@@ -164,15 +150,16 @@ 

          for group in groups:

              if query_group != '' and group['name'] != query_group:

                  continue

-             expected += "%s  [%s]" % (group['name'], tags.get(group['tag_id'], group['tag_id'])) + "\n"

+             expected += "%s  [%s]" % (group['name'], tags.get(group['tag_id'],

+                                                               group['tag_id'])) + "\n"

              for grp in group["grouplist"]:

                  grp['tag_name'] = tags.get(grp['tag_id'], grp['tag_id'])

                  expected += "  @%(name)s  [%(tag_name)s]" % grp + "\n"

              for pkg in group["packagelist"]:

                  pkg['tag_name'] = tags.get(pkg['tag_id'], pkg['tag_id'])

-                 expected += "  %(package)s: %(basearchonly)s, %(type)s  [%(tag_name)s]" % pkg + "\n"

+                 expected += "  %(package)s: %(basearchonly)s, %(type)s  [%(tag_name)s]"\

+                             % pkg + "\n"

  

-         #self.session.listTags.return_value = _list_tags

          def get_tag(tag_id, strict=False):

              self.assertFalse(strict)

              for tag in _list_tags:

@@ -12,6 +12,7 @@ 

  

  class TestListHosts(utils.CliTestCase):

      def setUp(self):

+         self.maxDiff = None

          # force locale to compare 'expect' value

          locale.setlocale(locale.LC_ALL, ('en_US', 'UTF-8'))

          self.options = mock.MagicMock()
@@ -21,6 +22,22 @@ 

          self.original_timezone = os.environ.get('TZ')

          os.environ['TZ'] = 'UTC'

          time.tzset()

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

+         self.error_format = """Usage: %s list-hosts [options]

+ (Specify the --help global option for a list of other help options)

+ 

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.list_hosts = [{'arches': 'x86_64',

+                             'capacity': 2.0,

+                             'comment': 'test-comment',

+                             'description': 'test-description',

+                             'enabled': False,

+                             'id': 1,

+                             'name': 'kojibuilder',

+                             'ready': True,

+                             'task_load': 0.0,

+                             'user_id': 2}]

  

      def tearDown(self):

          locale.resetlocale()
@@ -31,47 +48,175 @@ 

              time.tzset()

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_hosts_valid(self, ensure_connection, stdout):

+     def test_list_hosts_valid_without_quiet(self, stdout):

+         self.options.quiet = False

          host_update = 1615875554.862938

-         expected = "kojibuilder Y   Y    0.0/2.0  x86_64           " \

-                    "Tue, 16 Mar 2021 06:19:14 UTC      \n"

-         list_hosts = [{'arches': 'x86_64',

-                        'capacity': 2.0,

-                        'comment': None,

-                        'description': None,

-                        'enabled': True,

-                        'id': 1,

-                        'name': 'kojibuilder',

-                        'ready': True,

-                        'task_load': 0.0,

-                        'user_id': 2}]

+         expected = """Hostname    Enb Rdy Load/Cap  Arches           Last Update                         

+ kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC      

+ """

+ 

          self.session.getLastHostUpdate.return_value = host_update

          self.session.multiCall.return_value = [[host_update]]

-         self.session.listHosts.return_value = list_hosts

+         self.session.listHosts.return_value = self.list_hosts

          rv = anon_handle_list_hosts(self.options, self.session, [])

          self.assertEqual(rv, None)

          self.assert_console_message(stdout, expected)

          self.session.listHosts.assert_called_once_with()

-         self.session.getLastHostUpdate.assert_called_once_with(list_hosts[0]['id'], ts=True)

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_hosts_non_exist_channel(self, stderr):

+     def test_list_hosts_non_exist_channel(self):

          channel = 'test-channel'

-         expected = "Usage: %s list-hosts [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: No such channel: %s\n" % (self.progname, self.progname, channel)

          self.session.getChannel.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_hosts(self.options, self.session, ['--channel', channel])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_hosts,

+             self.options, self.session, ['--channel', channel],

+             stderr=self.format_error_message('No such channel: %s' % channel),

+             exit_code=2,

+             activate_session=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

  

      @mock.patch('sys.stderr', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_hosts_empty(self, ensure_connection, stderr):

+     def test_list_hosts_empty(self, stderr):

          expected = "No hosts found.\n"

          self.session.listHosts.return_value = []

          anon_handle_list_hosts(self.options, self.session, [])

          self.assert_console_message(stderr, expected)

          self.session.listHosts.assert_called_once_with()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_arch(self, stdout):

+         host_update = 1615875554.862938

+         expected = "kojibuilder N   Y    0.0/2.0  x86_64           " \

+                    "Tue, 16 Mar 2021 06:19:14 UTC      \n"

+ 

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--arch', 'x86_64'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(arches=['x86_64'])

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_arch_not_used(self, stdout):

+         expected = ""

+ 

+         self.session.listHosts.return_value = []

+         rv = anon_handle_list_hosts(self.options, self.session, ['--arch', 'ppc'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(arches=['ppc'])

+         self.session.getLastHostUpdate.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_ready(self, stdout):

+         host_update = None

+         expected = "kojibuilder N   Y    0.0/2.0  x86_64           " \

+                    "-                                  \n"

+ 

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--ready'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(ready=True)

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_not_ready(self, stdout):

+         expected = ""

+         self.session.listHosts.return_value = []

+         rv = anon_handle_list_hosts(self.options, self.session, ['--not-ready'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(ready=False)

+         self.session.getLastHostUpdate.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_enabled(self, stdout):

+         expected = ""

+ 

+         self.session.listHosts.return_value = []

+         rv = anon_handle_list_hosts(self.options, self.session, ['--enabled'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(enabled=True)

+         self.session.getLastHostUpdate.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_with_not_enabled(self, stdout):

+         host_update = 1615875554.862938

+         expected = "kojibuilder N   Y    0.0/2.0  x86_64           " \

+                    "Tue, 16 Mar 2021 06:19:14 UTC      \n"

+ 

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--not-enabled'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(enabled=False)

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_param_error_get_last_host_update(self, stdout):

+         host_update = 1615875554.862938

+         expected = "kojibuilder N   Y    0.0/2.0  x86_64           " \

+                    "Tue, 16 Mar 2021 06:19:14 UTC      \n"

+ 

+         self.session.getLastHostUpdate.side_effect = [koji.ParameterError, host_update]

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--ready'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with(ready=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_valid_without_quiet_description_and_comment(self, stdout):

+         self.options.quiet = False

+         host_update = 1615875554.862938

+         expected = "Hostname    Enb Rdy Load/Cap  Arches           Last Update" \

+                    "                         Description                                        " \

+                    "Comment                                            \n" \

+                    "kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC" \

+                    "       test-description                                   test-comment" \

+                    "                                      \n"

+ 

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--description', '--comment'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with()

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_hosts_valid_description_and_comment(self, stdout):

+         host_update = 1615875554.862938

+         expected = "kojibuilder N   Y    0.0/2.0  x86_64           Tue, 16 Mar 2021 06:19:14 UTC" \

+                    "       test-description                                   test-comment" \

+                    "                                      \n"

+ 

+         self.session.getLastHostUpdate.return_value = host_update

+         self.session.multiCall.return_value = [[host_update]]

+         self.session.listHosts.return_value = self.list_hosts

+         rv = anon_handle_list_hosts(self.options, self.session, ['--description', '--comment'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.listHosts.assert_called_once_with()

+         self.session.getLastHostUpdate.assert_called_once_with(self.list_hosts[0]['id'], ts=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

@@ -10,14 +10,21 @@ 

  

  class TestListNotifications(utils.CliTestCase):

      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.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

+         self.activate_session_mock = mock.patch('koji_cli.commands.activate_session').start()

+         self.error_format = """Usage: %s list-notifications [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=StringIO)

-     @mock.patch('koji_cli.commands.activate_session')

-     def test_list_notifications(self, activate_session_mock, stdout):

+     def test_list_notifications(self, stdout):

          self.session.getBuildNotifications.return_value = [

              {'id': 1, 'tag_id': 1, 'package_id': 11, 'email': 'email@test.com',

               'success_only': True},
@@ -44,17 +51,16 @@ 

  No notification blocks

  '''

  

-         self.maxDiff = None

          self.assertMultiLineEqual(actual, expected)

-         activate_session_mock.assert_called_once()

          self.session.getTag.assert_has_calls([mock.call(1), mock.call(1)])

          self.session.getPackage.assert_has_calls([mock.call(11), mock.call(11)])

          self.session.getUser.assert_not_called()

          self.session.getBuildNotifications.assert_called_once_with(None)

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.ensure_connection_mock.asset_not_called()

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_notifications_user(self, ensure_connection_mock, stdout):

+     def test_list_notifications_user(self, stdout):

          self.session.getBuildNotifications.return_value = [

              {'id': 1, 'tag_id': 1, 'package_id': 11, 'email': 'email@test.com',

               'success_only': True},
@@ -96,64 +102,59 @@ 

      12 *                         *                        

  '''

  

-         self.maxDiff = None

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

          self.session.getTag.assert_has_calls([mock.call(1), mock.call(1)])

          self.session.getPackage.assert_has_calls([mock.call(11), mock.call(11)])

          self.session.getUser.assert_called_once_with('random_name')

          self.session.getBuildNotifications.assert_called_once_with(321)

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_list_notifications_without_option(self, stderr):

-         expected = """Usage: %s list-notifications [options]

- (Specify the --help global option for a list of other help options)

- 

- %s: error: Use --user or --mine.

- """ % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_notifications(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.activate_session_mock.asset_not_called()

+ 

+     def test_handle_list_notifications_without_option(self):

+         self.assert_system_exit(

+             anon_handle_list_notifications,

+             self.options, self.session, [],

+             stderr=self.format_error_message('Use --user or --mine.'),

+             exit_code=2,

+             activate_session=None)

          self.session.getBuildNotifications.assert_not_called()

          self.session.getTag.assert_not_called()

          self.session.getPackage.assert_not_called()

          self.session.getUser.assert_not_called()

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_handle_list_notifications_with_args(self, stderr):

-         expected = """Usage: %s list-notifications [options]

- (Specify the --help global option for a list of other help options)

- 

- %s: error: This command takes no arguments

- """ % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_notifications(self.options, self.session, ['test-argument'])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.ensure_connection_mock.asset_not_called()

+         self.activate_session_mock.asset_not_called()

+ 

+     def test_handle_list_notifications_with_args(self):

+         self.assert_system_exit(

+             anon_handle_list_notifications,

+             self.options, self.session, ['test-argument'],

+             stderr=self.format_error_message('This command takes no arguments'),

+             exit_code=2,

+             activate_session=None)

          self.session.getBuildNotifications.assert_not_called()

          self.session.getTag.assert_not_called()

          self.session.getPackage.assert_not_called()

          self.session.getUser.assert_not_called()

+         self.ensure_connection_mock.asset_not_called()

+         self.activate_session_mock.asset_not_called()

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_notifications_user_non_exist_user(self, stderr):

+     def test_list_notifications_user_non_exist_user(self):

          username = 'random_name'

          self.session.getUser.return_value = None

- 

-         with self.assertRaises(SystemExit):

-             anon_handle_list_notifications(self.options, self.session,

-                                            ['--user', username])

-         actual = stderr.getvalue()

-         expected = 'No such user: %s\n' % username

-         self.assertMultiLineEqual(actual, expected)

+         self.assert_system_exit(

+             anon_handle_list_notifications,

+             self.options, self.session, ['--user', username],

+             stderr='No such user: %s\n' % username,

+             exit_code=1,

+             activate_session=None)

          self.session.getBuildNotifications.assert_not_called()

          self.session.getTag.assert_not_called()

          self.session.getPackage.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.activate_session_mock.asset_not_called()

  

      @mock.patch('sys.stdout', new_callable=StringIO)

-     @mock.patch('koji_cli.commands.ensure_connection')

-     def test_list_notifications_without_notification(self, ensure_connection_mock, stdout):

+     def test_list_notifications_without_notification(self, stdout):

          username = 'random_name'

          self.session.getUser.return_value = {'id': 321}

          self.session.getBuildNotifications.return_value = []
@@ -171,8 +172,9 @@ 

  """

          actual = stdout.getvalue()

          self.assertMultiLineEqual(actual, expected)

-         ensure_connection_mock.assert_called_once_with(self.session, self.options)

          self.session.getTag.assert_called_once_with(22)

          self.session.getPackage.assert_not_called()

          self.session.getUser.assert_called_once_with('random_name')

          self.session.getBuildNotifications.assert_called_once_with(321)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+         self.activate_session_mock.asset_not_called()

file modified
+258 -21
@@ -1,6 +1,7 @@ 

  from __future__ import absolute_import

  

  import mock

+ import copy

  from six.moves import StringIO

  

  import koji
@@ -14,27 +15,263 @@ 

          self.options.debug = False

          self.session = mock.MagicMock()

          self.session.getAPIVersion.return_value = koji.API_VERSION

+         self.ensure_connection_mock = mock.patch('koji_cli.commands.ensure_connection').start()

+         self.error_format = """Usage: %s list-pkgs [options]

+ (Specify the --help global option for a list of other help options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_list_pkgs_non_exist_tag(self, stderr):

-         tag = 'test-tag'

-         expected = "Usage: %s list-pkgs [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)

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.owner = 'test-owner'

+         self.tag = 'test-tag-2'

+         self.pkg = 'test-pkg-2'

+         self.userinfo = {'id': 1, 'krb_principals': [], 'name': self.owner,

+                          'status': 0, 'usertype': 0}

+         self.list_packages = [{'blocked': False,

+                                'extra_arches': '',

+                                'owner_id': 1,

+                                'owner_name': 'test-owner',

+                                'package_id': 1,

+                                'package_name': 'test-pkg-1',

+                                'tag_id': 1,

+                                'tag_name': 'test-tag-1'},

+                               {'blocked': True,

+                                'extra_arches': 'x86_64',

+                                'owner_id': 1,

+                                'owner_name': 'usertest',

+                                'package_id': 2,

+                                'package_name': 'test-pkg-2',

+                                'tag_id': 2,

+                                'tag_name': 'test-tag-2'}, ]

+         self.taginfo = {'arches': 'x86_64',

+                         'extra': {},

+                         'id': 2,

+                         'locked': False,

+                         'maven_include_all': False,

+                         'maven_support': False,

+                         'name': 'test-tag-2',

+                         'perm': None,

+                         'perm_id': None}

+ 

+     def test_list_pkgs_non_exist_tag(self):

          self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_pkgs(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_list_pkgs_non_exist_owner(self, stderr):

-         owner = 'test-owner'

-         expected = "Usage: %s list-pkgs [options]\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: No such user: %s\n" % (self.progname, self.progname, owner)

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['--tag', self.tag],

+             stderr=self.format_error_message("No such tag: %s" % self.tag),

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getUser.assert_not_called()

+         self.session.listPackages.assert_not_called()

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     def test_list_pkgs_non_exist_owner(self):

          self.session.getUser.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             anon_handle_list_pkgs(self.options, self.session, ['--owner', owner])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['--owner', self.owner],

+             stderr=self.format_error_message("No such user: %s" % self.owner),

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.listPackages.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     def test_list_pkgs_argument_error(self):

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['arg'],

+             stderr=self.format_error_message("This command takes no arguments"),

+             activate_session=None)

+         self.ensure_connection_mock.assert_not_called()

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_with_owner_without_quiet(self, stdout):

+         self.options.quiet = False

+         expected = """Package                 Tag                     Extra Arches     Owner          

+ ----------------------- ----------------------- ---------------- ---------------

+ test-pkg-1              test-tag-1                               test-owner     

+ """

+         self.session.getUser.return_value = self.userinfo

+         self.session.listPackages.return_value = [self.list_packages[0]]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--owner', self.owner])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_called_once_with(inherited=True, userID=1,

+                                                           with_dups=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_with_tag_and_pkg_without_quiet_with_blocked(self, stdout):

+         self.options.quiet = False

+         expected = """Package                 Tag                     Extra Arches     Owner          

+ ----------------------- ----------------------- ---------------- ---------------

+ test-pkg-2              test-tag-2              x86_64           usertest        [BLOCKED]

+ """

+         self.session.getTag.return_value = self.taginfo

+         self.session.listPackages.return_value = [self.list_packages[1]]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--tag', self.tag,

+                                                                 '--package', self.pkg,

+                                                                 '--show-blocked'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.listPackages.assert_called_once_with(inherited=True, tagID=2, pkgID=self.pkg,

+                                                           with_blocked=True, with_dups=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_with_tag_and_pkg_without_quiet_with_blocked_extra_arch_none(self, stdout):

+         self.options.quiet = False

+         list_packages = copy.deepcopy(self.list_packages)

+         list_packages[1]['extra_arches'] = None

+         expected = """Package                 Tag                     Extra Arches     Owner          

+ ----------------------- ----------------------- ---------------- ---------------

+ test-pkg-2              test-tag-2                               usertest        [BLOCKED]

+ """

+         self.session.getTag.return_value = self.taginfo

+         self.session.listPackages.return_value = [list_packages[1]]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--tag', self.tag,

+                                                                 '--package', self.pkg,

+                                                                 '--show-blocked'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.listPackages.assert_called_once_with(inherited=True, tagID=2, pkgID=self.pkg,

+                                                           with_blocked=True, with_dups=None)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_with_pkg_without_quiet_with_blocked_tag_not_in_pkg(self, stdout):

+         self.options.quiet = False

+         list_packages = copy.deepcopy(self.list_packages)

+         del list_packages[1]['tag_id']

+         del list_packages[1]['tag_name']

+         expected = """Package                 Tag                     Extra Arches     Owner          

+ ----------------------- ----------------------- ---------------- ---------------

+ test-pkg-2

+ """

+         self.session.listPackages.return_value = [list_packages[1]]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--package', self.pkg,

+                                                                 '--show-blocked'])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_called_once_with(inherited=True, pkgID=self.pkg,

+                                                           with_blocked=True, with_dups=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_without_options(self, stdout):

+         expected = """test-pkg-1

+ test-pkg-2

+ """

+         self.session.listPackages.return_value = self.list_packages

+         rv = anon_handle_list_pkgs(self.options, self.session, [])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_called_once_with(inherited=True, with_dups=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_not_quiet(self, stdout):

+         self.options.quiet = False

+         expected = """Package

+ -----------------------

+ test-pkg-1

+ test-pkg-2

+ """

+         self.session.listPackages.return_value = self.list_packages

+         rv = anon_handle_list_pkgs(self.options, self.session, [])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_called_once_with(inherited=True, with_dups=True)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     def test_list_pkgs_no_pkg(self):

+         self.session.listPackages.return_value = []

+         self.session.getTag.return_value = self.taginfo

+         self.session.getUser.return_value = self.userinfo

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['--tag', self.tag, '--owner', self.owner],

+             stderr="(no matching packages)\n",

+             activate_session=None,

+             exit_code=1

+         )

+         self.session.getUser.assert_called_once_with(self.owner)

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.listPackages.assert_called_once_with(inherited=True, with_dups=None,

+                                                           tagID=2, userID=1)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_without_blocked_empty_result(self, stdout):

+         expected = ""

+         self.session.getTag.return_value = self.taginfo

+         self.session.listPackages.return_value = [self.list_packages[1]]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--tag', self.tag])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.listPackages.assert_called_once_with(inherited=True, with_dups=None, tagID=2)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('sys.stdout', new_callable=StringIO)

+     def test_list_pkgs_param_error(self, stdout):

+         expected = """test-pkg-1              test-tag-1                               test-owner     

+ test-pkg-2              test-tag-2              x86_64           usertest        [BLOCKED]

+ """

+         self.session.getTag.return_value = self.taginfo

+         self.session.listPackages.side_effect = [koji.ParameterError, self.list_packages]

+         rv = anon_handle_list_pkgs(self.options, self.session, ['--show-blocked',

+                                                                 '--tag', self.tag])

+         self.assertEqual(rv, None)

+         self.assert_console_message(stdout, expected)

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     def test_list_pkgs_blocked_without_option(self):

+         expected = '--show-blocked makes sense only with --tag, --owner or --package'

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['--show-blocked'],

+             stderr=self.format_error_message(expected),

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

+ 

+     @mock.patch('koji.util.eventFromOpts', return_value={'id': 1000,

+                                                          'ts': 1000000.11})

+     def test_list_pkgs_event_without_option(self, event_from_opts):

+         expected = '--event and --ts makes sense only with --tag, --owner or --package'

+         self.assert_system_exit(

+             anon_handle_list_pkgs,

+             self.options, self.session, ['--event', '1000'],

+             stderr=self.format_error_message(expected),

+             stdout='Querying at event 1000 (Mon Jan 12 13:46:40 1970)\n',

+             activate_session=None,

+             exit_code=2

+         )

+         self.session.getUser.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.listPackages.assert_not_called()

+         self.ensure_connection_mock.assert_called_once_with(self.session, self.options)

@@ -1,7 +1,7 @@ 

  from __future__ import absolute_import

  

  import mock

- from six.moves import StringIO

+ from mock import call

  

  import koji

  from koji_cli.commands import handle_remove_tag_inheritance
@@ -14,35 +14,24 @@ 

          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-tag-inheritance <tag> <parent> <priority>

+ (Specify the --help global option for a list of other help options)

  

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_remove_tag_inheritance_without_option(self, stderr):

-         expected = "Usage: %s remove-tag-inheritance <tag> <parent> <priority>\n" \

-                    "(Specify the --help global option for a list of other help options)\n\n" \

-                    "%s: error: This command takes at least one argument: " \

-                    "a tag name or ID\n" % (self.progname, self.progname)

-         with self.assertRaises(SystemExit) as ex:

-             handle_remove_tag_inheritance(self.options, self.session, [])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_remove_tag_inheritance_non_exist_tag(self, stderr):

-         tag = 'test-tag'

-         parent_tag = 'parent-test-tag'

-         priority = '99'

-         expected = "Usage: %s remove-tag-inheritance <tag> <parent> <priority>\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)

-         self.session.getTag.return_value = None

-         with self.assertRaises(SystemExit) as ex:

-             handle_remove_tag_inheritance(self.options, self.session, [tag, parent_tag, priority])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

- 

-     @mock.patch('sys.stderr', new_callable=StringIO)

-     def test_remove_tag_inheritance_non_exist_parent_tag(self, stderr):

-         side_effect_result = [{'arches': 'x86_64',

+ %s: error: {message}

+ """ % (self.progname, self.progname)

+         self.tag = 'test-tag'

+         self.parent_tag = 'parent-test-tag'

+         self.priority = '99'

+         self.tag_inheritance = {'child_id': 1,

+                                 'intransitive': False,

+                                 'maxdepth': None,

+                                 'name': self.tag,

+                                 'noconfig': False,

+                                 'parent_id': 2,

+                                 'pkg_filter': '',

+                                 'priority': self.priority}

+         self.child_tag_info = {'arches': 'x86_64',

                                 'extra': {},

                                 'id': 1,

                                 'locked': False,
@@ -50,16 +39,172 @@ 

                                 'maven_support': False,

                                 'name': 'test-tag',

                                 'perm': None,

-                                'perm_id': None},

-                               None]

-         tag = 'test-tag'

-         parent_tag = 'parent-test-tag'

-         priority = '99'

-         expected = "Usage: %s remove-tag-inheritance <tag> <parent> <priority>\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)

-         self.session.getTag.side_effect = side_effect_result

-         with self.assertRaises(SystemExit) as ex:

-             handle_remove_tag_inheritance(self.options, self.session, [tag, parent_tag, priority])

-         self.assertExitCode(ex, 2)

-         self.assert_console_message(stderr, expected)

+                                'perm_id': None}

+         self.parent_tag_info = {'arches': 'x86_64',

+                                 'extra': {},

+                                 'id': 2,

+                                 'locked': False,

+                                 'maven_include_all': False,

+                                 'maven_support': False,

+                                 'name': 'parent-test-tag',

+                                 'perm': None,

+                                 'perm_id': None}

+ 

+     def test_remove_tag_inheritance_without_option(self):

+         expected = self.format_error_message(

+             "This command takes at least one argument: a tag name or ID")

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_more_arguments(self):

+         expected = self.format_error_message(

+             "This command takes at most three argument: a tag name or ID, "

+             "a parent tag name or ID, and a priority")

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             ['arg1', 'arg2', 'arg3', 'arg4'],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_not_called()

+         self.session.getTag.assert_not_called()

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_non_exist_tag(self):

+         self.session.getTag.return_value = None

+         expected = self.format_error_message("No such tag: %s" % self.tag)

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_non_exist_parent_tag(self):

+         self.session.getTag.side_effect = [self.child_tag_info, None]

+         expected = self.format_error_message("No such tag: %s" % self.parent_tag)

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr=expected,

+             activate_session=None,

+             exit_code=2

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_not_called()

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_non_exist_inheritance(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = []

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='',

+             stderr='No inheritance link found to remove.  Please check your arguments\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_multi_inheritance_without_parent(self):

+         self.session.getTag.return_value = self.child_tag_info

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag],

+             stdout='Multiple matches for tag.\n',

+             stderr='Please specify a parent on the command line.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_called_once_with(self.tag)

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_multi_inheritance_without_priority(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag],

+             stdout='Multiple matches for tag.\n',

+             stderr='Please specify a priority on the command line.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_multi_inheritance(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.return_value = [self.tag_inheritance, self.tag_inheritance]

+         self.assert_system_exit(

+             handle_remove_tag_inheritance,

+             self.options,

+             self.session,

+             [self.tag, self.parent_tag, self.priority],

+             stdout='Multiple matches for tag.\n',

+             stderr='Error: Key constraints may be broken.  Exiting.\n',

+             activate_session=None,

+             exit_code=1

+         )

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_called_once_with(1)

+         self.session.setInheritanceData.assert_not_called()

+ 

+     def test_remove_tag_inheritance_valid(self):

+         self.session.getTag.side_effect = [self.child_tag_info, self.parent_tag_info]

+         self.session.getInheritanceData.side_effect = [[self.tag_inheritance],

+                                                        [self.tag_inheritance]]

+         handle_remove_tag_inheritance(self.options, self.session,

+                                       [self.tag, self.parent_tag, self.priority])

+         self.activate_session_mock.assert_called_once_with(self.session, self.options)

+         self.session.getTag.assert_has_calls([call(self.tag), call(self.parent_tag)])

+         self.session.getInheritanceData.assert_has_calls([call(1), call(1)])

+         self.session.setInheritanceData.assert_called_once_with(

+             1, [{'child_id': 1, 'intransitive': False, 'maxdepth': None, 'name': self.tag,

+                  'noconfig': False, 'parent_id': 2, 'pkg_filter': '', 'priority': self.priority,

+                  'delete link': True}])

no initial comment

rebased onto 513c619a0c82a18c386226be737bd70717077169

2 years ago

rebased onto 5289156

2 years ago

Commit 1a71dce fixes this pull-request

Pull-Request has been merged by tkopecek

2 years ago
Metadata
Changes Summary 39
+22 -22
file changed
tests/test_cli/test_clone_tag.py
+38 -42
file changed
tests/test_cli/test_disable_channel.py
+48 -63
file changed
tests/test_cli/test_disable_host.py
+26 -22
file changed
tests/test_cli/test_disable_user.py
+106 -38
file changed
tests/test_cli/test_download_build.py
+64 -51
file changed
tests/test_cli/test_edit_channel.py
+14 -9
file changed
tests/test_cli/test_edit_external_repo.py
+110 -142
file changed
tests/test_cli/test_edit_host.py
+101 -61
file changed
tests/test_cli/test_edit_notification.py
+8 -4
file changed
tests/test_cli/test_edit_permission.py
+97 -95
file changed
tests/test_cli/test_edit_tag.py
+246 -44
file changed
tests/test_cli/test_edit_tag_inheritance.py
+103 -72
file changed
tests/test_cli/test_edit_target.py
+58 -98
file changed
tests/test_cli/test_edit_user.py
+37 -41
file changed
tests/test_cli/test_enable_channel.py
+46 -59
file changed
tests/test_cli/test_enable_host.py
+26 -29
file changed
tests/test_cli/test_enable_user.py
+24 -17
file changed
tests/test_cli/test_free_task.py
+37 -35
file changed
tests/test_cli/test_grant_cg_access.py
+37 -35
file changed
tests/test_cli/test_hello.py
+74 -32
file changed
tests/test_cli/test_hostinfo.py
+60 -71
file changed
tests/test_cli/test_image_build.py
+2 -8
file changed
tests/test_cli/test_image_build_indirection.py
+4 -5
file changed
tests/test_cli/test_import.py
+153 -76
file changed
tests/test_cli/test_import_archive.py
+36 -59
file changed
tests/test_cli/test_import_cg.py
+60 -105
file changed
tests/test_cli/test_import_comps.py
+41 -63
file changed
tests/test_cli/test_import_sig.py
+38 -49
file changed
tests/test_cli/test_latest_build.py
+22 -25
file changed
tests/test_cli/test_list_api.py
+52 -20
file changed
tests/test_cli/test_list_buildroot.py
+425 -188
file changed
tests/test_cli/test_list_builds.py
+21 -40
file changed
tests/test_cli/test_list_channels.py
+1 -3
file changed
tests/test_cli/test_list_commands.py
+10 -23
file changed
tests/test_cli/test_list_groups.py
+172 -27
file changed
tests/test_cli/test_list_hosts.py
+46 -44
file changed
tests/test_cli/test_list_notifications.py
+258 -21
file changed
tests/test_cli/test_list_pkgs.py
+187 -42
file changed
tests/test_cli/test_remove_tag_inheritance.py