#3771 prune-signed-copies unit tests
Merged a year ago by tkopecek. Opened a year ago by jcupova.

prune-signed-copies unit tests
Jana Cupova • a year ago  
@@ -1,6 +1,10 @@ 

  from __future__ import absolute_import

  

+ import koji

  import mock

+ import os

+ import six

+ import time

  

  from koji_cli.commands import handle_prune_signed_copies

  from . import utils
@@ -8,11 +12,29 @@ 

  

  class TestPruneSignedCopies(utils.CliTestCase):

  

-     # Show long diffs in error output...

-     maxDiff = None

- 

      def setUp(self):

+         self.maxDiff = None

+         self.original_timezone = os.environ.get('TZ')

+         os.environ['TZ'] = 'US/Eastern'

+         time.tzset()

+         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 prune-signed-copies [options]

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

+ 

+ %s: error: {message}

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

+ 

+     def tearDown(self):

+         if self.original_timezone is None:

+             del os.environ['TZ']

+         else:

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

+         time.tzset()

+         mock.patch.stopall()

  

      def test_handle_prune_signed_copies_help(self):

          self.assert_help(
@@ -41,3 +63,670 @@ 

    --trashcan-tag=TRASHCAN_TAG

                          Specify trashcan tag

  """ % self.progname)

+ 

+     def test_handle_prune_signes_copies_non_exist_build(self):

+         build_id = '123'

+         arguments = ['--build', build_id]

+         self.session.getBuild.return_value = None

+         self.assert_system_exit(

+             handle_prune_signed_copies,

+             self.options, self.session, arguments,

+             stdout='',

+             stderr=self.format_error_message("No such build: %s" % build_id),

+             exit_code=2,

+             activate_session=None)

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

+         self.session.getBuild.assert_called_once_with(build_id)

+ 

+     @mock.patch('time.asctime', return_value='Sat Apr  1 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_with_package_verbose_debug(

+             self, stdout, pathinfobuild, timeasctime):

+         """Returns info about 1 build, 4 tags, 0 files, 0 bytes and ignoring trashcan tag,

+         ignored tag and info about protected tag"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name', '--trashcan-tag', 'test-tag1',

+                      '--protect-tag', 'test-tag3', '--ignore-tag', 'test-tag2']

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [[{'build_id': 1, 'nvr': 'package-name-1.3-4',

+                                                  'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'},

+                              {'tag.name': 'test-tag3'}, {'tag.name': 'test-tag4'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': None, 'tag_name': 'test-tag4', 'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag3',

+                               'version': '1.3'}]}]

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  1 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2', 'test-tag3', 'test-tag4']

+ Ignoring trashcan tag for build package-name-1.3-4

+ Ignoring tag test-tag2 for build package-name-1.3-4

+ Sat Apr  1 14:08:17 2023: Tagged package-name-1.3-4 with test-tag3 [still active]

+ Build package-name-1.3-4 had protected tag test-tag3 until Sat Apr  1 14:08:17 2023

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('time.asctime', return_value='Sat Apr  1 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_latest_tag(self, stdout, pathinfobuild, timeasctime):

+         """Returns prune signed copies info with package latest tag"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': None, 'tag_name': 'test-tag1', 'version': '1.3'}]}]

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  1 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  1 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ package-name-1.3-4 is latest in tag test-tag1

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('time.asctime', return_value='Sat Apr  1 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_cutoff_package(self, stdout, pathinfobuild, timeasctime):

+         """Returns prune signed copies info with cutoff package"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]}]

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  1 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  1 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  1 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  1 14:08:17 2023)

+ package-name-1.3-4 was latest past the cutoff

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     def __vm(self, result):

+         m = koji.VirtualCall('mcall_method', [], {})

+         if isinstance(result, dict) and result.get('faultCode'):

+             m._result = result

+         else:

+             m._result = (result,)

+         return m

+ 

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_without_signatures(

+             self, stdout, pathinfobuild, timeasctime, timetime):

+         """Returns prune signed copies info without signatures"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}]

+         self.session.listRPMs.return_value = list_rpms

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

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ (build has no signatures)

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_not_regular_file(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg):

+         """Returns prune signed copies info without regular file info"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}

+         ]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1683191826

+         lstat.return_value = stat

+         isreg.return_value = False

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Skipping fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm. Not a regular file

+ (build has no signed copies)

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_file_newer(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg):

+         """Returns prune signed copies info with file newer info"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}

+         ]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1683191826

+         lstat.return_value = stat

+         isreg.return_value = True

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Skipping fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm. File newer than cutoff

+ (build has no signed copies)

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_with_test(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg):

+         """Returns prune signed copies info with test option"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name', '--test']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}

+         ]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1681191826

+         lstat.return_value = stat

+         isreg.return_value = True

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Would have unlinked: fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm

+ Would have removed dir: fakebuildpath/data/signed/qwertyuiop/test-arch

+ Would have removed dir: fakebuildpath/data/signed/qwertyuiop

+ Build: package-name-1.3-4, Removed 1 signed copies (1 bytes). Total: 1/1

+ --- Grand Totals ---

+ Files: 1

+ Bytes: 1

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('os.unlink', return_value=None)

+     @mock.patch('os.rmdir', return_value=None)

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_with_verbose_removing(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg, rmdir, unlink):

+         """Returns prune signed copies info with verbose option and removing files/dirs"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1681191826

+         lstat.return_value = stat

+         isreg.return_value = True

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Unlinking: fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm

+ Removing dir: fakebuildpath/data/signed/qwertyuiop/test-arch

+ Removing dir: fakebuildpath/data/signed/qwertyuiop

+ Build: package-name-1.3-4, Removed 1 signed copies (1 bytes). Total: 1/1

+ --- Grand Totals ---

+ Files: 1

+ Bytes: 1

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_unlink_perms_error(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg):

+         """Returns prune signed copies info with unlink perms error"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}

+         ]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1681191826

+         lstat.return_value = stat

+         isreg.return_value = True

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Unlinking: fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm

+ Error removing fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm: [Errno 2] No such file or directory: 'fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm'

+ This script needs write access to /mnt/koji

+ (build has no signed copies)

+ --- Grand Totals ---

+ Files: 0

+ Bytes: 0

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('os.unlink', return_value=None)

+     @mock.patch('stat.S_ISREG')

+     @mock.patch('os.lstat')

+     @mock.patch('time.time', return_value=1682063424)

+     @mock.patch('time.asctime', return_value='Sat Apr  20 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_error_removing(

+             self, stdout, pathinfobuild, timeasctime, timetime, lstat, isreg, unlink):

+         """Returns prune signed copies info with removing error"""

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         list_rpms = [{'id': 123, 'name': 'test', 'version': '1.3', 'release': 1,

+                       'arch': 'test-arch', 'external_repo_name': 'ext-repo',

+                       'external_repo_id': 456, 'build_id': 1}]

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3-4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag1',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag1',

+                               'version': '1.3'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': 11,

+                               'create_ts': 1681191826, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 22, 'revoke_ts': 1681191836, 'tag_name': 'test-tag2',

+                               'version': '1.3'},

+                              {'active': True, 'build_id': 1, 'create_event': 33,

+                               'create_ts': 1681191846, 'name': 'package-name', 'release': '4',

+                               'revoke_event': 44, 'revoke_ts': 1681191856, 'tag_name': 'test-tag2',

+                               'version': '1.3'}]}

+         ]

+         self.session.listRPMs.return_value = list_rpms

+         sigRpm = [[[{'rpm_id': 123, 'sigkey': 'qwertyuiop'}]]]

+         self.session.multiCall.return_value = sigRpm

+         stat = mock.MagicMock()

+         stat.st_mode = 'mode'

+         stat.st_mtime = 1681191826

+         lstat.return_value = stat

+         isreg.return_value = True

+         rv = handle_prune_signed_copies(self.options, self.session, arguments)

+         actual = stdout.getvalue()

+         expected = """Cutoff date: Sat Apr  20 14:08:17 2023

+ Getting builds...

+ ...got 1 builds

+ DEBUG: package-name-1.3-4

+ Tags: ['test-tag1', 'test-tag2']

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag1 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag1

+ tag test-tag1: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Sat Apr  20 14:08:17 2023: Tagged package-name-1.3-4 with test-tag2 [still active]

+ Sat Apr  20 14:08:17 2023: Untagged package-name-1.3-4 from test-tag2

+ tag test-tag2: package-name-1.3-4 not latest (revoked Sat Apr  20 14:08:17 2023)

+ Unlinking: fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm

+ Removing dir: fakebuildpath/data/signed/qwertyuiop/test-arch

+ Error removing fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm: [Errno 2] No such file or directory: 'fakebuildpath/data/signed/qwertyuiop/test-arch'

+ Removing dir: fakebuildpath/data/signed/qwertyuiop

+ Error removing fakebuildpath/data/signed/qwertyuiop/test-arch/test-1.3-1.test-arch.rpm: [Errno 2] No such file or directory: 'fakebuildpath/data/signed/qwertyuiop'

+ Build: package-name-1.3-4, Removed 1 signed copies (1 bytes). Total: 1/1

+ --- Grand Totals ---

+ Files: 1

+ Bytes: 1

+ """

+         self.assertMultiLineEqual(actual, expected)

+         self.assertNotEqual(rv, 1)

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     @mock.patch('time.asctime', return_value='Sat Apr  1 14:08:17 2023')

+     @mock.patch('koji.pathinfo.build', return_value='fakebuildpath')

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

+     def test_handle_prune_signes_copies_not_create_event(self, stdout, pathinfobuild, timeasctime):

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3.4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': [{'active': True, 'build_id': 1, 'create_event': None,

+                               'create_ts': None, 'name': 'package-name', 'release': '4',

+                               'revoke_event': None, 'revoke_ts': None, 'tag_name': 'test-tag1',

+                               'version': '3'}]}]

+ 

+         with self.assertRaises(koji.GenericError) as ex:

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

+         self.assertEqual(str(ex.exception),

+                          "No creation event found for package-name-1.3.4 in test-tag1")

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

+ 

+     def test_handle_prune_signes_copies_without_pkg_tag_history(self):

+         self.options.debug = True

+         arguments = ['--verbose', '--package', 'package-name']

+         self.session.getPackage.return_value = {'id': 135, 'name': 'package-name'}

+         self.session.listBuilds.side_effect = [

+             [{'build_id': 1, 'nvr': 'package-name-1.3.4', 'package_name': 'package-name'}], []]

+         self.session.queryHistory.side_effect = [

+             {'tag_listing': [{'tag.name': 'test-tag1'}, {'tag.name': 'test-tag2'}]},

+             {'tag_listing': []}]

+ 

+         with self.assertRaises(koji.GenericError) as ex:

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

+         self.assertEqual(str(ex.exception), "No history found for package-name-1.3.4 in test-tag1")

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

+         self.session.getBuild.assert_not_called()

+         self.session.getPackage.assert_called_once_with('package-name')

Commit 650a149 fixes this pull-request

Pull-Request has been merged by tkopecek

a year ago
Metadata