#4186 Basic tests for kiwi plugin
Merged 8 months ago by tkopecek. Opened 8 months ago by tkopecek.
tkopecek/koji kiwi-tests  into  master

@@ -63,7 +63,8 @@ 

              # 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: '

@@ -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'<?xml version="1.0"?><test></test>')

+             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'''<?xml version="1.0" encoding="utf-8"?>

+                     <image schemaversion="7.4" name="Fedora-34.0_disk">

+                         <profiles>

+                             <profile name="Base" description="Base System"

+                                      import="true" image="true"/>

+                         </profiles>

+                         <preferences>

+                             <version>1.0.0</version>

+                         </preferences>

+                     </image>

+             ''')

+             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

@@ -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] <channel_name>

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

+ 

+ 

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

+         )

+