1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 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 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
|
# 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
# 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_ # pylint: disable=E0611
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
# 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)
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
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 ' \
'<markus.lehtonen@linux.intel.com>'
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"""
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 <email> 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 <email> 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)
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',
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
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
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(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,
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
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()
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\:·:
|