debian-koji/tests/test_utils.py
2016-11-21 10:52:32 -05:00

484 lines
19 KiB
Python

import mock
import unittest
from mock import call
import os
import optparse
import ConfigParser
import koji
import koji.util
class EnumTestCase(unittest.TestCase):
def test_enum_create_alpha(self):
""" Test that we can create an Enum with alphabet names """
koji.Enum(('one', 'two', 'three'))
def test_enum_bracket_access(self):
""" Test bracket access. """
test = koji.Enum(('one', 'two', 'three'))
self.assertEquals(test['one'], 0)
self.assertEquals(test['two'], 1)
self.assertEquals(test['three'], 2)
with self.assertRaises(KeyError):
test['does not exist']
def test_enum_getter_access(self):
""" Test getter access. """
test = koji.Enum(('one', 'two', 'three'))
self.assertEquals(test.get('one'), 0)
self.assertEquals(test.get('two'), 1)
self.assertEquals(test.get('three'), 2)
self.assertEquals(test.get('does not exist'), None)
def test_enum_slice_access(self):
""" Test slice access. """
test = koji.Enum(('one', 'two', 'three'))
self.assertEquals(test[1:], ('two', 'three'))
class MiscFunctionTestCase(unittest.TestCase):
@mock.patch('os.path.exists')
@mock.patch('os.path.islink')
@mock.patch('shutil.move')
def test_safer_move(self, move, islink, exists):
"""Test safer_move function"""
src = '/FAKEPATH/SRC'
dst = '/FAKEPATH/DST'
# good args
exists.return_value = False
islink.return_value = False
koji.util.safer_move(src, dst)
exists.assert_called_once_with(dst)
islink.assert_called_once_with(dst)
move.assert_called_once_with(src, dst)
move.reset_mock()
islink.reset_mock()
exists.reset_mock()
# existing dst
exists.return_value = True
with self.assertRaises(koji.GenericError):
koji.util.safer_move(src, dst)
exists.assert_called_once_with(dst)
move.assert_not_called()
move.reset_mock()
islink.reset_mock()
exists.reset_mock()
# symlink dst
exists.return_value = False
islink.return_value = True
with self.assertRaises(koji.GenericError):
koji.util.safer_move(src, dst)
exists.assert_called_once_with(dst)
islink.assert_called_once_with(dst)
move.assert_not_called()
@mock.patch('urllib2.urlopen')
@mock.patch('tempfile.TemporaryFile')
@mock.patch('shutil.copyfileobj')
@mock.patch('__builtin__.open')
def test_openRemoteFile(self, m_open, m_copyfileobj, m_TemporaryFile,
m_urlopen):
"""Test openRemoteFile function"""
mocks = [m_open, m_copyfileobj, m_TemporaryFile, m_urlopen]
topurl = 'http://example.com/koji'
path = 'relative/file/path'
url = 'http://example.com/koji/relative/file/path'
# using topurl, no tempfile
fo = koji.openRemoteFile(path, topurl)
m_urlopen.assert_called_once_with(url)
m_urlopen.return_value.close.assert_called_once()
m_TemporaryFile.assert_called_once_with(dir=None)
m_copyfileobj.assert_called_once()
m_open.assert_not_called()
assert fo is m_TemporaryFile.return_value
for m in mocks:
m.reset_mock()
# using topurl + tempfile
tempdir = '/tmp/koji/1234'
fo = koji.openRemoteFile(path, topurl, tempdir=tempdir)
m_urlopen.assert_called_once_with(url)
m_urlopen.return_value.close.assert_called_once()
m_TemporaryFile.assert_called_once_with(dir=tempdir)
m_copyfileobj.assert_called_once()
m_open.assert_not_called()
assert fo is m_TemporaryFile.return_value
for m in mocks:
m.reset_mock()
# using topdir
topdir = '/mnt/mykojidir'
filename = '/mnt/mykojidir/relative/file/path'
fo = koji.openRemoteFile(path, topdir=topdir)
m_urlopen.assert_not_called()
m_TemporaryFile.assert_not_called()
m_copyfileobj.assert_not_called()
m_open.assert_called_once_with(filename)
assert fo is m_open.return_value
for m in mocks:
m.reset_mock()
# using neither
with self.assertRaises(koji.GenericError):
koji.openRemoteFile(path)
for m in mocks:
m.assert_not_called()
class MavenUtilTestCase(unittest.TestCase):
"""Test maven relative functions"""
maxDiff = None
def test_maven_config_opt_adapter(self):
"""Test class MavenConfigOptAdapter"""
conf = mock.MagicMock()
section = 'section'
adapter = koji.util.MavenConfigOptAdapter(conf, section)
self.assertIs(adapter._conf, conf)
self.assertIs(adapter._section, section)
conf.has_option.return_value = True
adapter.goals
adapter.properties
adapter.someattr
conf.has_option.return_value = False
with self.assertRaises(AttributeError) as cm:
adapter.noexistsattr
self.assertEquals(cm.exception.args[0], 'noexistsattr')
self.assertEquals(conf.mock_calls, [call.has_option(section, 'goals'),
call.get(section, 'goals'),
call.get().split(),
call.has_option(section, 'properties'),
call.get(section, 'properties'),
call.get().splitlines(),
call.has_option(section, 'someattr'),
call.get('section', 'someattr'),
call.has_option(section, 'noexistsattr')])
def test_maven_opts(self):
"""Test maven_opts function"""
values = optparse.Values({
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': ['p1=1', 'p2', 'p3=ppp3'],
'envs': ['e1=1', 'e2=2'],
'buildrequires': ['r1', 'r2'],
'otheropts': 'others'})
self.assertEqual(koji.util.maven_opts(values), {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'}})
self.assertEqual(koji.util.maven_opts(values, chain=True, scratch=True), {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'},
'buildrequires': ['r1', 'r2']})
self.assertEqual(koji.util.maven_opts(values, chain=False, scratch=True), {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'},
'scratch': True})
values = optparse.Values({'envs': ['e1']})
with self.assertRaises(ValueError) as cm:
koji.util.maven_opts(values)
self.assertEqual(
cm.exception.args[0],
"Environment variables must be in NAME=VALUE format")
def test_maven_params(self):
"""Test maven_params function"""
config = self._read_conf('/data/maven/config.ini')
self.assertEqual(koji.util.maven_params(config, 'pkg1'), {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'}})
def test_wrapper_params(self):
"""Test wrapper_params function"""
config = self._read_conf('/data/maven/config.ini')
self.assertEqual(koji.util.wrapper_params(config, 'pkg2'), {
'type': 'maven',
'scmurl': 'scmurl',
'buildrequires': ['r1', 'r2'],
'create_build': True})
self.assertEqual(koji.util.wrapper_params(config, 'pkg2', scratch=True), {
'type': 'maven',
'scmurl': 'scmurl',
'buildrequires': ['r1', 'r2']})
def test_parse_maven_params(self):
"""Test parse_maven_params function"""
path = os.path.dirname(__file__)
# single conf file, and chain=False, scratch=False
confs = path + '/data/maven/config.ini'
self.assertEqual(koji.util.parse_maven_params(confs), {
'pkg1': {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'}},
'pkg2': {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'}},
'pkg3': {
'type': 'wrapper',
'scmurl': 'scmurl',
'buildrequires': ['r1'],
'create_build': True}})
# multiple conf file, and chain=True, scratch=False
confs = [confs, path + '/data/maven/good_config.ini']
self.assertEqual(koji.util.parse_maven_params(confs, chain=True), {
'pkg1': {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'},
'buildrequires': ['r1', 'r2']},
'pkg2': {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'},
'buildrequires': ['r1', 'r2']},
'pkg3': {
'type': 'wrapper',
'scmurl': 'scmurl',
'buildrequires': ['r1'],
'create_build': True},
'pkg4': {
'scmurl': 'scmurl',
'patches': 'patchurl',
'specfile': 'specfile',
'goals': ['goal1', 'goal2'],
'profiles': ['profile1', 'profile2'],
'packages': ['pkg1', 'pkg2'],
'jvm_options': ['--opt1', '--opt2=val'],
'maven_options': ['--opt1', '--opt2=val'],
'properties': {'p2': None, 'p3': 'ppp3', 'p1': '1'},
'envs': {'e1': '1', 'e2': '2'},
'buildrequires': ['r1', 'r2']},
})
# bad conf file - type=wrapper and len(params.get('buildrequires')!=1)
confs = path + '/data/maven/bad_wrapper_config.ini'
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_params(confs)
self.assertEqual(
cm.exception.args[0],
'A wrapper-rpm must depend on exactly one package')
# bad conf file - type is neither 'maven' nor 'wrapper')
confs = path + '/data/maven/bad_type_config.ini'
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_params(confs)
self.assertEqual(cm.exception.args[0], 'Unsupported build type: other')
# bad conf file - no scmurl param
confs = path + '/data/maven/bad_scmurl_config.ini'
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_params(confs)
self.assertEqual(
cm.exception.args[0],
'pkg is missing the scmurl parameter')
# bad conf file - empty dict returned
confs = path + '/data/maven/bad_empty_config.ini'
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_params(confs)
self.assertEqual(
cm.exception.args[0],
'No sections found in: %s' %
confs)
def test_parse_maven_param(self):
"""Test parse_maven_param function"""
path = os.path.dirname(__file__)
# single conf file, and chain=False, scratch=False
confs = path + '/data/maven/config.ini'
with mock.patch('koji.util.parse_maven_params',
return_value={
'pkg1': {'sth': 'pkg1'},
'pkg2': {'sth': 'pkg2'},
'pkg3': {'sth': 'pkg3'}}):
self.assertEqual(
koji.util.parse_maven_param(
confs, section='pkg1'), {
'pkg1': {
'sth': 'pkg1'}})
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_param(confs, section='pkg4')
self.assertEqual(
cm.exception.args[0],
'Section pkg4 does not exist in: %s' %
confs)
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_param(confs)
self.assertEqual(
cm.exception.args[0],
'Multiple sections in: %s, you must specify the section' %
confs)
with mock.patch('koji.util.parse_maven_params', return_value={
'pkg': {'sth': 'pkg'}}):
self.assertEqual(koji.util.parse_maven_param(confs),
{'pkg': {'sth': 'pkg'}})
def test_parse_maven_chain(self):
"""Test parse_maven_chain function"""
path = os.path.dirname(__file__)
confs = path + '/data/maven/config.ini'
with mock.patch('koji.util.parse_maven_params',
return_value={
'pkg1': {'buildrequires': ['pkg2', 'pkg3']},
'pkg2': {'buildrequires': ['pkg3']},
'pkg3': {'sth': 'sth'}}):
self.assertEqual(koji.util.parse_maven_chain(confs),
{'pkg1': {'buildrequires': ['pkg2', 'pkg3']},
'pkg2': {'buildrequires': ['pkg3']},
'pkg3': {'sth': 'sth'}})
# circular deps
with mock.patch('koji.util.parse_maven_params',
return_value={
'pkg1': {'buildrequires': ['pkg2', 'pkg3']},
'pkg2': {'buildrequires': ['pkg3']},
'pkg3': {'buildrequires': ['pkg1']}}):
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_chain(confs)
self.assertEqual(
cm.exception.args[0],
'No possible build order, missing/circular dependencies')
# missing deps
with mock.patch('koji.util.parse_maven_params',
return_value={
'pkg1': {'buildrequires': ['pkg2', 'pkg3']},
'pkg2': {'buildrequires': ['pkg3']},
'pkg3': {'buildrequires': ['pkg4']}}):
with self.assertRaises(ValueError) as cm:
koji.util.parse_maven_chain(confs)
self.assertEqual(
cm.exception.args[0],
'No possible build order, missing/circular dependencies')
def test_tsort(self):
# success, one path
parts = {
'p1': {'p2', 'p3'},
'p2': {'p3'},
'p3': set()
}
self.assertEqual(koji.util.tsort(parts),
[{'p3'}, {'p2'}, {'p1'}])
# success, multi-path
parts = {
'p1': {'p2'},
'p2': {'p4'},
'p3': {'p4'},
'p4': set(),
'p5': set()
}
self.assertEqual(koji.util.tsort(parts),
[{'p4', 'p5'}, {'p2', 'p3'}, {'p1'}])
# failed, missing child 'p4'
parts = {
'p1': {'p2'},
'p2': {'p3'},
'p3': {'p4'}
}
with self.assertRaises(ValueError) as cm:
koji.util.tsort(parts)
self.assertEqual(cm.exception.args[0], 'total ordering not possible')
# failed, circular
parts = {
'p1': {'p2'},
'p2': {'p3'},
'p3': {'p1'}
}
with self.assertRaises(ValueError) as cm:
koji.util.tsort(parts)
self.assertEqual(cm.exception.args[0], 'total ordering not possible')
def _read_conf(self, cfile):
config = ConfigParser.ConfigParser()
path = os.path.dirname(__file__)
with open(path + cfile, 'r') as conf_file:
config.readfp(conf_file)
return config
if __name__ == '__main__':
unittest.main()