20_test_rpm.py 16.6 KB
Newer Older
Markus Lehtonen's avatar
Markus Lehtonen committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# vim: set fileencoding=utf-8 :
#
# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
15 16
#    along with this program; if not, please see
#    <http://www.gnu.org/licenses/>
Markus Lehtonen's avatar
Markus Lehtonen committed
17 18 19 20 21 22
"""Test the classes under L{gbp.rpm}"""

import filecmp
import os
import shutil
import tempfile
23
from nose.tools import assert_raises, eq_, ok_  # pylint: disable=E0611
Markus Lehtonen's avatar
Markus Lehtonen committed
24 25

from gbp.errors import GbpError
26 27
from gbp.rpm import (SpecFile, SrcRpmFile, NoSpecError, guess_spec,
                     guess_spec_repo, spec_from_repo)
Markus Lehtonen's avatar
Markus Lehtonen committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
from gbp.git.repository import GitRepository

# Disable "Method could be a function"
#   pylint: disable=R0201


DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data',
                        'rpm')
SRPM_DIR = os.path.join(DATA_DIR, 'srpms')
SPEC_DIR = os.path.join(DATA_DIR, 'specs')


class SpecFileTester(SpecFile):
    """Helper class for testing"""

    def protected(self, name):
        """Get a protected member"""
        return super(SpecFileTester, self).__getattribute__(name)


class RpmTestBase(object):
    """Test base class"""
    def __init__(self):
        self.tmpdir = None

    def setup(self):
        """Test case setup"""
        self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.')

    def teardown(self):
        """Test case teardown"""
        shutil.rmtree(self.tmpdir)

61

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
class TestSrcRpmFile(RpmTestBase):
    """Test L{gbp.rpm.SrcRpmFile}"""

    def test_srpm(self):
        """Test parsing of a source rpm"""
        srpm = SrcRpmFile(os.path.join(SRPM_DIR, 'gbp-test-1.0-1.src.rpm'))
        eq_(srpm.version, {'release': '1', 'upstreamversion': '1.0'})
        eq_(srpm.name, 'gbp-test')
        eq_(srpm.upstreamversion, '1.0')
        eq_(srpm.packager, None)

    def test_srpm_2(self):
        """Test parsing of another source rpm"""
        srpm = SrcRpmFile(os.path.join(SRPM_DIR, 'gbp-test2-3.0-0.src.rpm'))
        eq_(srpm.version, {'release': '0', 'upstreamversion': '3.0',
                           'epoch': '2'})
        eq_(srpm.packager, 'Markus Lehtonen <markus.lehtonen@linux.intel.com>')

    def test_unpack_srpm(self):
        """Test unpacking of a source rpm"""
        srpm = SrcRpmFile(os.path.join(SRPM_DIR, 'gbp-test-1.0-1.src.rpm'))
        srpm.unpack(self.tmpdir)
        for fn in ['gbp-test-1.0.tar.bz2', 'foo.txt', 'bar.tar.gz', 'my.patch',
                   'my2.patch', 'my3.patch']:
            ok_(os.path.exists(os.path.join(self.tmpdir, fn)),
87 88
                "%s not found" % fn)

89

Markus Lehtonen's avatar
Markus Lehtonen committed
90 91 92 93 94 95 96 97 98
class TestSpecFile(RpmTestBase):
    """Test L{gbp.rpm.SpecFile}"""

    def test_spec(self):
        """Test parsing of a valid spec file"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test.spec')
        spec = SpecFileTester(spec_filepath)

        # Test basic properties
99 100 101
        eq_(spec.specfile, os.path.basename(spec_filepath))
        eq_(spec.specdir, os.path.dirname(spec_filepath))
        eq_(spec.specpath, spec_filepath)
Markus Lehtonen's avatar
Markus Lehtonen committed
102

103 104
        eq_(spec.name, 'gbp-test')
        eq_(spec.packager, None)
Markus Lehtonen's avatar
Markus Lehtonen committed
105

106 107 108 109
        eq_(spec.upstreamversion, '1.0')
        eq_(spec.release, '1')
        eq_(spec.epoch, None)
        eq_(spec.version, {'release': '1', 'upstreamversion': '1.0'})
Markus Lehtonen's avatar
Markus Lehtonen committed
110 111

        orig = spec.orig_src
112 113 114 115 116 117
        eq_(orig['filename'], 'gbp-test-1.0.tar.bz2')
        eq_(orig['uri'], 'gbp-test-1.0.tar.bz2')
        eq_(orig['filename_base'], 'gbp-test-1.0')
        eq_(orig['archive_fmt'], 'tar')
        eq_(orig['compression'], 'bzip2')
        eq_(orig['prefix'], 'gbp-test/')
Markus Lehtonen's avatar
Markus Lehtonen committed
118 119 120 121 122 123 124

    def test_spec_2(self):
        """Test parsing of another valid spec file"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
        spec = SpecFile(spec_filepath)

        # Test basic properties
125 126
        eq_(spec.name, 'gbp-test2')
        eq_(spec.packager, 'Markus Lehtonen <markus.lehtonen@linux.intel.com>')
Markus Lehtonen's avatar
Markus Lehtonen committed
127

128 129 130
        eq_(spec.epoch, '2')
        eq_(spec.version, {'release': '0', 'upstreamversion': '3.0',
                           'epoch': '2'})
Markus Lehtonen's avatar
Markus Lehtonen committed
131 132

        orig = spec.orig_src
133 134 135 136 137
        eq_(orig['filename'], 'gbp-test2-3.0.tar.gz')
        eq_(orig['uri'], 'ftp://ftp.host.com/gbp-test2-3.0.tar.gz')
        eq_(orig['archive_fmt'], 'tar')
        eq_(orig['compression'], 'gzip')
        eq_(orig['prefix'], '')
Markus Lehtonen's avatar
Markus Lehtonen committed
138 139 140 141 142 143 144

    def test_spec_3(self):
        """Test parsing of yet another valid spec file"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native.spec')
        spec = SpecFile(spec_filepath)

        # Test basic properties
145
        eq_(spec.name, 'gbp-test-native')
Markus Lehtonen's avatar
Markus Lehtonen committed
146
        orig = spec.orig_src
147 148 149 150
        eq_(orig['filename'], 'gbp-test-native-1.0.zip')
        eq_(orig['archive_fmt'], 'zip')
        eq_(orig['compression'], None)
        eq_(orig['prefix'], 'gbp-test-native-1.0/')
Markus Lehtonen's avatar
Markus Lehtonen committed
151 152 153 154 155 156 157

    def test_spec_4(self):
        """Test parsing of spec without orig tarball"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native2.spec')
        spec = SpecFile(spec_filepath)

        # Test basic properties
158 159
        eq_(spec.name, 'gbp-test-native2')
        eq_(spec.orig_src, None)
Markus Lehtonen's avatar
Markus Lehtonen committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173

    def test_parse_raw(self):
        """Test parsing of a valid spec file"""
        with assert_raises(NoSpecError):
            SpecFile(None, None)
        with assert_raises(NoSpecError):
            SpecFile('filename', 'filedata')

        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test.spec')
        with open(spec_filepath, 'r') as spec_fd:
            spec_data = spec_fd.read()
        spec = SpecFile(filedata=spec_data)

        # Test basic properties
174 175 176
        eq_(spec.specfile, None)
        eq_(spec.specdir, None)
        eq_(spec.name, 'gbp-test')
Markus Lehtonen's avatar
Markus Lehtonen committed
177 178 179 180 181 182 183 184 185 186 187

    def test_update_spec(self):
        """Test spec autoupdate functionality"""
        # Create temporary spec file
        tmp_spec = os.path.join(self.tmpdir, 'gbp-test.spec')
        shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test.spec'), tmp_spec)

        reference_spec = os.path.join(SPEC_DIR, 'gbp-test-reference.spec')
        spec = SpecFile(tmp_spec)
        spec.update_patches(['new.patch'], {})
        spec.write_spec_file()
188
        eq_(filecmp.cmp(tmp_spec, reference_spec), True)
Markus Lehtonen's avatar
Markus Lehtonen committed
189 190 191 192 193 194

        # Test adding the VCS tag and adding changelog
        reference_spec = os.path.join(SPEC_DIR, 'gbp-test-reference2.spec')
        spec.set_tag('VCS', None, 'myvcstag')
        spec.set_changelog("* Wed Feb 05 2014 Name <email> 1\n- New entry\n")
        spec.write_spec_file()
195
        eq_(filecmp.cmp(tmp_spec, reference_spec), True)
Markus Lehtonen's avatar
Markus Lehtonen committed
196 197 198 199 200 201 202 203 204 205 206 207 208

    def test_update_spec2(self):
        """Another test for spec autoupdate functionality"""
        tmp_spec = os.path.join(self.tmpdir, 'gbp-test2.spec')
        shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test2.spec'), tmp_spec)

        reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference2.spec')
        spec = SpecFile(tmp_spec)
        spec.update_patches(['1.patch', '2.patch'],
                            {'1.patch': {'if': 'true'},
                             '2.patch': {'ifarch': '%ix86'}})
        spec.set_tag('VCS', None, 'myvcstag')
        spec.write_spec_file()
209
        eq_(filecmp.cmp(tmp_spec, reference_spec), True)
Markus Lehtonen's avatar
Markus Lehtonen committed
210 211 212 213 214 215 216 217

        # Test updating patches again, removing the VCS tag and re-writing
        # changelog
        reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference.spec')
        spec.update_patches(['new.patch'], {'new.patch': {'if': '1'}})
        spec.set_tag('VCS', None, '')
        spec.set_changelog("* Wed Feb 05 2014 Name <email> 2\n- New entry\n\n")
        spec.write_spec_file()
218
        eq_(filecmp.cmp(tmp_spec, reference_spec), True)
Markus Lehtonen's avatar
Markus Lehtonen committed
219 220 221 222 223 224 225 226 227 228 229 230 231

    def test_modifying(self):
        """Test updating/deleting of tags and macros"""
        tmp_spec = os.path.join(self.tmpdir, 'gbp-test.spec')
        shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test-updates.spec'), tmp_spec)
        reference_spec = os.path.join(SPEC_DIR,
                                      'gbp-test-updates-reference.spec')
        spec = SpecFileTester(tmp_spec)

        # Mangle tags
        prev = spec.protected('_delete_tag')('Vendor', None)
        spec.protected('_set_tag')('License', None, 'new license', prev)
        spec.protected('_delete_tag')('source', 0)
232
        eq_(spec.sources(), {})
Markus Lehtonen's avatar
Markus Lehtonen committed
233 234
        spec.protected('_delete_tag')('patch', 0)
        spec.protected('_delete_tag')('patch', -1)
235
        eq_(spec.protected('_patches')(), {})
Markus Lehtonen's avatar
Markus Lehtonen committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
        prev = spec.protected('_delete_tag')('invalidtag', None)

        with assert_raises(GbpError):
            # Check that setting empty value fails
            spec.protected('_set_tag')('Version', None, '', prev)
        with assert_raises(GbpError):
            # Check that setting invalid tag with public method fails
            spec.set_tag('invalidtag', None, 'value')

        # Mangle macros
        prev = spec.protected('_delete_special_macro')('patch', -1)
        spec.protected('_delete_special_macro')('patch', 123)
        spec.protected('_set_special_macro')('patch', 0, 'my new args', prev)
        with assert_raises(GbpError):
            spec.protected('_delete_special_macro')('invalidmacro', 0)
        with assert_raises(GbpError):
            spec.protected('_set_special_macro')('invalidmacro', 0, 'args',
253
                                                 prev)
Markus Lehtonen's avatar
Markus Lehtonen committed
254 255 256

        # Check resulting spec file
        spec.write_spec_file()
257
        eq_(filecmp.cmp(tmp_spec, reference_spec), True)
Markus Lehtonen's avatar
Markus Lehtonen committed
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291

    def test_modifying_err(self):
        """Test error conditions of modification methods"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
        spec = SpecFileTester(spec_filepath)

        # Unknown/invalid section name
        with assert_raises(GbpError):
            spec.protected('_set_section')('patch', 'new content\n')

        # Multiple sections with the same name
        with assert_raises(GbpError):
            spec.protected('_set_section')('files', '%{_sysconfdir}/foo\n')

    def test_changelog(self):
        """Test changelog methods"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
        spec = SpecFile(spec_filepath)

        # Read changelog
        eq_(spec.get_changelog(),
            "* Tue Feb 04 2014 Name <email> 1\n- My change\n\n\n")

        # Set changelog and check again
        new_text = "* Wed Feb 05 2014 Name <email> 2\n- New entry\n\n\n"
        spec.set_changelog(new_text)
        eq_(spec.get_changelog(), new_text)

    def test_quirks(self):
        """Test spec that is broken/has anomalities"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-quirks.spec')
        spec = SpecFile(spec_filepath)

        # Check that we quess orig source and prefix correctly
292
        eq_(spec.orig_src['prefix'], 'foobar/')
Markus Lehtonen's avatar
Markus Lehtonen committed
293 294 295 296 297 298 299

    def test_tags(self):
        """Test parsing of all the different tags of spec file"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-tags.spec')
        spec = SpecFileTester(spec_filepath)

        # Check all the tags
Guido Günther's avatar
Guido Günther committed
300
        for name, val in spec.protected('_tags').items():
Markus Lehtonen's avatar
Markus Lehtonen committed
301 302 303 304 305 306 307 308
            rval = None
            if name in ('version', 'release', 'epoch'):
                rval = '0'
            elif name in ('autoreq', 'autoprov', 'autoreqprov'):
                rval = 'No'
            elif name not in spec.protected('_listtags'):
                rval = 'my_%s' % name
            if rval:
309
                eq_(val['value'], rval, ("'%s:' is '%s', expecting '%s'" %
310
                                         (name, val['value'], rval)))
311
            eq_(spec.ignorepatches, [])
Markus Lehtonen's avatar
Markus Lehtonen committed
312 313 314 315 316
            # Check patch numbers and patch filenames
            patches = {}
            for patch in spec.protected('_tags')['patch']['lines']:
                patches[patch['num']] = patch['linevalue']

317
            eq_(patches, {0: 'my_patch0', -1: 'my_patch'})
Markus Lehtonen's avatar
Markus Lehtonen committed
318 319 320 321 322 323

    def test_patch_series(self):
        """Test the getting the patches as a patchseries"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native.spec')
        spec = SpecFileTester(spec_filepath)

324
        eq_(len(spec.patchseries()), 0)
Markus Lehtonen's avatar
Markus Lehtonen committed
325
        spec.update_patches(['1.patch', '2.patch', '3.patch'], {})
326
        eq_(len(spec.patchseries()), 3)
Markus Lehtonen's avatar
Markus Lehtonen committed
327 328
        spec.protected('_gbp_tags')['ignore-patches'].append({'args': "0"})
        spec.update_patches(['4.patch'], {})
329 330
        eq_(len(spec.patchseries()), 1)
        eq_(len(spec.patchseries(ignored=True)), 2)
Markus Lehtonen's avatar
Markus Lehtonen committed
331
        spec.protected('_delete_special_macro')('patch', 0)
332
        eq_(len(spec.patchseries(ignored=True)), 1)
Markus Lehtonen's avatar
Markus Lehtonen committed
333
        series = spec.patchseries(unapplied=True, ignored=True)
334 335
        eq_(len(series), 2)
        eq_(os.path.basename(series[-1].path), '1.patch')
Markus Lehtonen's avatar
Markus Lehtonen committed
336

337 338 339 340 341 342 343 344 345 346 347 348
    def test_patch_series_autosetup(self):
        """Check patch series functionalitu with %autostup"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test3.spec')
        spec = SpecFileTester(spec_filepath)

        eq_(len(spec.patchseries()), 2)
        eq_(len(spec.patchseries(ignored=True)), 3)
        spec.update_patches(['1.patch'], {})
        eq_(len(spec.patchseries()), 1)
        eq_(len(spec.patchseries(ignored=True)), 2)
        eq_(spec.protected('_special_directives')['patch'], [])

Markus Lehtonen's avatar
Markus Lehtonen committed
349 350 351 352 353 354 355
    def test_patch_series_quirks(self):
        """Patches are applied in order different from the patch numbering"""
        spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-quirks.spec')
        spec = SpecFileTester(spec_filepath)

        # Check series is returned in the order the patches are applied
        files = [os.path.basename(patch.path) for patch in spec.patchseries()]
356
        eq_(files, ['05.patch', '01.patch'])
Markus Lehtonen's avatar
Markus Lehtonen committed
357 358
        # Also ignored patches are returned in the correct order
        files = [os.path.basename(patch.path) for patch in
359
                 spec.patchseries(ignored=True)]
360
        eq_(files, ['05.patch', '02.patch', '01.patch'])
Markus Lehtonen's avatar
Markus Lehtonen committed
361 362
        # Unapplied patches are added to the end of the series
        files = [os.path.basename(patch.path) for patch in
363
                 spec.patchseries(unapplied=True)]
364
        eq_(files, ['05.patch', '01.patch', '03.patch'])
Markus Lehtonen's avatar
Markus Lehtonen committed
365 366
        # Return all patches (for which tag is found)
        files = [os.path.basename(patch.path) for patch in
367
                 spec.patchseries(unapplied=True, ignored=True)]
368
        eq_(files, ['05.patch', '02.patch', '01.patch', '03.patch', '04.patch'])
Markus Lehtonen's avatar
Markus Lehtonen committed
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385


class TestUtilityFunctions(RpmTestBase):
    """Test utility functions of L{gbp.rpm}"""

    def test_guess_spec(self):
        """Test guess_spec() function"""
        # Spec not found
        with assert_raises(NoSpecError):
            guess_spec(DATA_DIR, recursive=False)
        # Multiple spec files
        with assert_raises(NoSpecError):
            guess_spec(DATA_DIR, recursive=True)
        with assert_raises(NoSpecError):
            guess_spec(SPEC_DIR, recursive=False)
        # Spec found
        spec = guess_spec(SPEC_DIR, recursive=False,
386
                          preferred_name='gbp-test2.spec')
387 388
        eq_(spec.specfile, 'gbp-test2.spec')
        eq_(spec.specdir, SPEC_DIR)
Markus Lehtonen's avatar
Markus Lehtonen committed
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411

    def test_guess_spec_repo(self):
        """Test guess_spec_repo() and spec_from_repo() functions"""
        # Create dummy repository with some commits
        repo = GitRepository.create(self.tmpdir)
        with open(os.path.join(repo.path, 'foo.txt'), 'w') as fobj:
            fobj.write('bar\n')
        repo.add_files('foo.txt')
        repo.commit_all('Add dummy file')
        os.mkdir(os.path.join(repo.path, 'packaging'))
        shutil.copy(os.path.join(SPEC_DIR, 'gbp-test.spec'),
                    os.path.join(repo.path, 'packaging'))
        repo.add_files('packaging/gbp-test.spec')
        repo.commit_all('Add spec file')

        # Spec not found
        with assert_raises(NoSpecError):
            guess_spec_repo(repo, 'HEAD~1', recursive=True)
        with assert_raises(NoSpecError):
            guess_spec_repo(repo, 'HEAD', recursive=False)
        # Spec found
        spec = guess_spec_repo(repo, 'HEAD', 'packaging', recursive=False)
        spec = guess_spec_repo(repo, 'HEAD', recursive=True)
412 413 414
        eq_(spec.specfile, 'gbp-test.spec')
        eq_(spec.specdir, 'packaging')
        eq_(spec.specpath, 'packaging/gbp-test.spec')
Markus Lehtonen's avatar
Markus Lehtonen committed
415 416 417 418 419

        # Test spec_from_repo()
        with assert_raises(NoSpecError):
            spec_from_repo(repo, 'HEAD~1', 'packaging/gbp-test.spec')
        spec = spec_from_repo(repo, 'HEAD', 'packaging/gbp-test.spec')
420
        eq_(spec.specfile, 'gbp-test.spec')
Markus Lehtonen's avatar
Markus Lehtonen committed
421 422

# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: