From 8d0ef68bfa9c93d3016c3a7da9538794b50ea404 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Aug 28 2024 13:54:17 +0000 Subject: Basic tests for kiwi plugin Related: https://pagure.io/koji/issue/4179 --- diff --git a/tests/test_builder/test_taskparams.py b/tests/test_builder/test_taskparams.py index a21a103..701df02 100644 --- a/tests/test_builder/test_taskparams.py +++ b/tests/test_builder/test_taskparams.py @@ -63,7 +63,8 @@ class TestParseTaskParams(unittest.TestCase): # match self.assertIn(list(spec), koji.tasks.LEGACY_SIGNATURES[method]) - external = ['runroot', 'saveFailedTree', 'vmExec', 'winbuild'] + external = ['runroot', 'saveFailedTree', 'vmExec', 'winbuild', + 'kiwiBuild', 'createKiwiImage'] missing = [m for m in missing if m not in external] if missing: raise Exception('Unable to test legacy signatures. Missing: ' diff --git a/tests/test_plugins/test_kiwi_builder.py b/tests/test_plugins/test_kiwi_builder.py new file mode 100644 index 0000000..2278ece --- /dev/null +++ b/tests/test_plugins/test_kiwi_builder.py @@ -0,0 +1,228 @@ +import mock +import tempfile +import unittest + +import koji +# inject builder data +from tests.test_builder.loadkojid import kojid +import __main__ +__main__.BuildRoot = kojid.BuildRoot +__main__.BaseBuildTask = kojid.BaseBuildTask +__main__.BuildImageTask = kojid.BuildImageTask +__main__.SCM = kojid.SCM + +from plugins.builder import kiwi + + +class TestKiwiBuildTask(unittest.TestCase): + def SCM(self, *args, **kwargs): + scm = mock.MagicMock() + scm.assert_allowed = mock.MagicMock() + self.scm.append(scm) + return scm + + def setUp(self): + self.scm = [] + self.session = mock.MagicMock() + self.options = mock.MagicMock() + self.options.allowed_scms = 'allowed_scms' + self.options.allowed_scms_use_config = False + self.options.allowed_scms_use_policy = True + kiwi.SCM = mock.MagicMock(side_effect=self.SCM) + koji.ensuredir = mock.MagicMock() + self.task = kiwi.KiwiBuildTask(123, 'kiwiBuild', {}, self.session, self.options) + + def test_get_nrvp_invalid_xml(self): + # missing file + with self.assertRaises(koji.GenericError): + self.task.get_nvrp('/dev/null/non_existent_path') + + # empty file + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + fp.write(b'') + fp.close() + with self.assertRaises(koji.GenericError): + self.task.get_nvrp(fp.name) + + # empty xml + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + fp.write(b'') + fp.close() + with self.assertRaises(koji.GenericError): + self.task.get_nvrp(fp.name) + + def test_get_nrvp_correct(self): + # minimal correct xml + with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: + fp.write(b''' + + + + + + 1.0.0 + + + ''') + fp.close() + name, version, profile = self.task.get_nvrp(fp.name) + self.assertEqual(name, 'Fedora-34.0_disk') + self.assertEqual(version, '1.0.0') + self.assertEqual(profile, 'Base') + + def test_handler_correct(self, arches=None): + if arches is None: + arches = ['arch1', 'arch2'] + self.session.getBuildTarget.return_value = { + 'id': 1, + 'name': 'target', + 'build_tag': 123, + 'build_tag_name': 'build_tag', + 'dest_tag': 321, + 'dest_tag_name': 'dest_tag' + } + self.task.getRepo = mock.MagicMock() + self.task.getRepo.return_value = { + 'create_event': 59911321, + 'create_ts': 1724763098.15199, + 'creation_time': '2024-08-27 12:51:38.151991', + 'dist': False, + 'id': 8561958, + 'state': 1, + 'task_id': 63698179 + } + self.session.getBuildConfig.return_value = { + 'arches': 'arch1 arch2', + 'id': 1234, + 'extra': {}, + } + self.task.run_callbacks = mock.MagicMock() + self.task.initImageBuild = mock.MagicMock() + self.task.initImageBuild.return_value = { + 'id': 98, + 'name': 'image_name', + 'version': 'image_version', + 'release': 'image_release', + } + self.task.get_nvrp = mock.MagicMock() + self.task.get_nvrp.return_value = 'name', 'version', 'profile' + self.task.wait = mock.MagicMock() + self.task.wait.return_value = { + 1: 'correct result' + } + self.session.getChannel.return_value = {'name': 'channel_id'} + self.session.getTaskInfo.return_value = { + 'owner': 'owner_id', + 'channel_id': 'channel_id', + } + self.session.getNextRelease.return_value = 'next_release' + + result = self.task.handler('target', arches, + 'git://desc.server/repo#fragment', 'desc_path') + + # test scm.assert_allowed inputs + scm = self.scm[0] + scm.assert_allowed.assert_called_once_with( + allowed=self.options.allowed_scms, + session=self.session, + by_config=self.options.allowed_scms_use_config, + by_policy=self.options.allowed_scms_use_policy, + policy_data={ + 'user_id': 'owner_id', + 'channel': 'channel_id', + 'scratch': False, + }) + + self.task.run_callbacks.assert_has_calls([ + mock.call( + 'preSCMCheckout', + scminfo=scm.get_info(), + build_tag=123, + scratch=False, + ), + mock.call( + 'postSCMCheckout', + scminfo=scm.get_info(), + build_tag=123, + scratch=False, + srcdir=scm.checkout() + ) + ]) + + # subtasks + self.session.host.subtask.assert_has_calls([ + mock.call( + method='createKiwiImage', + arglist=[ + 'name-profile', + 'version', + 'image_release', + 'arch1', + self.session.getBuildTarget.return_value, + 123, + self.task.getRepo.return_value, + 'git://desc.server/repo#fragment', + 'desc_path', + { + 'scratch': False, + 'optional_arches': [], + } + ], + label='arch1', + parent=123, + arch='arch1', + ), + mock.call( + method='createKiwiImage', + arglist=[ + 'name-profile', + 'version', + 'image_release', + 'arch2', + self.session.getBuildTarget.return_value, + 123, + self.task.getRepo.return_value, + 'git://desc.server/repo#fragment', + 'desc_path', + { + 'scratch': False, + 'optional_arches': [] + } + ], + label='arch2', + parent=123, + arch='arch2' + ), + mock.call( + method='tagBuild', + arglist=[ + 321, + self.task.initImageBuild()['id'], + False, + None, + True + ], + label='tag', + parent=123, + arch='noarch' + ) + ]) + + self.assertEqual(result, + 'image build results in: /mnt/koji/packages/' + 'image_name/image_version/image_release/images') + + def test_handler_incompatible_archs(self): + # arches must be preset in the buildroot + with self.assertRaises(koji.BuildError): + self.test_handler_correct(arches=['arch3', 'arch4']) + + def test_no_arches(self): + # exactly same as correct variant. No arches are supplied, + # they should be taken from build_config + self.test_handler_correct(arches=[]) + + +class TestKiwiCreateImageTask(unittest.TestCase): + pass diff --git a/tests/test_plugins/test_kiwi_cli.py b/tests/test_plugins/test_kiwi_cli.py new file mode 100644 index 0000000..f50769a --- /dev/null +++ b/tests/test_plugins/test_kiwi_cli.py @@ -0,0 +1,137 @@ +import mock +import io +import os +import sys + + +sys.path = [os.path.join(os.path.dirname(__file__), '..')] + sys.path +from test_cli import utils + +import plugins.cli.kiwi as kiwi + +class TestAddChannel(utils.CliTestCase): + def setUp(self): + self.maxDiff = None + self.task_id = 1 + self.options = mock.MagicMock() + self.session = mock.MagicMock() + self.session.hub_version = (1, 35, 0) + #self.activate_session_mock = mock.patch('koji_cli.lib.activate_session').start() + self.error_format = """Usage: %s add-channel [options] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + self.target = 'target' + self.description_scm = 'git://scm' + self.description_path = 'path/to/file.kiwi' + + def tearDown(self): + mock.patch.stopall() + + @mock.patch('sys.stderr', new_callable=io.StringIO) + @mock.patch('sys.stdout', new_callable=io.StringIO) + def test_handle_kiwi_build_old_hub(self, stdout, stderr): + # missing use_buildroot_repo option + kiwi.watch_tasks = mock.MagicMock() + self.session.hub_version = (1, 34, 1) + self.session.kiwiBuild.return_value = self.task_id + rv = kiwi.handle_kiwi_build(self.options, self.session, + [ + self.target, + self.description_scm, + self.description_path + ]) + actual = stderr.getvalue() + expected = 'hub version is < 1.35, buildroot repo is always used in addition to specified repos\n' + self.assertMultiLineEqual(actual, expected) + self.assertMultiLineEqual(stdout.getvalue(), '') + self.session.kiwiBuild.assert_called_once_with( + arches=[], + target=self.target, + desc_url=self.description_scm, + desc_path=self.description_path, + ) + self.assertNotEqual(rv, 1) + + @mock.patch('sys.stderr', new_callable=io.StringIO) + @mock.patch('sys.stdout', new_callable=io.StringIO) + def test_handle_kiwi_build_newd_hub(self, stdout, stderr): + # introduced use_buildroot_repo option + kiwi.watch_tasks = mock.MagicMock() + self.session.hub_version = (1, 35, 0) + self.session.kiwiBuild.return_value = self.task_id + rv = kiwi.handle_kiwi_build(self.options, self.session, + [ + self.target, + self.description_scm, + self.description_path + ]) + actual = stderr.getvalue() + expected = 'no repos given, using buildroot repo\n' + self.assertMultiLineEqual(actual, expected) + self.assertMultiLineEqual(stdout.getvalue(), '') + self.session.kiwiBuild.assert_called_once_with( + arches=[], + target=self.target, + desc_url=self.description_scm, + desc_path=self.description_path, + use_buildroot_repo=True, + ) + self.assertNotEqual(rv, 1) + + @mock.patch('sys.stderr', new_callable=io.StringIO) + @mock.patch('sys.stdout', new_callable=io.StringIO) + def test_handle_kiwi_all_options(self, stdout, stderr): + # introduced use_buildroot_repo option + kiwi.watch_tasks = mock.MagicMock() + self.session.hub_version = (1, 35, 0) + self.session.kiwiBuild.return_value = self.task_id + rv = kiwi.handle_kiwi_build(self.options, self.session, + [ + self.target, + self.description_scm, + self.description_path, + '--scratch', + '--version=test_version', + '--release=test_release', + '--repo=https://test_repo_1', + '--repo=https://test_repo_2', + '--buildroot-repo', + '--repo-releasever=releasever', + '--noprogress', + '--kiwi-profile=profile.kiwi', + '--type=build_type', + '--type-attr=type_attr', + '--result-bundle-name-format=name_format', + '--make-prep', + '--can-fail=x86_64', + '--arch=x86_64', + '--arch=s390x', + '--nowait', + ]) + actual = stderr.getvalue() + expected = '' + self.assertMultiLineEqual(actual, expected) + self.assertMultiLineEqual(stdout.getvalue(), '') + self.session.kiwiBuild.assert_called_once_with( + arches=['x86_64', 's390x'], + target=self.target, + desc_url=self.description_scm, + desc_path=self.description_path, + scratch=True, + optional_arches=['x86_64'], + profile='profile.kiwi', + version='test_version', + release='test_release', + make_prep=True, + type='build_type', + type_attr=['type_attr'], + result_bundle_name_format='name_format', + repos=['https://test_repo_1', 'https://test_repo_2'], + repo_releasever='releasever', + use_buildroot_repo=True, + ) + self.assertNotEqual(rv, 1) + + diff --git a/tests/test_plugins/test_kiwi_hub.py b/tests/test_plugins/test_kiwi_hub.py new file mode 100644 index 0000000..cd5c7f6 --- /dev/null +++ b/tests/test_plugins/test_kiwi_hub.py @@ -0,0 +1,97 @@ +import mock +import unittest + +import koji +import kojihub +from plugins.hub import kiwi + +class TestKiwiHub(unittest.TestCase): + def setUp(self): + self.context = mock.patch('plugins.hub.kiwi.context').start() + self.context.session.assertPerm = mock.MagicMock() + kojihub.get_build_target = mock.MagicMock() + kojihub.get_build_target.return_value = {'id': 1, 'name': 'target'} + kojihub.make_task = mock.MagicMock() + kojihub.make_task.return_value = 1 + + def tearDown(self): + mock.patch.stopall() + + def test_kiwi_basic(self): + kiwi.kiwiBuild('target', ['arch1', 'arch2'], 'desc_url', 'desc_path') + kojihub.get_build_target.assert_called_once_with('target', strict=True) + kojihub.make_task.assert_called_once_with( + 'kiwiBuild', + [ + 'target', + ['arch1', 'arch2'], + 'desc_url', + 'desc_path', + {'use_buildroot_repo': True} + ], + channel='image' + ) + + def test_nonexistent_target(self): + kojihub.get_build_target.side_effect = koji.GenericError + with self.assertRaises(koji.GenericError): + kiwi.kiwiBuild('target', ['arch1', 'arch2'], 'desc_url', 'desc_path') + kojihub.get_build_target.assert_called_once_with('target', strict=True) + + def test_invalid_arches(self): + for arch_set in ['arch1,arch2', 'ěšč']: + with self.assertRaises(koji.GenericError): + kiwi.kiwiBuild('target', arch_set, 'desc_url', 'desc_path') + + with self.assertRaises(TypeError): + kiwi.kiwiBuild('target', ["arch1", None], 'desc_url', 'desc_path') + + with self.assertRaises(AttributeError): + kiwi.kiwiBuild('target', None, 'desc_url', 'desc_path') + + def test_all_options(self): + kiwi.kiwiBuild( + 'target', + ['arch1', 'arch2'], + 'desc_url', + 'desc_path', + optional_arches=['arch1'], + profile='profile', + scratch=True, + priority=10, + make_prep=True, + repos=['repo1', 'repo2'], + release='release', + type='type', + type_attr=['type_attr'], + result_bundle_name_format='name_format', + use_buildroot_repo=True, + version='version', + repo_releasever='relver' + ) + kojihub.make_task.assert_called_once_with( + 'kiwiBuild', + [ + 'target', + ['arch1', 'arch2'], + 'desc_url', + 'desc_path', + { + 'scratch': True, + 'profile': 'profile', + 'version': 'version', + 'release': 'release', + 'optional_arches': ['arch1'], + 'repos': ['repo1', 'repo2'], + 'repo_releasever': 'relver', + 'make_prep': True, + 'type': 'type', + 'use_buildroot_repo': True, + 'type_attr': ['type_attr'], + 'result_bundle_name_format': 'name_format' + }, + ], + channel='image', + priority=koji.PRIO_DEFAULT + 10, + ) +