# vim: set fileencoding=utf-8 : # # (C) 2012 Intel Corporation # 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 # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Test the classes under L{gbp.rpm}""" import filecmp import os import shutil import tempfile from nose.tools import assert_raises, eq_ from gbp.errors import GbpError from gbp.rpm import (SrcRpmFile, SpecFile, parse_srpm, NoSpecError, guess_spec, guess_spec_repo, spec_from_repo) from gbp.git.repository import GitRepository 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 TestSrcRpmFile(object): """Test L{gbp.rpm.SrcRpmFile}""" def setup(self): self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.') def teardown(self): shutil.rmtree(self.tmpdir) def test_srpm(self): """Test parsing of a source rpm""" srpm = SrcRpmFile(os.path.join(SRPM_DIR, 'gbp-test-1.0-1.src.rpm')) assert srpm.version == {'release': '1', 'upstreamversion': '1.0'} assert srpm.name == 'gbp-test' assert srpm.upstreamversion == '1.0' assert srpm.packager is 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')) assert srpm.version == {'release': '0', 'upstreamversion': '3.0', 'epoch': '2'} assert srpm.packager == 'Markus Lehtonen '\ '' 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']: assert os.path.exists(os.path.join(self.tmpdir, fn)), \ "%s not found" % fn class TestSpecFile(object): """Test L{gbp.rpm.SpecFile}""" def setup(self): self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.') def teardown(self): shutil.rmtree(self.tmpdir) 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 assert spec.specfile == os.path.basename(spec_filepath) assert spec.specdir == os.path.dirname(spec_filepath) assert spec.specpath == spec_filepath assert spec.name == 'gbp-test' assert spec.packager is None assert spec.upstreamversion == '1.0' assert spec.release == '1' assert spec.epoch is None assert spec.version == {'release': '1', 'upstreamversion': '1.0'} orig = spec.orig_src assert orig['filename'] == 'gbp-test-1.0.tar.bz2' assert orig['uri'] == 'gbp-test-1.0.tar.bz2' assert orig['filename_base'] == 'gbp-test-1.0' assert orig['archive_fmt'] == 'tar' assert orig['compression'] == 'bzip2' assert orig['prefix'] == 'gbp-test/' 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 assert spec.name == 'gbp-test2' assert spec.packager == 'Markus Lehtonen ' \ '' assert spec.epoch == '2' assert spec.version == {'release': '0', 'upstreamversion': '3.0', 'epoch': '2'} orig = spec.orig_src assert orig['filename'] == 'gbp-test2-3.0.tar.gz' assert orig['uri'] == 'ftp://ftp.host.com/gbp-test2-3.0.tar.gz' assert orig['archive_fmt'] == 'tar' assert orig['compression'] == 'gzip' assert orig['prefix'] == '' 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 assert spec.name == 'gbp-test-native' orig = spec.orig_src assert orig['filename'] == 'gbp-test-native-1.0.zip' assert orig['archive_fmt'] == 'zip' assert orig['compression'] == None assert orig['prefix'] == 'gbp-test-native-1.0/' 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 assert spec.name == 'gbp-test-native2' assert spec.orig_src is None def test_parse_raw(self): """Test parsing of a valid spec file""" assert_raises(NoSpecError, SpecFile, None, None) assert_raises(NoSpecError, SpecFile, 'filename', 'filedata') """ 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 assert spec.specfile == None assert spec.specdir == None assert spec.name == 'gbp-test' 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() assert filecmp.cmp(tmp_spec, reference_spec) is True # 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 1\n- New entry\n") spec.write_spec_file() assert filecmp.cmp(tmp_spec, reference_spec) is True 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() assert filecmp.cmp(tmp_spec, reference_spec) is True # 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 2\n- New entry\n\n") spec.write_spec_file() assert filecmp.cmp(tmp_spec, reference_spec) is True 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) assert spec.sources() == {} spec.protected('_delete_tag')('patch', 0) spec.protected('_delete_tag')('patch', -1) assert spec.protected('_patches')() == {} prev = spec.protected('_delete_tag')('invalidtag', None) assert_raises(GbpError, spec.protected('_set_tag'), 'Version', None, '', prev) assert_raises(GbpError, spec.set_tag, 'invalidtag', None, 'value') """ 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) assert_raises(GbpError, spec.protected('_delete_special_macro'), 'invalidmacro', 0) assert_raises(GbpError, spec.protected('_set_special_macro'), 'invalidmacro', 0, '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', prev) """ # Check resulting spec file spec.write_spec_file() assert filecmp.cmp(tmp_spec, reference_spec) is True 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 assert_raises(GbpError, spec.protected('_set_section'), 'patch', 'new content\n') """ with assert_raises(GbpError): spec.protected('_set_section')('patch', 'new content\n') """ # Multiple sections with the same name assert_raises(GbpError, spec.protected('_set_section'), 'files', '%{_sysconfdir}/foo\n') """ 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 1\n- My change\n\n\n") # Set changelog and check again new_text = "* Wed Feb 05 2014 Name 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 assert spec.orig_src['prefix'] == 'foobar/' 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 for name, val in spec.protected('_tags').iteritems(): 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: assert val['value'] == rval, ("'%s:' is '%s', expecting '%s'" % (name, val['value'], rval)) assert spec.ignorepatches == [] # Check patch numbers and patch filenames patches = {} for patch in spec.protected('_tags')['patch']['lines']: patches[patch['num']] = patch['linevalue'] assert patches == {0: 'my_patch0', -1: 'my_patch'} 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) assert len(spec.patchseries()) == 0 spec.update_patches(['1.patch', '2.patch', '3.patch'], {}) assert len(spec.patchseries()) == 3 spec.protected('_gbp_tags')['ignore-patches'].append({'args': "0"}) spec.update_patches(['4.patch'], {}) assert len(spec.patchseries()) == 1 assert len(spec.patchseries(ignored=True)) == 2 spec.protected('_delete_special_macro')('patch', 0) assert len(spec.patchseries(ignored=True)) == 1 series = spec.patchseries(unapplied=True, ignored=True) assert len(series) == 2 assert os.path.basename(series[-1].path) == '1.patch' 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()] assert files == ['05.patch', '01.patch'] # Also ignored patches are returned in the correct order files = [os.path.basename(patch.path) for patch in spec.patchseries(ignored=True)] assert files == ['05.patch', '02.patch', '01.patch'] # Unapplied patches are added to the end of the series files = [os.path.basename(patch.path) for patch in spec.patchseries(unapplied=True)] assert files == ['05.patch', '01.patch', '03.patch'] # Return all patches (for which tag is found) files = [os.path.basename(patch.path) for patch in spec.patchseries(unapplied=True, ignored=True)] assert files == ['05.patch', '02.patch', '01.patch', '03.patch', '04.patch'] class TestUtilityFunctions(object): """Test utility functions of L{gbp.rpm}""" def setup(self): self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.') def teardown(self): shutil.rmtree(self.tmpdir) def test_parse_srpm(self): """Test parse_srpm() function""" parse_srpm(os.path.join(SRPM_DIR, 'gbp-test-1.0-1.src.rpm')) assert_raises(GbpError, parse_srpm, os.path.join(DATA_DIR, 'notexists.src.rpm')) """ with assert_raises(GbpError): parse_srpm(os.path.join(DATA_DIR, 'notexists.src.rpm')) with assert_raises(GbpError): parse_srpm(os.path.join(SPEC_DIR, 'gbp-test.spec')) """ def test_guess_spec(self): """Test guess_spec() function""" # Spec not found assert_raises(NoSpecError, guess_spec, DATA_DIR, recursive=False) """ with assert_raises(NoSpecError): guess_spec(DATA_DIR, recursive=False) """ # Multiple spec files assert_raises(NoSpecError, guess_spec, DATA_DIR, recursive=True) assert_raises(NoSpecError, guess_spec, SPEC_DIR, recursive=False) """ 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, preferred_name = 'gbp-test2.spec') assert spec.specfile == 'gbp-test2.spec' assert spec.specdir == SPEC_DIR 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 assert_raises(NoSpecError, guess_spec_repo, repo, 'HEAD~1', recursive=True) assert_raises(NoSpecError, guess_spec_repo, repo, 'HEAD', recursive=False) """ 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) assert spec.specfile == 'gbp-test.spec' assert spec.specdir == 'packaging' assert spec.specpath == 'packaging/gbp-test.spec' # Test spec_from_repo() assert_raises(NoSpecError, spec_from_repo, repo, 'HEAD~1', 'packaging/gbp-test.spec') """ with assert_raises(NoSpecError): spec_from_repo(repo, 'HEAD~1', 'packaging/gbp-test.spec') """ spec = spec_from_repo(repo, 'HEAD', 'packaging/gbp-test.spec') assert spec.specfile == 'gbp-test.spec' # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: