Hub, plugins and tools inputs validation
Fixes: https://pagure.io/koji/issue/3319
This commit is contained in:
parent
a371c76128
commit
9bfefe782e
75 changed files with 3031 additions and 1695 deletions
173
hub/kojihub.py
173
hub/kojihub.py
|
|
@ -91,6 +91,30 @@ def xform_user_krb(entry):
|
|||
return entry
|
||||
|
||||
|
||||
def convert_value(value, cast=None, message=None, exc_type=None, none_allowed=False):
|
||||
if exc_type is None:
|
||||
exc_type = koji.ParameterError
|
||||
if value is None:
|
||||
if not none_allowed:
|
||||
raise(exc_type(message or "Invalid type"))
|
||||
else:
|
||||
return value
|
||||
try:
|
||||
return cast(value)
|
||||
except (ValueError, TypeError):
|
||||
raise(exc_type(message or f"Invalid type for value '{value}': {type(value)}"))
|
||||
|
||||
|
||||
def check_value_type(value, cast=None, message=None, exc_type=None, none_allowed=False):
|
||||
if none_allowed:
|
||||
if value is None:
|
||||
return value
|
||||
if exc_type is None:
|
||||
exc_type = koji.ParameterError
|
||||
if not isinstance(value, cast):
|
||||
raise (exc_type(message or f"Invalid type for value '{value}': {type(value)}"))
|
||||
|
||||
|
||||
class Task(object):
|
||||
"""A task for the build hosts"""
|
||||
|
||||
|
|
@ -116,7 +140,7 @@ class Task(object):
|
|||
('task.weight', 'weight'))
|
||||
|
||||
def __init__(self, id):
|
||||
self.id = int(id)
|
||||
self.id = convert_value(id, cast=int)
|
||||
self.logger = logging.getLogger("koji.hub.Task")
|
||||
|
||||
def _split_fields(self, fields=None):
|
||||
|
|
@ -288,7 +312,7 @@ class Task(object):
|
|||
def setWeight(self, weight):
|
||||
"""Set weight for task"""
|
||||
task_id = self.id
|
||||
weight = float(weight)
|
||||
weight = convert_value(weight, cast=float)
|
||||
info = self.getInfo(request=True)
|
||||
self.runCallbacks('preTaskStateChange', info, 'weight', weight)
|
||||
# access checks should be performed by calling function
|
||||
|
|
@ -299,7 +323,7 @@ class Task(object):
|
|||
def setPriority(self, priority, recurse=False):
|
||||
"""Set priority for task"""
|
||||
task_id = self.id
|
||||
priority = int(priority)
|
||||
priority = convert_value(priority, cast=int)
|
||||
info = self.getInfo(request=True)
|
||||
self.runCallbacks('preTaskStateChange', info, 'priority', priority)
|
||||
# access checks should be performed by calling function
|
||||
|
|
@ -540,6 +564,22 @@ def make_task(method, arglist, **opts):
|
|||
priority: the priority of the task
|
||||
assign: a host_id to assign the task to
|
||||
"""
|
||||
check_value_type(method, cast=str)
|
||||
if 'parent' in opts:
|
||||
opts['parent'] = convert_value(opts['parent'], cast=int)
|
||||
if 'label' in opts:
|
||||
check_value_type(opts['label'], cast=str)
|
||||
if 'owner' in opts:
|
||||
if not isinstance(opts['owner'], int):
|
||||
opts['owner'] = get_user(opts['owner'], strict=True)['id']
|
||||
if 'arch' in opts:
|
||||
opts['arch'] = koji.parse_arches(opts['arch'], strict=True, allow_none=True)
|
||||
if 'priority' in opts:
|
||||
opts['priority'] = \
|
||||
convert_value(opts['priority'], cast=int)
|
||||
if 'assign' in opts:
|
||||
if not isinstance(opts['assign'], int):
|
||||
opts['assign'] = get_host(opts['assign'], strict=True)['id']
|
||||
if 'parent' in opts:
|
||||
# for subtasks, we use some of the parent's options as defaults
|
||||
fields = ('state', 'owner', 'channel_id', 'priority', 'arch')
|
||||
|
|
@ -1389,6 +1429,8 @@ def readTaggedBuilds(tag, event=None, inherit=False, latest=False, package=None,
|
|||
'build.state = %(st_complete)i'
|
||||
]
|
||||
if package:
|
||||
if not isinstance(package, str):
|
||||
package = lookup_package(package, strict=True)['name']
|
||||
clauses.append('package.name = %(package)s')
|
||||
if owner:
|
||||
clauses.append('users.name = %(owner)s')
|
||||
|
|
@ -1636,8 +1678,10 @@ def check_tag_access(tag_id, user_id=None):
|
|||
"""
|
||||
if user_id is None:
|
||||
user_id = context.session.user_id
|
||||
if user_id is None:
|
||||
raise koji.GenericError("a user_id is required")
|
||||
if not user_id:
|
||||
raise koji.GenericError("a user_id is required")
|
||||
else:
|
||||
user_id = convert_value(user_id, cast=int)
|
||||
perms = koji.auth.get_user_perms(user_id)
|
||||
override = False
|
||||
if 'admin' in perms:
|
||||
|
|
@ -2376,12 +2420,14 @@ def edit_channel(channelInfo, **kw):
|
|||
return False
|
||||
|
||||
if kw.get('name'):
|
||||
if not isinstance(kw['name'], str):
|
||||
raise koji.GenericError("new channel name must be a string")
|
||||
verify_name_internal(kw['name'])
|
||||
dup_check = get_channel(kw['name'], strict=False)
|
||||
if dup_check:
|
||||
raise koji.GenericError("channel %(name)s already exists (id=%(id)i)" % dup_check)
|
||||
if kw.get('description'):
|
||||
check_value_type(kw['description'], cast=str)
|
||||
if kw.get('comment'):
|
||||
check_value_type(kw['comment'], cast=str)
|
||||
|
||||
update = UpdateProcessor('channels',
|
||||
values={'channelID': channel['id']},
|
||||
|
|
@ -2433,8 +2479,7 @@ def add_channel(channel_name, description=None):
|
|||
:param str description: description of channel
|
||||
"""
|
||||
context.session.assertPerm('admin')
|
||||
if not isinstance(channel_name, str):
|
||||
raise koji.GenericError("Channel name must be a string")
|
||||
check_value_type(description, cast=str, none_allowed=True)
|
||||
verify_name_internal(channel_name)
|
||||
dup_check = get_channel(channel_name, strict=False)
|
||||
if dup_check:
|
||||
|
|
@ -2449,6 +2494,7 @@ def add_channel(channel_name, description=None):
|
|||
|
||||
def set_channel_enabled(channelname, enabled=True, comment=None):
|
||||
context.session.assertPerm('host')
|
||||
check_value_type(comment, cast=str, none_allowed=True)
|
||||
channel = get_channel(channelname)
|
||||
if not channel:
|
||||
raise koji.GenericError('No such channel: %s' % channelname)
|
||||
|
|
@ -2640,6 +2686,7 @@ def repo_init(tag, task_id=None, with_src=False, with_debuginfo=False, event=Non
|
|||
Returns a dictionary containing
|
||||
repo_id, event_id
|
||||
"""
|
||||
task_id = convert_value(task_id, cast=int, none_allowed=True)
|
||||
logger = logging.getLogger("koji.hub.repo_init")
|
||||
state = koji.REPO_INIT
|
||||
tinfo = get_tag(tag, strict=True, event=event)
|
||||
|
|
@ -2694,9 +2741,9 @@ def repo_init(tag, task_id=None, with_src=False, with_debuginfo=False, event=Non
|
|||
'tag_id': tinfo['id'],
|
||||
'task_id': task_id,
|
||||
'event_id': event_id,
|
||||
'with_src': with_src,
|
||||
'with_separate_src': with_separate_src,
|
||||
'with_debuginfo': with_debuginfo,
|
||||
'with_src': bool(with_src),
|
||||
'with_separate_src': bool(with_separate_src),
|
||||
'with_debuginfo': bool(with_debuginfo),
|
||||
}
|
||||
with open('%s/repo.json' % repodir, 'wt', encoding='utf-8') as fp:
|
||||
json.dump(repo_info, fp, indent=2)
|
||||
|
|
@ -2823,9 +2870,12 @@ def _write_maven_repo_metadata(destdir, artifacts):
|
|||
def dist_repo_init(tag, keys, task_opts):
|
||||
"""Create a new repo entry in the INIT state, return full repo data"""
|
||||
state = koji.REPO_INIT
|
||||
check_value_type(keys, cast=list)
|
||||
tinfo = get_tag(tag, strict=True)
|
||||
tag_id = tinfo['id']
|
||||
check_value_type(task_opts, cast=dict)
|
||||
event = task_opts.get('event')
|
||||
event = convert_value(event, cast=int, none_allowed=True)
|
||||
volume = task_opts.get('volume')
|
||||
if volume is not None:
|
||||
volume = lookup_name('volume', volume, strict=True)['name']
|
||||
|
|
@ -2853,6 +2903,7 @@ def dist_repo_init(tag, keys, task_opts):
|
|||
os.symlink(relpath, basedir)
|
||||
# handle comps
|
||||
if task_opts.get('comps'):
|
||||
check_value_type(task_opts['comps'], cast=str)
|
||||
groupsdir = joinpath(repodir, 'groups')
|
||||
koji.ensuredir(groupsdir)
|
||||
shutil.copyfile(joinpath(koji.pathinfo.work(),
|
||||
|
|
@ -2877,6 +2928,7 @@ def dist_repo_init(tag, keys, task_opts):
|
|||
|
||||
def repo_set_state(repo_id, state, check=True):
|
||||
"""Set repo state"""
|
||||
repo_id = convert_value(repo_id, cast=int)
|
||||
if check:
|
||||
# The repo states are sequential, going backwards makes no sense
|
||||
q = """SELECT state FROM repo WHERE id = %(repo_id)s FOR UPDATE"""
|
||||
|
|
@ -2934,6 +2986,7 @@ def repo_delete(repo_id):
|
|||
"""Attempt to mark repo deleted, return number of references
|
||||
|
||||
If the number of references is nonzero, no change is made"""
|
||||
repo_id = convert_value(repo_id, cast=int)
|
||||
# get a row lock on the repo
|
||||
q = """SELECT state FROM repo WHERE id = %(repo_id)s FOR UPDATE"""
|
||||
_singleValue(q, locals())
|
||||
|
|
@ -3235,14 +3288,12 @@ def name_or_id_clause(table, info):
|
|||
"""
|
||||
if isinstance(info, dict):
|
||||
if 'id' in info:
|
||||
try:
|
||||
info = int(info['id'])
|
||||
except (ValueError, TypeError):
|
||||
raise koji.ParameterError('Invalid name or id value: %r' % info)
|
||||
info = convert_value(info['id'], cast=int,
|
||||
message=fr"Invalid name or id value: {info}")
|
||||
elif 'name' in info:
|
||||
info = info['name']
|
||||
else:
|
||||
raise koji.ParameterError('Invalid name or id value: %r' % info)
|
||||
raise koji.ParameterError(fr'Invalid name or id value: {info}')
|
||||
if isinstance(info, int):
|
||||
clause = f"({table}.id = %({table}_id)s)"
|
||||
values = {f"{table}_id": info}
|
||||
|
|
@ -3250,7 +3301,7 @@ def name_or_id_clause(table, info):
|
|||
clause = f"({table}.name = %({table}_name)s)"
|
||||
values = {f"{table}_name": info}
|
||||
else:
|
||||
raise koji.ParameterError('Invalid name or id value: %r' % info)
|
||||
raise koji.ParameterError(fr"Invalid name or id value: {info}")
|
||||
|
||||
return clause, values
|
||||
|
||||
|
|
@ -3557,6 +3608,10 @@ def _edit_tag(tagInfo, **kwargs):
|
|||
if not context.opts.get('EnableMaven') \
|
||||
and dslice(kwargs, ['maven_support', 'maven_include_all'], strict=False):
|
||||
raise koji.GenericError("Maven support not enabled")
|
||||
if kwargs.get('remove_extra'):
|
||||
check_value_type(kwargs['remove_extra'], cast=list, none_allowed=True)
|
||||
if kwargs.get('block_extra'):
|
||||
check_value_type(kwargs['block_extra'], cast=list, none_allowed=True)
|
||||
|
||||
tag = get_tag(tagInfo, strict=True)
|
||||
if 'perm' in kwargs and 'perm_id' not in kwargs:
|
||||
|
|
@ -3882,6 +3937,8 @@ def add_external_repo_to_tag(tag_info, repo_info, priority, merge_mode='koji', a
|
|||
if arches is not None:
|
||||
arches = koji.parse_arches(arches, strict=True)
|
||||
|
||||
priority = convert_value(priority, cast=int)
|
||||
|
||||
tag_repos = get_tag_external_repos(tag_info=tag_id)
|
||||
if [tr for tr in tag_repos if tr['external_repo_id'] == repo_id]:
|
||||
raise koji.GenericError('tag %s already associated with external repo %s' %
|
||||
|
|
@ -4442,8 +4499,7 @@ def get_next_release(build_info, incr=1):
|
|||
:raises: BuildError if the latest build uses a release value that Koji
|
||||
does not know how to increment.
|
||||
"""
|
||||
if not isinstance(incr, int):
|
||||
raise koji.ParameterError("incr parameter must be an integer")
|
||||
incr = convert_value(incr, cast=int, message='incr parameter must be an integer')
|
||||
values = {
|
||||
'name': build_info['name'],
|
||||
'version': build_info['version'],
|
||||
|
|
@ -5522,6 +5578,10 @@ def edit_host(hostInfo, **kw):
|
|||
if not changes:
|
||||
return False
|
||||
|
||||
for change in changes:
|
||||
if change in ['description', 'comment', 'arches']:
|
||||
check_value_type(kw[change], cast=str)
|
||||
|
||||
update = UpdateProcessor('host_config', values=host, clauses=['host_id = %(id)i'])
|
||||
update.make_revoke()
|
||||
update.execute()
|
||||
|
|
@ -5675,7 +5735,7 @@ def query_buildroots(hostID=None, tagID=None, state=None, rpmID=None, archiveID=
|
|||
|
||||
def get_buildroot(buildrootID, strict=False):
|
||||
"""Return information about a buildroot. buildrootID must be an int ID."""
|
||||
|
||||
buildrootID = convert_value(buildrootID, cast=int)
|
||||
result = query_buildroots(buildrootID=buildrootID)
|
||||
if len(result) == 0:
|
||||
if strict:
|
||||
|
|
@ -5741,6 +5801,7 @@ def list_channels(hostID=None, event=None, enabled=None):
|
|||
|
||||
|
||||
def new_package(name, strict=True):
|
||||
verify_name_internal(name)
|
||||
c = context.cnx.cursor()
|
||||
# TODO - table lock?
|
||||
# check for existing
|
||||
|
|
@ -6171,6 +6232,10 @@ def import_build(srpm, rpms, brmap=None, task_id=None, build_id=None, logs=None)
|
|||
"""
|
||||
if brmap is None:
|
||||
brmap = {}
|
||||
else:
|
||||
check_value_type(brmap, cast=dict)
|
||||
check_value_type(srpm, cast=str)
|
||||
check_value_type(rpms, cast=list)
|
||||
koji.plugin.run_callbacks('preImport', type='build', srpm=srpm, rpms=rpms, brmap=brmap,
|
||||
task_id=task_id, build_id=build_id, build=None, logs=logs)
|
||||
uploadpath = koji.pathinfo.work()
|
||||
|
|
@ -6536,7 +6601,6 @@ class CG_Importer(object):
|
|||
|
||||
def get_metadata(self, metadata, directory):
|
||||
"""Get the metadata from the args"""
|
||||
|
||||
if isinstance(metadata, dict):
|
||||
self.metadata = metadata
|
||||
try:
|
||||
|
|
@ -6548,8 +6612,7 @@ class CG_Importer(object):
|
|||
if metadata is None:
|
||||
# default to looking for uploaded file
|
||||
metadata = 'metadata.json'
|
||||
if not isinstance(metadata, str):
|
||||
raise koji.GenericError("Invalid type for metadata value: %r" % type(metadata))
|
||||
check_value_type(metadata, cast=str)
|
||||
if metadata.endswith('.json'):
|
||||
# handle uploaded metadata
|
||||
workdir = koji.pathinfo.work()
|
||||
|
|
@ -7324,8 +7387,7 @@ def get_archive_type(filename=None, type_name=None, type_id=None, strict=False):
|
|||
elif type_name:
|
||||
return _get_archive_type_by_name(type_name, strict)
|
||||
elif filename:
|
||||
# we handle that below
|
||||
pass
|
||||
check_value_type(filename, cast=str)
|
||||
else:
|
||||
raise koji.GenericError('one of filename, type_name, or type_id must be specified')
|
||||
|
||||
|
|
@ -7365,6 +7427,8 @@ def add_archive_type(name, description, extensions):
|
|||
"""
|
||||
context.session.assertPerm('admin')
|
||||
verify_name_internal(name)
|
||||
check_value_type(description, cast=str)
|
||||
check_value_type(extensions, cast=str)
|
||||
data = {'name': name,
|
||||
'description': description,
|
||||
'extensions': extensions,
|
||||
|
|
@ -8774,6 +8838,9 @@ def tag_notification(is_successful, tag_id, from_id, build_id, user_id, ignore_s
|
|||
failure_msg=''):
|
||||
if context.opts.get('DisableNotifications'):
|
||||
return
|
||||
if user_id:
|
||||
if not isinstance(user_id, int):
|
||||
user_id = get_user(user_id, strict=True)
|
||||
if is_successful:
|
||||
state = koji.BUILD_STATES['COMPLETE']
|
||||
else:
|
||||
|
|
@ -10320,6 +10387,7 @@ def policy_data_from_task_args(method, arglist):
|
|||
# newRepo has a 'src' parameter that means something else
|
||||
break
|
||||
if k in params:
|
||||
check_value_type(params[k], cast=str)
|
||||
policy_data['source'] = params.get(k)
|
||||
break
|
||||
# parameters that indicate build target
|
||||
|
|
@ -10482,8 +10550,10 @@ class RootExports(object):
|
|||
context.session.assertPerm('host')
|
||||
if options is None:
|
||||
args = []
|
||||
else:
|
||||
elif isinstance(options, dict):
|
||||
args = [options]
|
||||
else:
|
||||
raise koji.ParameterError('Invalid type of options: %s' % type(options))
|
||||
return make_task('restartHosts', args, priority=priority)
|
||||
|
||||
def build(self, src, target, opts=None, priority=None, channel=None):
|
||||
|
|
@ -10499,6 +10569,7 @@ class RootExports(object):
|
|||
if not opts:
|
||||
opts = {}
|
||||
taskOpts = {}
|
||||
check_value_type(src, cast=str)
|
||||
if priority:
|
||||
if priority < 0:
|
||||
if not context.session.hasPerm('admin'):
|
||||
|
|
@ -10522,6 +10593,7 @@ class RootExports(object):
|
|||
Returns a list of all the dependent task ids
|
||||
"""
|
||||
context.session.assertLogin()
|
||||
check_value_type(srcs, cast=list)
|
||||
if not opts:
|
||||
opts = {}
|
||||
taskOpts = {}
|
||||
|
|
@ -10550,6 +10622,7 @@ class RootExports(object):
|
|||
context.session.assertLogin()
|
||||
if not context.opts.get('EnableMaven'):
|
||||
raise koji.GenericError("Maven support not enabled")
|
||||
check_value_type(url, cast=str)
|
||||
if not opts:
|
||||
opts = {}
|
||||
taskOpts = {}
|
||||
|
|
@ -10586,13 +10659,13 @@ class RootExports(object):
|
|||
if not opts:
|
||||
opts = {}
|
||||
|
||||
check_value_type(url, cast=str)
|
||||
|
||||
build = self.getBuild(build, strict=True)
|
||||
if list_rpms(build['id']) and not (opts.get('scratch') or opts.get('create_build')):
|
||||
raise koji.PreBuildError('wrapper rpms for %s have already been built' %
|
||||
koji.buildLabel(build))
|
||||
build_target = self.getBuildTarget(target)
|
||||
if not build_target:
|
||||
raise koji.PreBuildError('no such build target: %s' % target)
|
||||
build_target = self.getBuildTarget(target, strict=True)
|
||||
build_tag = self.getTag(build_target['build_tag'], strict=True)
|
||||
repo_info = self.getRepo(build_tag['id'])
|
||||
if not repo_info:
|
||||
|
|
@ -10602,7 +10675,8 @@ class RootExports(object):
|
|||
taskOpts = {}
|
||||
if priority:
|
||||
taskOpts['priority'] = koji.PRIO_DEFAULT + priority
|
||||
taskOpts['channel'] = channel
|
||||
if channel:
|
||||
taskOpts['channel'] = channel
|
||||
|
||||
return make_task('wrapperRPM', [url, build_target, build, None, opts], **taskOpts)
|
||||
|
||||
|
|
@ -10621,6 +10695,7 @@ class RootExports(object):
|
|||
context.session.assertLogin()
|
||||
if not context.opts.get('EnableMaven'):
|
||||
raise koji.GenericError("Maven support not enabled")
|
||||
check_value_type(builds, cast=list)
|
||||
taskOpts = {}
|
||||
if priority:
|
||||
if priority < 0:
|
||||
|
|
@ -10650,7 +10725,9 @@ class RootExports(object):
|
|||
context.session.assertLogin()
|
||||
if not context.opts.get('EnableWin'):
|
||||
raise koji.GenericError("Windows support not enabled")
|
||||
targ_info = self.getBuildTarget(target)
|
||||
check_value_type(vm, cast=str)
|
||||
check_value_type(url, cast=str)
|
||||
targ_info = get_build_target(target, strict=True)
|
||||
policy_data = {'vm_name': vm,
|
||||
'tag': targ_info['dest_tag']}
|
||||
assert_policy('vm', policy_data)
|
||||
|
|
@ -10676,6 +10753,8 @@ class RootExports(object):
|
|||
|
||||
if img_type not in ('livecd', 'appliance', 'livemedia'):
|
||||
raise koji.GenericError('Unrecognized image type: %s' % img_type)
|
||||
for i in [name, ksfile, version]:
|
||||
check_value_type(i, cast=str)
|
||||
|
||||
context.session.assertPerm(img_type)
|
||||
|
||||
|
|
@ -10723,6 +10802,8 @@ class RootExports(object):
|
|||
"""
|
||||
Create an image using a kickstart file and group package list.
|
||||
"""
|
||||
for i in [name, inst_tree, version]:
|
||||
check_value_type(i, cast=str)
|
||||
context.session.assertPerm('image')
|
||||
taskOpts = {'channel': 'image'}
|
||||
if priority:
|
||||
|
|
@ -10986,6 +11067,9 @@ class RootExports(object):
|
|||
def downloadTaskOutput(self, taskID, fileName, offset=0, size=-1, volume=None):
|
||||
"""Download the file with the given name, generated by the task with the
|
||||
given ID."""
|
||||
size = convert_value(size, cast=int)
|
||||
if volume:
|
||||
volume = self.getVolume(volume, strict=True)['name']
|
||||
if '..' in fileName:
|
||||
raise koji.GenericError('Invalid file name: %s' % fileName)
|
||||
filePath = '%s/%s/%s' % (koji.pathinfo.work(volume),
|
||||
|
|
@ -12493,6 +12577,7 @@ class RootExports(object):
|
|||
verify_name_internal(permission)
|
||||
if description is not None and not create:
|
||||
raise koji.GenericError('Description should be specified only with create.')
|
||||
check_value_type(description, cast=str, none_allowed=True)
|
||||
user_id = get_user(userinfo, strict=True)['id']
|
||||
perm = lookup_perm(permission, strict=(not create), create=create)
|
||||
perm_id = perm['id']
|
||||
|
|
@ -12526,6 +12611,7 @@ class RootExports(object):
|
|||
def editPermission(self, permission, description):
|
||||
"""Edit a permission description"""
|
||||
context.session.assertPerm('admin')
|
||||
check_value_type(description, cast=str)
|
||||
perm = lookup_perm(permission, strict=True)
|
||||
perm_id = perm['id']
|
||||
update = UpdateProcessor('permissions', clauses=['id=%(perm_id)i'],
|
||||
|
|
@ -12550,22 +12636,18 @@ class RootExports(object):
|
|||
raise koji.GenericError('user already exists: %s' % username)
|
||||
if krb_principal and get_user_by_krb_principal(krb_principal):
|
||||
raise koji.GenericError(
|
||||
'user with this Kerberos principal already exists: %s'
|
||||
% krb_principal)
|
||||
|
||||
return context.session.createUser(username, status=status,
|
||||
krb_principal=krb_principal)
|
||||
'user with this Kerberos principal already exists: %s' % krb_principal)
|
||||
status = convert_value(status, cast=int, none_allowed=True)
|
||||
return context.session.createUser(username, status=status, krb_principal=krb_principal)
|
||||
|
||||
def addUserKrbPrincipal(self, user, krb_principal):
|
||||
"""Add a Kerberos principal for user"""
|
||||
context.session.assertPerm('admin')
|
||||
userinfo = get_user(user, strict=True)
|
||||
if not krb_principal:
|
||||
raise koji.GenericError('krb_principal must be specified')
|
||||
verify_name_user(krb=krb_principal)
|
||||
if get_user_by_krb_principal(krb_principal):
|
||||
raise koji.GenericError(
|
||||
'user with this Kerberos principal already exists: %s'
|
||||
% krb_principal)
|
||||
'user with this Kerberos principal already exists: %s' % krb_principal)
|
||||
return context.session.setKrbPrincipal(userinfo['name'], krb_principal)
|
||||
|
||||
def removeUserKrbPrincipal(self, user, krb_principal):
|
||||
|
|
@ -13036,6 +13118,7 @@ class RootExports(object):
|
|||
# builder user can already exist, if host tried to log in before adding into db
|
||||
userinfo = {'name': hostname}
|
||||
if krb_principal:
|
||||
verify_name_user(krb=krb_principal)
|
||||
userinfo['krb_principal'] = krb_principal
|
||||
user = get_user(userInfo=userinfo)
|
||||
if user:
|
||||
|
|
@ -13757,6 +13840,7 @@ class BuildRoot(object):
|
|||
self.is_standard = True
|
||||
|
||||
def new(self, host, repo, arch, task_id=None, ctype='chroot'):
|
||||
arch = koji.parse_arches(arch, strict=True, allow_none=True)
|
||||
state = koji.BR_STATES['INIT']
|
||||
br_id = _singleValue("SELECT nextval('buildroot_id_seq')", strict=True)
|
||||
insert = InsertProcessor('buildroot', data={'id': br_id})
|
||||
|
|
@ -14016,7 +14100,7 @@ class Host(object):
|
|||
|
||||
def taskSetWait(self, parent, tasks):
|
||||
"""Mark task waiting and subtasks awaited"""
|
||||
|
||||
check_value_type(tasks, cast=list, none_allowed=True)
|
||||
# mark parent as waiting
|
||||
update = UpdateProcessor('task', clauses=['id=%(parent)s'], values=locals())
|
||||
update.set(waiting=True)
|
||||
|
|
@ -14134,6 +14218,7 @@ class Host(object):
|
|||
|
||||
def updateHost(self, task_load, ready):
|
||||
host_data = get_host(self.id)
|
||||
task_load = convert_value(task_load, cast=float)
|
||||
if task_load != host_data['task_load'] or ready != host_data['ready']:
|
||||
c = context.cnx.cursor()
|
||||
id = self.id
|
||||
|
|
@ -14416,6 +14501,7 @@ class HostExports(object):
|
|||
|
||||
def moveImageBuildToScratch(self, task_id, results):
|
||||
"""move a completed image scratch build into place"""
|
||||
check_value_type(results, cast=dict)
|
||||
host = Host()
|
||||
host.verify()
|
||||
task = Task(task_id)
|
||||
|
|
@ -14861,6 +14947,8 @@ class HostExports(object):
|
|||
pkg_id = build['package_id']
|
||||
tag_id = get_tag(tag, strict=True)['id']
|
||||
user_id = task.getOwner()
|
||||
if not isinstance(fromtag, str):
|
||||
tag = get_tag(tag, strict=True)['name']
|
||||
policy_data = {'tag': tag, 'build': build, 'fromtag': fromtag}
|
||||
policy_data['user_id'] = user_id
|
||||
if fromtag is None:
|
||||
|
|
@ -15156,6 +15244,7 @@ class HostExports(object):
|
|||
host = Host()
|
||||
host.verify()
|
||||
rinfo = repo_info(repo_id, strict=True)
|
||||
check_value_type(data, cast=dict)
|
||||
koji.plugin.run_callbacks('preRepoDone', repo=rinfo, data=data, expire=expire)
|
||||
if rinfo['state'] != koji.REPO_INIT:
|
||||
raise koji.GenericError("Repo %(id)s not in INIT state (got %(state)s)" % rinfo)
|
||||
|
|
|
|||
|
|
@ -18,10 +18,19 @@ koji.tasks.LEGACY_SIGNATURES['createKiwiImage'] = [
|
|||
def kiwiBuild(target, arches, desc_url, desc_path, optional_arches=None, profile=None,
|
||||
scratch=False, priority=None, make_prep=False, repos=None, release=None):
|
||||
context.session.assertPerm('image')
|
||||
for i in [desc_url, desc_path, profile, release]:
|
||||
if i is not None:
|
||||
kojihub.check_value_type(i, cast=str)
|
||||
if repos:
|
||||
kojihub.check_value_type(repos, cast=list)
|
||||
kojihub.get_build_targets(target, strict=True)
|
||||
arches = koji.parse_arches(arches, strict=True, allow_none=False)
|
||||
optional_arches = koji.parse_arches(optional_arches, strict=True, allow_none=True)
|
||||
taskOpts = {
|
||||
'channel': 'image',
|
||||
}
|
||||
if priority:
|
||||
priority = kojihub.convert_value(priority, cast=int)
|
||||
if priority < 0:
|
||||
if not context.session.hasPerm('admin'):
|
||||
raise koji.ActionNotAllowed(
|
||||
|
|
@ -31,10 +40,10 @@ def kiwiBuild(target, arches, desc_url, desc_path, optional_arches=None, profile
|
|||
opts = {
|
||||
'optional_arches': optional_arches,
|
||||
'profile': profile,
|
||||
'scratch': scratch,
|
||||
'scratch': bool(scratch),
|
||||
'release': release,
|
||||
'repos': repos or [],
|
||||
'make_prep': make_prep,
|
||||
'make_prep': bool(make_prep),
|
||||
}
|
||||
return kojihub.make_task('kiwiBuild',
|
||||
[target, arches, desc_url, desc_path, opts],
|
||||
|
|
|
|||
|
|
@ -30,12 +30,17 @@ def get_channel_arches(channel):
|
|||
def runroot(tagInfo, arch, command, channel=None, **opts):
|
||||
""" Create a runroot task """
|
||||
context.session.assertPerm('runroot')
|
||||
arch = koji.parse_arches(arch, strict=True, allow_none=False)
|
||||
kojihub.check_value_type(command, cast=str)
|
||||
taskopts = {
|
||||
'priority': 15,
|
||||
'arch': arch,
|
||||
}
|
||||
|
||||
taskopts['channel'] = channel or 'runroot'
|
||||
if channel is None:
|
||||
taskopts['channel'] = 'runroot'
|
||||
else:
|
||||
taskopts['channel'] = kojihub.get_channel(channel, strict=True)['name']
|
||||
|
||||
tag = kojihub.get_tag(tagInfo, strict=True)
|
||||
if arch == 'noarch':
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ def saveFailedTree(buildrootID, full=False, **opts):
|
|||
global config, allowed_methods
|
||||
|
||||
# let it raise errors
|
||||
buildrootID = int(buildrootID)
|
||||
buildrootID = kojihub.convert_value(buildrootID, cast=int)
|
||||
full = bool(full)
|
||||
|
||||
# read configuration only once
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ from kojihub import ( # noqa: E402
|
|||
get_tag,
|
||||
get_user,
|
||||
nextval,
|
||||
policy_get_user
|
||||
policy_get_user,
|
||||
check_value_type
|
||||
)
|
||||
|
||||
CONFIG_FILE = "/etc/koji-hub/plugins/sidetag.conf"
|
||||
|
|
@ -270,9 +271,11 @@ def editSideTag(sidetag, debuginfo=None, rpm_macros=None, remove_rpm_macros=None
|
|||
if debuginfo is not None:
|
||||
kwargs['extra']['with_debuginfo'] = bool(debuginfo)
|
||||
if rpm_macros is not None:
|
||||
check_value_type(rpm_macros, cast=dict)
|
||||
for macro, value in rpm_macros.items():
|
||||
kwargs['extra']['rpm.macro.%s' % macro] = value
|
||||
if remove_rpm_macros is not None:
|
||||
check_value_type(remove_rpm_macros, cast=list)
|
||||
kwargs['remove_extra'] = ['rpm.macro.%s' % m for m in remove_rpm_macros]
|
||||
|
||||
_edit_tag(sidetag['id'], **kwargs)
|
||||
|
|
|
|||
|
|
@ -10,54 +10,74 @@ IP = kojihub.InsertProcessor
|
|||
|
||||
class TestAddArchiveType(unittest.TestCase):
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub._multiRow')
|
||||
@mock.patch('kojihub.get_archive_type')
|
||||
@mock.patch('kojihub.InsertProcessor')
|
||||
def test_add_archive_type(self, InsertProcessor, get_archive_type, _multiRow,
|
||||
verify_name_internal):
|
||||
# Not sure why mock can't patch kojihub.context, so we do this
|
||||
session = kojihub.context.session = mock.MagicMock()
|
||||
mocks = [InsertProcessor, get_archive_type, session]
|
||||
# It seems MagicMock will not automatically handle attributes that
|
||||
# start with "assert"
|
||||
session.assertPerm = mock.MagicMock()
|
||||
verify_name_internal.return_value = None
|
||||
def setUp(self):
|
||||
|
||||
# expected case
|
||||
get_archive_type.return_value = None
|
||||
insert = InsertProcessor.return_value
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.channel_name = 'test-channel'
|
||||
self.description = 'test-description'
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.insert_execute = mock.MagicMock()
|
||||
self.verify_name_internal = mock.patch('kojihub.verify_name_internal').start()
|
||||
self.get_archive_type = mock.patch('kojihub.get_archive_type').start()
|
||||
self._multiRow = mock.patch('kojihub._multiRow').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = self.insert_execute
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def test_add_archive_type_valid(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
self.get_archive_type.return_value = None
|
||||
kojihub.add_archive_type('deb', 'Debian package', 'deb')
|
||||
InsertProcessor.assert_called_once()
|
||||
insert.execute.assert_called_once()
|
||||
|
||||
args, kwargs = InsertProcessor.call_args
|
||||
ip = IP(*args, **kwargs)
|
||||
self.assertEqual(ip.table, 'archivetypes')
|
||||
self.assertEqual(ip.data, {'name': 'deb',
|
||||
'description': 'Debian package',
|
||||
'extensions': 'deb'})
|
||||
self.assertEqual(ip.rawdata, {})
|
||||
session.assertPerm.assert_called_with('admin')
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
self.assertEqual(insert.table, 'archivetypes')
|
||||
self.assertEqual(insert.data, {'name': 'deb',
|
||||
'description': 'Debian package',
|
||||
'extensions': 'deb'})
|
||||
self.assertEqual(insert.rawdata, {})
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
||||
for m in mocks:
|
||||
m.reset_mock()
|
||||
session.assertPerm = mock.MagicMock()
|
||||
|
||||
# already exists
|
||||
get_archive_type.return_value = True
|
||||
def test_add_archive_type_already_exists(self):
|
||||
self.get_archive_type.return_value = True
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.add_archive_type('deb', 'Debian package', 'deb')
|
||||
InsertProcessor.assert_not_called()
|
||||
session.assertPerm.assert_called_with('admin')
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
||||
def test_add_archive_type_invalid_value_type(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
description = ['Debian package']
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
kojihub.add_archive_type('deb', description, 'deb')
|
||||
self.assertEqual(f"Invalid type for value '{description}': {type(description)}",
|
||||
str(ex.exception))
|
||||
|
||||
def test_add_archive_type_invalid_value_extensions(self):
|
||||
extensions = ['deb']
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
kojihub.add_archive_type('deb', 'Debian package', extensions)
|
||||
self.assertEqual(f"Invalid type for value '{extensions}': {type(extensions)}",
|
||||
str(ex.exception))
|
||||
|
||||
def test_add_archive_type_wrong_name_verify(self):
|
||||
# name is longer as expected
|
||||
new_archive_type = 'new-archive-type+'
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.add_archive_type(new_archive_type, 'Debian package', 'deb')
|
||||
|
||||
# not except regex rules
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.add_archive_type(new_archive_type, 'Debian package', 'deb')
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ class TestAddChannel(unittest.TestCase):
|
|||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.insert_execute = mock.MagicMock()
|
||||
self.verify_name_internal = mock.patch('kojihub.verify_name_internal').start()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self._singleValue = mock.patch('kojihub._singleValue').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
|
@ -32,25 +35,19 @@ class TestAddChannel(unittest.TestCase):
|
|||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_channel_exists(self, _singleValue, get_channel, verify_name_internal):
|
||||
verify_name_internal.return_value = None
|
||||
get_channel.return_value = {'id': 123, 'name': self.channel_name}
|
||||
def test_add_channel_exists(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
self.get_channel.return_value = {'id': 123, 'name': self.channel_name}
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addChannel(self.channel_name)
|
||||
get_channel.assert_called_once_with(self.channel_name, strict=False)
|
||||
_singleValue.assert_not_called()
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=False)
|
||||
self._singleValue.assert_not_called()
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_channel_valid(self, _singleValue, get_channel, verify_name_internal):
|
||||
get_channel.return_value = {}
|
||||
_singleValue.side_effect = [12]
|
||||
verify_name_internal.return_value = None
|
||||
def test_add_channel_valid(self):
|
||||
self.get_channel.return_value = {}
|
||||
self._singleValue.side_effect = [12]
|
||||
self.verify_name_internal.return_value = None
|
||||
|
||||
r = self.exports.addChannel(self.channel_name, description=self.description)
|
||||
self.assertEqual(r, 12)
|
||||
|
|
@ -62,21 +59,20 @@ class TestAddChannel(unittest.TestCase):
|
|||
self.assertEqual(insert.table, 'channels')
|
||||
|
||||
self.context.session.assertPerm.assert_called_once_with('admin')
|
||||
get_channel.assert_called_once_with(self.channel_name, strict=False)
|
||||
self.assertEqual(_singleValue.call_count, 1)
|
||||
_singleValue.assert_has_calls([
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=False)
|
||||
self.assertEqual(self._singleValue.call_count, 1)
|
||||
self._singleValue.assert_has_calls([
|
||||
mock.call("SELECT nextval('channels_id_seq')", strict=True)
|
||||
])
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
def test_add_channel_wrong_format(self, verify_name_internal):
|
||||
def test_add_channel_wrong_name(self):
|
||||
# name is longer as expected
|
||||
channel_name = 'test-channel+'
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addChannel(channel_name)
|
||||
|
||||
# not except regex rules
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addChannel(channel_name)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
|
@ -6,8 +7,26 @@ import kojihub
|
|||
|
||||
class TestAddExternalRepoToTag(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tag_name = 'test-tag'
|
||||
self.get_tag = mock.patch('kojihub.get_tag').start()
|
||||
self.get_external_repo = mock.patch('kojihub.get_external_repo').start()
|
||||
self.tag_info = {'id': 1, 'name': self.tag_name}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_with_wrong_merge_mode(self):
|
||||
merge_mode = 'test-mode'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.add_external_repo_to_tag('tag', 'repo', 1, merge_mode=merge_mode)
|
||||
self.assertEqual('No such merge mode: %s' % merge_mode, str(cm.exception))
|
||||
kojihub.add_external_repo_to_tag(self.tag_name, 'repo', 1, merge_mode=merge_mode)
|
||||
self.assertEqual(f"No such merge mode: {merge_mode}", str(cm.exception))
|
||||
|
||||
def test_priority_not_int(self):
|
||||
priority = 'test-priority'
|
||||
self.get_tag.return_value = self.tag_info
|
||||
self.get_external_repo.return_value = {'id': 123}
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.add_external_repo_to_tag(self.tag_name, 'repo', priority, merge_mode=None)
|
||||
self.assertEqual(f"Invalid type for value '{priority}': {type(priority)}",
|
||||
str(cm.exception))
|
||||
|
|
|
|||
|
|
@ -20,20 +20,20 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
self.nextval = mock.patch('kojihub.nextval').start()
|
||||
self.Savepoint = mock.patch('kojihub.Savepoint').start()
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.insert_execute = mock.MagicMock()
|
||||
|
||||
self.rpminfo = {
|
||||
'name': 'NAME',
|
||||
'version': 'VERSION',
|
||||
'release': 'RELEASE',
|
||||
'epoch': None,
|
||||
'arch': 'noarch',
|
||||
'payloadhash': 'fakehash',
|
||||
'size': 42,
|
||||
'buildtime': 0,
|
||||
}
|
||||
'name': 'NAME',
|
||||
'version': 'VERSION',
|
||||
'release': 'RELEASE',
|
||||
'epoch': None,
|
||||
'arch': 'noarch',
|
||||
'payloadhash': 'fakehash',
|
||||
'size': 42,
|
||||
'buildtime': 0,
|
||||
}
|
||||
self.repo = 'myrepo'
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -63,8 +63,9 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
rpminfo = self.rpminfo.copy()
|
||||
del rpminfo['size']
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(rpminfo, self.repo)
|
||||
self.assertEqual(f"size field missing: {rpminfo}", str(ex.exception))
|
||||
|
||||
self.get_rpm.assert_not_called()
|
||||
self.nextval.assert_not_called()
|
||||
|
|
@ -73,8 +74,10 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
rpminfo = self.rpminfo.copy()
|
||||
rpminfo['size'] = ['invalid type']
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(rpminfo, self.repo)
|
||||
self.assertEqual(f"Invalid value for size: {rpminfo['size']}",
|
||||
str(ex.exception))
|
||||
|
||||
self.get_rpm.assert_not_called()
|
||||
self.nextval.assert_not_called()
|
||||
|
|
@ -88,8 +91,11 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
self.get_external_repo_id.return_value = mock.sentinel.repo_id
|
||||
|
||||
# call it (default is strict)
|
||||
with self.assertRaises(koji.GenericError):
|
||||
nvra = "%(name)s-%(version)s-%(release)s.%(arch)s" % self.rpminfo
|
||||
disp = f"{nvra}@{self.repo}"
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(self.rpminfo, self.repo)
|
||||
self.assertEqual(f"external rpm already exists: {disp}", str(ex.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.nextval.assert_not_called()
|
||||
|
|
@ -103,8 +109,12 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
|
||||
# different hash
|
||||
prev['payloadhash'] = 'different hash'
|
||||
with self.assertRaises(koji.GenericError):
|
||||
nvra = "%(name)s-%(version)s-%(release)s.%(arch)s" % self.rpminfo
|
||||
disp = f"{nvra}@{self.repo}"
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False)
|
||||
self.assertEqual(f"hash changed for external rpm: {disp} (different hash -> fakehash)",
|
||||
str(ex.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.nextval.assert_not_called()
|
||||
|
|
@ -118,8 +128,11 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
self.insert_execute.side_effect = FakeException('insert failed')
|
||||
|
||||
# call it (default is strict)
|
||||
with self.assertRaises(koji.GenericError):
|
||||
nvra = "%(name)s-%(version)s-%(release)s.%(arch)s" % self.rpminfo
|
||||
disp = f"{nvra}@{self.repo}"
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(self.rpminfo, self.repo)
|
||||
self.assertEqual(f"external rpm already exists: {disp}", str(ex.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
self.nextval.assert_called_once()
|
||||
|
|
@ -139,8 +152,12 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
self.nextval.reset_mock()
|
||||
self.get_rpm.side_effect = [None, prev]
|
||||
prev['payloadhash'] = 'different hash'
|
||||
with self.assertRaises(koji.GenericError):
|
||||
nvra = "%(name)s-%(version)s-%(release)s.%(arch)s" % self.rpminfo
|
||||
disp = f"{nvra}@{self.repo}"
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False)
|
||||
self.assertEqual(f"hash changed for external rpm: {disp} (different hash -> fakehash)",
|
||||
str(ex.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
self.nextval.assert_called_once()
|
||||
|
|
@ -149,10 +166,9 @@ class TestAddExternalRPM(unittest.TestCase):
|
|||
self.inserts[:] = []
|
||||
self.nextval.reset_mock()
|
||||
self.get_rpm.side_effect = [None, None]
|
||||
with self.assertRaises(FakeException):
|
||||
with self.assertRaises(FakeException) as ex:
|
||||
kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False)
|
||||
self.assertEqual('insert failed', str(ex.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
self.nextval.assert_called_once()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,32 +36,31 @@ class TestAddHost(unittest.TestCase):
|
|||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.context.opts = {'HostPrincipalFormat': '-%s-'}
|
||||
self.exports = kojihub.RootExports()
|
||||
self.verify_host_name = mock.patch('kojihub.verify_host_name').start()
|
||||
self.verify_name_user = mock.patch('kojihub.verify_name_user').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self.get_host = mock.patch('kojihub.get_host').start()
|
||||
self._singleValue = mock.patch('kojihub._singleValue').start()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub.get_host')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_host_exists(self, _singleValue, get_host, _dml, verify_host_name):
|
||||
verify_host_name.return_value = None
|
||||
get_host.return_value = {'id': 123}
|
||||
def test_add_host_exists(self):
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_host.return_value = {'id': 123}
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost('hostname', ['i386', 'x86_64'])
|
||||
_dml.assert_not_called()
|
||||
get_host.assert_called_once_with('hostname')
|
||||
_singleValue.assert_not_called()
|
||||
self._dml.assert_not_called()
|
||||
self.get_host.assert_called_once_with('hostname')
|
||||
self._singleValue.assert_not_called()
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub.get_host')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_host_valid(self, _singleValue, get_host, _dml, verify_host_name):
|
||||
verify_host_name.return_value = None
|
||||
get_host.return_value = {}
|
||||
_singleValue.side_effect = [333, 12]
|
||||
def test_add_host_valid(self):
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_host.return_value = {}
|
||||
self._singleValue.side_effect = [333, 12]
|
||||
self.context.session.createUser.return_value = 456
|
||||
self.get_user.return_value = None
|
||||
|
||||
r = self.exports.addHost('hostname', ['i386', 'x86_64'])
|
||||
self.assertEqual(r, 12)
|
||||
|
|
@ -70,59 +69,48 @@ class TestAddHost(unittest.TestCase):
|
|||
kojihub.get_host.assert_called_once_with('hostname')
|
||||
self.context.session.createUser.assert_called_once_with(
|
||||
'hostname', usertype=koji.USERTYPES['HOST'], krb_principal='-hostname-')
|
||||
self.assertEqual(_singleValue.call_count, 2)
|
||||
_singleValue.assert_has_calls([
|
||||
self.assertEqual(self._singleValue.call_count, 2)
|
||||
self._singleValue.assert_has_calls([
|
||||
mock.call("SELECT id FROM channels WHERE name = 'default'"),
|
||||
mock.call("SELECT nextval('host_id_seq')", strict=True)
|
||||
])
|
||||
self.assertEqual(_dml.call_count, 1)
|
||||
_dml.assert_called_once_with("INSERT INTO host (id, user_id, name) "
|
||||
"VALUES (%(hostID)i, %(userID)i, %(hostname)s)",
|
||||
{'hostID': 12, 'userID': 456, 'hostname': 'hostname'})
|
||||
self.assertEqual(self._dml.call_count, 1)
|
||||
self._dml.assert_called_once_with("INSERT INTO host (id, user_id, name) "
|
||||
"VALUES (%(hostID)i, %(userID)i, %(hostname)s)",
|
||||
{'hostID': 12, 'userID': 456, 'hostname': 'hostname'})
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub.get_host')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_host_wrong_user(self, _singleValue, get_host, _dml, get_user, verify_host_name):
|
||||
verify_host_name.return_value = None
|
||||
get_user.return_value = {
|
||||
def test_add_host_wrong_user(self):
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_user.return_value = {
|
||||
'id': 1,
|
||||
'name': 'hostname',
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
get_host.return_value = {}
|
||||
self.get_host.return_value = {}
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost('hostname', ['i386', 'x86_64'])
|
||||
_dml.assert_not_called()
|
||||
get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
get_host.assert_called_once_with('hostname')
|
||||
_singleValue.assert_called_once()
|
||||
self._dml.assert_not_called()
|
||||
self.get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
self.get_host.assert_called_once_with('hostname')
|
||||
self._singleValue.assert_called_once()
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub.get_host')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_host_wrong_user_forced(self, _singleValue, get_host, _dml, get_user,
|
||||
verify_host_name):
|
||||
verify_host_name.return_value = None
|
||||
get_user.return_value = {
|
||||
def test_add_host_wrong_user_forced(self):
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_user.return_value = {
|
||||
'id': 123,
|
||||
'name': 'hostname',
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
get_host.return_value = {}
|
||||
self.get_host.return_value = {}
|
||||
|
||||
self.exports.addHost('hostname', ['i386', 'x86_64'], force=True)
|
||||
|
||||
_dml.assert_called_once()
|
||||
get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
get_host.assert_called_once_with('hostname')
|
||||
_singleValue.assert_called()
|
||||
self._dml.assert_called_once()
|
||||
self.get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
self.get_host.assert_called_once_with('hostname')
|
||||
self._singleValue.assert_called()
|
||||
self.assertEqual(len(self.inserts), 2)
|
||||
self.assertEqual(len(self.updates), 1)
|
||||
update = self.updates[0]
|
||||
|
|
@ -131,40 +119,50 @@ class TestAddHost(unittest.TestCase):
|
|||
self.assertEqual(update.clauses, ['id = %(userID)i'])
|
||||
self.assertEqual(update.data, {'usertype': koji.USERTYPES['HOST']})
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub.get_host')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
def test_add_host_superwrong_user_forced(self, _singleValue, get_host, _dml, get_user,
|
||||
verify_host_name):
|
||||
verify_host_name.return_value = None
|
||||
get_user.return_value = {
|
||||
def test_add_host_superwrong_user_forced(self):
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_user.return_value = {
|
||||
'id': 123,
|
||||
'name': 'hostname',
|
||||
'usertype': koji.USERTYPES['GROUP']
|
||||
}
|
||||
get_host.return_value = {}
|
||||
self.get_host.return_value = {}
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost('hostname', ['i386', 'x86_64'], force=True)
|
||||
|
||||
_dml.assert_not_called()
|
||||
get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
get_host.assert_called_once_with('hostname')
|
||||
_singleValue.assert_called()
|
||||
self._dml.assert_not_called()
|
||||
self.get_user.assert_called_once_with(userInfo={'name': 'hostname'})
|
||||
self.get_host.assert_called_once_with('hostname')
|
||||
self._singleValue.assert_called()
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.verify_host_name')
|
||||
def test_add_host_wrong_format(self, verify_host_name):
|
||||
def test_add_host_wrong_format(self):
|
||||
# name is longer as expected
|
||||
hostname = 'host-name+'
|
||||
verify_host_name.side_effect = koji.GenericError
|
||||
self.verify_host_name.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost(hostname, ['i386', 'x86_64'], force=True)
|
||||
|
||||
# not except regex rules
|
||||
verify_host_name.side_effect = koji.GenericError
|
||||
self.verify_host_name.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost(hostname, ['i386', 'x86_64'], force=True)
|
||||
|
||||
def test_add_host_krbprincipal_wrong_type(self):
|
||||
krb_principal = ['test-krb']
|
||||
self.verify_host_name.return_value = None
|
||||
self.get_host.return_value = {}
|
||||
self._singleValue.side_effect = [333, 12]
|
||||
self.verify_name_user.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.addHost('hostname', ['i386', 'x86_64'], krb_principal=krb_principal)
|
||||
|
||||
self.context.session.assertPerm.assert_called_once_with('host')
|
||||
kojihub.get_host.assert_called_once_with('hostname')
|
||||
self.context.session.createUser.assert_not_called()
|
||||
self.assertEqual(self._singleValue.call_count, 1)
|
||||
self._singleValue.assert_called_once_with("SELECT id FROM channels WHERE name = 'default'")
|
||||
self.verify_host_name.assert_called_once_with('hostname')
|
||||
self.verify_name_user.assert_called_once_with(krb=krb_principal)
|
||||
|
|
|
|||
42
tests/test_hub/test_add_user_krb_principal.py
Normal file
42
tests/test_hub/test_add_user_krb_principal.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import copy
|
||||
|
||||
|
||||
class TestAddUserKrbPrincipal(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self.verify_name_user = mock.patch('kojihub.verify_name_user').start()
|
||||
self.get_user_by_krb_principal = mock.patch('kojihub.get_user_by_krb_principal').start()
|
||||
self.username = 'testuser'
|
||||
self.krbprincipal = '%s@TEST.COM' % self.username
|
||||
self.userinfo = {'id': 1, 'name': self.username}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_non_exist_user(self):
|
||||
self.get_user.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.RootExports().addUserKrbPrincipal(self.username, self.krbprincipal)
|
||||
|
||||
def test_wrong_krbprincipal_format(self):
|
||||
krbprincipal = 'test-krbprincipal+'
|
||||
self.get_user.return_value = self.userinfo
|
||||
self.verify_name_user.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.RootExports().addUserKrbPrincipal(self.username, krbprincipal)
|
||||
|
||||
def test_existing_krb(self):
|
||||
userinfo = copy.deepcopy(self.userinfo)
|
||||
userinfo['krb_principal'] = self.krbprincipal
|
||||
self.get_user.return_value = self.userinfo
|
||||
self.verify_name_user.return_value = None
|
||||
self.get_user_by_krb_principal.return_value = userinfo
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.RootExports().addUserKrbPrincipal(self.username, self.krbprincipal)
|
||||
self.assertEqual('user with this Kerberos principal already exists: %s'
|
||||
% self.krbprincipal, str(ex.exception))
|
||||
40
tests/test_hub/test_build.py
Normal file
40
tests/test_hub/test_build.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestBuild(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.src = 'test-src'
|
||||
self.target = 'test-target'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_src_wrong_type(self):
|
||||
src = ['test-priority']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.build(src, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{src}': {type(src)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.build(self.src, self.target, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
priority = 10
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 2, 'name': 'maven'}
|
||||
self.make_task.return_value = 123
|
||||
self.exports.build(self.src, self.target, priority=priority, channel=2)
|
||||
69
tests/test_hub/test_build_image.py
Normal file
69
tests/test_hub/test_build_image.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestBuildImage(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.mock_parse_arches = mock.patch('koji.parse_arches').start()
|
||||
self.name = 'image-name'
|
||||
self.version = 'test-version'
|
||||
self.arch = 'x86_64'
|
||||
self.target = 'test-target'
|
||||
self.ksfile = 'test-ksfile'
|
||||
self.image_type = 'livecd'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_img_type_not_supported(self):
|
||||
image_type = 'test-type'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.buildImage(self.name, self.version, self.arch, self.target,
|
||||
self.ksfile, image_type)
|
||||
self.assertEqual(f"Unrecognized image type: {image_type}", str(cm.exception))
|
||||
|
||||
def test_name_wrong_type(self):
|
||||
name = ['test-name']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.buildImage(name, self.version, self.arch, self.target, self.ksfile,
|
||||
self.image_type)
|
||||
self.assertEqual(f"Invalid type for value '{name}': {type(name)}", str(cm.exception))
|
||||
|
||||
def test_version_wrong_type(self):
|
||||
version = ['test-version']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.buildImage(self.name, version, self.arch, self.target, self.ksfile,
|
||||
self.image_type)
|
||||
self.assertEqual(f"Invalid type for value '{version}': {type(version)}", str(cm.exception))
|
||||
|
||||
def test_ksfile_wrong_type(self):
|
||||
ksfile = ['test-ksfile']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.buildImage(self.name, self.version, self.arch, self.target, ksfile,
|
||||
self.image_type)
|
||||
self.assertEqual(f"Invalid type for value '{ksfile}': {type(ksfile)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
image_type = 'livemedia'
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.ActionNotAllowed) as cm:
|
||||
self.exports.buildImage(self.name, self.version, self.arch, self.target, self.ksfile,
|
||||
image_type, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_valid(self):
|
||||
priority = 10
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
self.make_task.return_value = 123
|
||||
self.exports.buildImage(self.name, self.version, self.arch, self.target, self.ksfile,
|
||||
self.image_type, priority=priority)
|
||||
33
tests/test_hub/test_build_image_indirection.py
Normal file
33
tests/test_hub/test_build_image_indirection.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestBuildImageIndirection(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.ActionNotAllowed) as cm:
|
||||
self.exports.buildImageIndirection(priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_opts_without_expected_keys(self):
|
||||
priority = 10
|
||||
opts = {}
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
with self.assertRaises(koji.ActionNotAllowed) as cm:
|
||||
self.exports.buildImageIndirection(opts=opts, priority=priority)
|
||||
self.assertEqual("Non-scratch builds must provide url for the indirection template",
|
||||
str(cm.exception))
|
||||
59
tests/test_hub/test_build_image_oz.py
Normal file
59
tests/test_hub/test_build_image_oz.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestBuildImageOz(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.parse_arches = mock.patch('koji.parse_arches').start()
|
||||
self.name = 'image-name'
|
||||
self.version = 'test-version'
|
||||
self.arches = ['x86_64', 'i386']
|
||||
self.target = 'test-target'
|
||||
self.inst_tree = 'test-tree'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_name_wrong_type(self):
|
||||
name = ['image-name']
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.buildImageOz(name, self.version, self.arches, self.target, self.inst_tree)
|
||||
self.assertEqual(f"Invalid type for value '{name}': {type(name)}", str(cm.exception))
|
||||
|
||||
def test_inst_tree_wrong_type(self):
|
||||
inst_tree = ['test-tree']
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.buildImageOz(self.name, self.version, self.arches, self.target, inst_tree)
|
||||
self.assertEqual(f"Invalid type for value '{inst_tree}': {type(inst_tree)}",
|
||||
str(cm.exception))
|
||||
|
||||
def test_version_wrong_type(self):
|
||||
version = ['test-version']
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.buildImageOz(self.name, version, self.arches, self.target, self.inst_tree)
|
||||
self.assertEqual(f"Invalid type for value '{version}': {type(version)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.ActionNotAllowed) as cm:
|
||||
self.exports.buildImageOz(self.name, self.version, self.arches, self.target,
|
||||
self.inst_tree, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_opts_without_expected_keys(self):
|
||||
priority = 10
|
||||
opts = {}
|
||||
self.context.session.assertPerm.side_effect = None
|
||||
with self.assertRaises(koji.ActionNotAllowed) as cm:
|
||||
self.exports.buildImageOz(self.name, self.version, self.arches, self.target,
|
||||
self.inst_tree, opts=opts, priority=priority)
|
||||
self.assertEqual("Non-scratch builds must provide ksurl", str(cm.exception))
|
||||
|
|
@ -10,6 +10,7 @@ from koji import GenericError
|
|||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestCGImporter(unittest.TestCase):
|
||||
TMP_PATH = os.path.join(os.path.dirname(__file__), 'tmptest')
|
||||
|
||||
|
|
@ -36,7 +37,8 @@ class TestCGImporter(unittest.TestCase):
|
|||
metadata = 42
|
||||
with self.assertRaises(GenericError) as ex:
|
||||
x.get_metadata(metadata, '')
|
||||
self.assertEqual('Invalid type for metadata value: %s' % type(metadata), str(ex.exception))
|
||||
self.assertEqual(f"Invalid type for value '{metadata}': {type(metadata)}",
|
||||
str(ex.exception))
|
||||
|
||||
def test_get_metadata_is_none(self):
|
||||
x = kojihub.CG_Importer()
|
||||
|
|
@ -158,7 +160,7 @@ class TestCGImporter(unittest.TestCase):
|
|||
'start_time': None, 'start_ts': None,
|
||||
'completion_time': None, 'completion_ts': None,
|
||||
'source': 'https://example.com', 'extra': {}
|
||||
}
|
||||
}
|
||||
new_build_id.return_value = 43
|
||||
x.get_build()
|
||||
assert x.buildinfo
|
||||
|
|
@ -187,7 +189,7 @@ class TestCGImporter(unittest.TestCase):
|
|||
get_metadata.return_value = metadata
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
x.do_import(metadata, '/test/dir')
|
||||
self.assertEqual('No such metadata version: %s' % metadata['metadata_version'],
|
||||
self.assertEqual(f"No such metadata version: {metadata['metadata_version']}",
|
||||
str(ex.exception))
|
||||
|
||||
def test_match_componemt_wrong_component(self):
|
||||
|
|
@ -195,7 +197,7 @@ class TestCGImporter(unittest.TestCase):
|
|||
components = [{'type': 'type'}]
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
x.match_components(components)
|
||||
self.assertEqual('No such component type: %s' % components[0]['type'], str(ex.exception))
|
||||
self.assertEqual(f"No such component type: {components[0]['type']}", str(ex.exception))
|
||||
|
||||
|
||||
class TestMatchKojiFile(unittest.TestCase):
|
||||
|
|
@ -203,23 +205,23 @@ class TestMatchKojiFile(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.importer = kojihub.CG_Importer()
|
||||
self.archive1 = {
|
||||
'id': 99,
|
||||
'build_id': 42,
|
||||
'checksum': 'e1f95555eae04b8e1ebdc5555c5555f0',
|
||||
'checksum_type': 0,
|
||||
'filename': 'foo-bar-3.0.jar',
|
||||
'size': 42710,
|
||||
}
|
||||
'id': 99,
|
||||
'build_id': 42,
|
||||
'checksum': 'e1f95555eae04b8e1ebdc5555c5555f0',
|
||||
'checksum_type': 0,
|
||||
'filename': 'foo-bar-3.0.jar',
|
||||
'size': 42710,
|
||||
}
|
||||
self.build1 = {
|
||||
'id': 79218,
|
||||
'nvr': 'foo-3.0-1',
|
||||
}
|
||||
'id': 79218,
|
||||
'nvr': 'foo-3.0-1',
|
||||
}
|
||||
self.comp1 = {
|
||||
'type': 'kojifile',
|
||||
'archive_id': self.archive1['id'],
|
||||
'nvr': self.build1['nvr'],
|
||||
'filename': self.archive1['filename'],
|
||||
}
|
||||
'type': 'kojifile',
|
||||
'archive_id': self.archive1['id'],
|
||||
'nvr': self.build1['nvr'],
|
||||
'filename': self.archive1['filename'],
|
||||
}
|
||||
self.get_archive = mock.patch('kojihub.get_archive').start()
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
|
||||
|
|
@ -270,7 +272,6 @@ class TestCGReservation(unittest.TestCase):
|
|||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
|
|
@ -298,8 +299,8 @@ class TestCGReservation(unittest.TestCase):
|
|||
new_build.return_value = 654
|
||||
cg = 'content_generator_name'
|
||||
self.mock_cursor.fetchone.side_effect = [
|
||||
[333], # get pkg_id
|
||||
[1234], # get nextval pkg_id
|
||||
[333], # get pkg_id
|
||||
[1234], # get nextval pkg_id
|
||||
]
|
||||
self.mock_cursor.fetchall.side_effect = [
|
||||
[[]],
|
||||
|
|
|
|||
40
tests/test_hub/test_chain_build.py
Normal file
40
tests/test_hub/test_chain_build.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestChainBuild(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.srcs = ['pkg1']
|
||||
self.target = 'test-target'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_srcs_wrong_type(self):
|
||||
srcs = 'pkg'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.chainBuild(srcs, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{srcs}': {type(srcs)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.chainBuild(self.srcs, self.target, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
priority = 10
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 2, 'name': 'maven'}
|
||||
self.make_task.return_value = 123
|
||||
self.exports.chainBuild(self.srcs, self.target, priority=priority, channel=2)
|
||||
48
tests/test_hub/test_chain_maven.py
Normal file
48
tests/test_hub/test_chain_maven.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestChainMaven(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.builds = ['build1', 'build2', 'build3']
|
||||
self.target = 'test-target'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_maven_not_supported(self):
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.chainMaven(self.builds, self.target)
|
||||
self.assertEqual("Maven support not enabled", str(cm.exception))
|
||||
|
||||
def test_builds_wrong_type(self):
|
||||
builds = 'test-builds'
|
||||
self.context.opts.get.return_value = True
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.chainMaven(builds, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{builds}': {type(builds)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.opts.get.return_value = True
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.chainMaven(self.builds, self.target, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
self.context.opts.get.return_value = True
|
||||
self.make_task.return_value = 123
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 2, 'name': 'maven'}
|
||||
self.exports.chainMaven(self.builds, self.target, channel=2, priority=10)
|
||||
|
|
@ -4,57 +4,168 @@ import mock
|
|||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestCreateNotification(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self.get_build_notifications = mock.patch('kojihub.get_build_notifications').start()
|
||||
self.get_tag_id = mock.patch('kojihub.get_tag_id').start()
|
||||
self.get_package_id = mock.patch('kojihub.get_package_id').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports.getUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.cursor = mock.MagicMock()
|
||||
self.user_id = 1
|
||||
self.package_id = 345
|
||||
self.tag_id = 345
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_createNotification(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'username'}
|
||||
self.exports.hasPerm.return_value = True
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notifications.return_value = []
|
||||
|
||||
r = self.exports.createNotification(
|
||||
self.user_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.getUser.asssert_called_once_with(self.user_id)
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
self.get_package_id.assert_called_once_with(self.package_id, strict=True)
|
||||
self.get_tag_id.assert_called_once_with(self.tag_id, strict=True)
|
||||
self.get_build_notifications.assert_called_once_with(2)
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
self.assertEqual(insert.table, 'build_notifications')
|
||||
self.assertEqual(insert.data, {
|
||||
'package_id': self.package_id,
|
||||
'user_id': 2,
|
||||
'tag_id': self.tag_id,
|
||||
'success_only': success_only,
|
||||
'email': 'username@test.domain.com',
|
||||
})
|
||||
self.assertEqual(insert.rawdata, {})
|
||||
|
||||
def test_createNotification_unauthentized(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
def test_non_exist_user(self):
|
||||
user_id = 999
|
||||
package_id = 555
|
||||
tag_id = 111
|
||||
success_only = False
|
||||
logged_user = {'authtype': 2,
|
||||
'id': 1,
|
||||
'krb_principal': None,
|
||||
'krb_principals': [],
|
||||
'name': 'kojiadmin',
|
||||
'status': 0,
|
||||
'usertype': 0}
|
||||
self.cursor.fetchone.return_value = None
|
||||
self.context.cnx.cursor.return_value = self.cursor
|
||||
self.exports.getLoggedInUser.return_value = logged_user
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
self.assertEqual('No such user ID: %s' % user_id, str(cm.exception))
|
||||
self.exports.createNotification(
|
||||
self.user_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual('Not logged-in', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
class TestCreateNotificationBlock(unittest.TestCase):
|
||||
def test_createNotification_invalid_user(self):
|
||||
user_id = 2
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = None
|
||||
|
||||
def setUp(self):
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.cursor = mock.MagicMock()
|
||||
|
||||
def test_non_exist_user(self):
|
||||
user_id = 999
|
||||
package_id = 555
|
||||
tag_id = 111
|
||||
logged_user = {'authtype': 2,
|
||||
'id': 1,
|
||||
'krb_principal': None,
|
||||
'krb_principals': [],
|
||||
'name': 'kojiadmin',
|
||||
'status': 0,
|
||||
'usertype': 0}
|
||||
self.cursor.fetchone.return_value = None
|
||||
self.context.cnx.cursor.return_value = self.cursor
|
||||
self.exports.getLoggedInUser.return_value = logged_user
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
self.assertEqual('No such user ID: %s' % user_id, str(cm.exception))
|
||||
self.exports.createNotification(user_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual(f'No such user ID: {user_id}', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotification_no_perm(self):
|
||||
user_id = 2
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'b'}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotification(user_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual('user a cannot create notifications for user b', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotification_invalid_pkg(self):
|
||||
user_id = 2
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotification(user_id, self.package_id, self.tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotification_invalid_tag(self):
|
||||
user_id = 2
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotification(user_id, self.package_id, self.tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotification_exists(self):
|
||||
user_id = 2
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notifications.return_value = [{
|
||||
'package_id': self.package_id,
|
||||
'tag_id': self.tag_id,
|
||||
'success_only': success_only,
|
||||
}]
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotification(user_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual('notification already exists', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
|
|
|||
161
tests/test_hub/test_create_notification_block.py
Normal file
161
tests/test_hub/test_create_notification_block.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestCreateNotificationBlock(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self.get_tag_id = mock.patch('kojihub.get_tag_id').start()
|
||||
self.get_package_id = mock.patch('kojihub.get_package_id').start()
|
||||
self.get_build_notification_blocks = mock.patch(
|
||||
'kojihub.get_build_notification_blocks').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.exports.getUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.cursor = mock.MagicMock()
|
||||
self.user_id = 1
|
||||
self.package_id = 555
|
||||
self.tag_id = 111
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_createNotificationBlock(self):
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'username'}
|
||||
self.exports.hasPerm.return_value = True
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notification_blocks.return_value = []
|
||||
|
||||
r = self.exports.createNotificationBlock(self.user_id, self.package_id, self.tag_id)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.getUser.asssert_called_once_with(self.user_id)
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
self.get_package_id.assert_called_once_with(self.package_id, strict=True)
|
||||
self.get_tag_id.assert_called_once_with(self.tag_id, strict=True)
|
||||
self.get_build_notification_blocks.assert_called_once_with(2)
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
self.assertEqual(insert.table, 'build_notifications_block')
|
||||
self.assertEqual(insert.data, {
|
||||
'package_id': self.package_id,
|
||||
'user_id': 2,
|
||||
'tag_id': self.tag_id,
|
||||
})
|
||||
self.assertEqual(insert.rawdata, {})
|
||||
|
||||
def test_createNotificationBlock_unauthentized(self):
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotificationBlock(self.user_id, self.package_id, self.tag_id)
|
||||
self.assertEqual('Not logged-in', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotificationBlock_invalid_user(self):
|
||||
user_id = 2
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotificationBlock(user_id, self.package_id, self.tag_id)
|
||||
self.assertEqual(f'No such user ID: {user_id}', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotificationBlock_no_perm(self):
|
||||
user_id = 2
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'b'}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotificationBlock(user_id, self.package_id, self.tag_id)
|
||||
self.assertEqual('user a cannot create notification blocks for user b', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotificationBlock_invalid_pkg(self):
|
||||
user_id = 2
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotificationBlock(user_id, self.package_id, self.tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotificationBlock_invalid_tag(self):
|
||||
user_id = 2
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotificationBlock(user_id, self.package_id, self.tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_createNotificationBlock_exists(self):
|
||||
user_id = 2
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notification_blocks.return_value = [{
|
||||
'package_id': self.package_id,
|
||||
'tag_id': self.tag_id,
|
||||
}]
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createNotificationBlock(user_id, self.package_id, self.tag_id)
|
||||
self.assertEqual('notification already exists', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
|
@ -24,8 +24,9 @@ class TestCreateTag(unittest.TestCase):
|
|||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self.get_tag = mock.patch('kojihub.get_tag').start()
|
||||
self.get_tag_id = mock.patch('kojihub.get_tag_id').start()
|
||||
self.get_perm_id = mock.patch('kojihub.get_perm_id').start()
|
||||
self.verify_name_internal = mock.patch('kojihub.verify_name_internal').start()
|
||||
self.writeInheritanceData = mock.patch('kojihub.writeInheritanceData').start()
|
||||
self.writeInheritanceData = mock.patch('kojihub._writeInheritanceData').start()
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
# It seems MagicMock will not automatically handle attributes that
|
||||
# start with "assert"
|
||||
|
|
@ -42,12 +43,13 @@ class TestCreateTag(unittest.TestCase):
|
|||
kojihub.create_tag('duptag')
|
||||
|
||||
def test_simple_create(self):
|
||||
self.get_tag.return_value = None
|
||||
self.get_tag.side_effect = [None, {'id': 1, 'name': 'parent-tag'}]
|
||||
self.get_tag_id.return_value = 99
|
||||
self.verify_name_internal.return_value = None
|
||||
self.context.event_id = 42
|
||||
self.context.session.user_id = 23
|
||||
kojihub.create_tag('newtag')
|
||||
self.writeInheritanceData.return_value = None
|
||||
kojihub.create_tag('newtag', parent='parent-tag')
|
||||
|
||||
# check the insert
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
|
|
@ -97,3 +99,21 @@ class TestCreateTag(unittest.TestCase):
|
|||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.create_tag(tag_name)
|
||||
|
||||
def test_tag_non_exist_parent(self):
|
||||
parent_tag = 'parent-tag'
|
||||
self.verify_name_internal.return_value = None
|
||||
self.get_tag.side_effect = [None, None]
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.create_tag('new-tag', parent=parent_tag)
|
||||
self.assertEqual("Parent tag '%s' could not be found" % parent_tag, str(ex.exception))
|
||||
|
||||
def test_tag_not_maven_support(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.create_tag('new-tag', maven_support=True)
|
||||
self.assertEqual("Maven support not enabled", str(ex.exception))
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.create_tag('new-tag', maven_include_all=True)
|
||||
self.assertEqual("Maven support not enabled", str(ex.exception))
|
||||
|
|
|
|||
|
|
@ -38,19 +38,27 @@ class TestCreateUser(unittest.TestCase):
|
|||
self.exports.createUser(user_name)
|
||||
|
||||
def test_create_user_exists(self):
|
||||
expected = 'user already exists: %s' % self.user_name
|
||||
self.verify_name_user.return_value = None
|
||||
self.get_user.return_value = self.user_info
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createUser(self.user_name)
|
||||
self.assertEqual(expected, str(cm.exception))
|
||||
self.assertEqual(f"user already exists: {self.user_name}", str(cm.exception))
|
||||
|
||||
def test_create_user_exists_krb(self):
|
||||
krb_principal = 'test_user@fedora.org'
|
||||
expected = 'user with this Kerberos principal already exists: %s' % krb_principal
|
||||
expected = f"user with this Kerberos principal already exists: {krb_principal}"
|
||||
self.verify_name_user.return_value = None
|
||||
self.get_user.return_value = None
|
||||
self.get_user_by_krb_principal.return_value = self.user_info_krb
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.createUser(self.user_name, krb_principal=krb_principal)
|
||||
self.assertEqual(expected, str(cm.exception))
|
||||
|
||||
def test_create_user_wrong_type_status(self):
|
||||
status = 'test-status'
|
||||
self.verify_name_user.return_value = None
|
||||
self.get_user.return_value = None
|
||||
self.get_user_by_krb_principal.return_value = self.user_info_krb
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.createUser(self.user_name, status=status)
|
||||
self.assertEqual(f"Invalid type for value '{status}': {type(status)}", str(cm.exception))
|
||||
|
|
|
|||
103
tests/test_hub/test_delete_notification.py
Normal file
103
tests/test_hub/test_delete_notification.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestDeleteNotifications(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.exports.getBuildNotification = mock.MagicMock()
|
||||
self.user_id = 752
|
||||
self.n_id = 543
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_deleteNotification(self):
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
|
||||
self.exports.deleteNotification(self.n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(self.n_id, strict=True)
|
||||
self.exports.getLoggedInUser.assert_called_once_with()
|
||||
self._dml.assert_called_once()
|
||||
|
||||
def test_deleteNotification_missing(self):
|
||||
self.exports.getBuildNotification.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotification(self.n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(self.n_id, strict=True)
|
||||
|
||||
def test_deleteNotification_not_logged(self):
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
# self.set_queries = ([
|
||||
# [{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
# ])
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.deleteNotification(self.n_id)
|
||||
self.assertEqual('Not logged-in', str(cm.exception))
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(self.n_id, strict=True)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
self.assertEqual(len(self.queries), 0)
|
||||
|
||||
def test_deleteNotification_no_perm(self):
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.deleteNotification(self.n_id)
|
||||
self.assertEqual(f'user 1 cannot delete notifications for user {self.user_id}',
|
||||
str(cm.exception))
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(self.n_id, strict=True)
|
||||
self._dml.assert_not_called()
|
||||
104
tests/test_hub/test_delete_notification_block.py
Normal file
104
tests/test_hub/test_delete_notification_block.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestDeleteNotificationsBlocks(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.exports.getBuildNotificationBlock = mock.MagicMock()
|
||||
self.user_id = 752
|
||||
self.n_id = 543
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_deleteNotificationBlock(self):
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': self.user_id}
|
||||
|
||||
self.exports.deleteNotificationBlock(self.n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(self.n_id, strict=True)
|
||||
self.exports.getLoggedInUser.assert_called_once_with()
|
||||
self._dml.assert_called_once()
|
||||
|
||||
def test_deleteNotificationBlock_missing(self):
|
||||
self.exports.getBuildNotificationBlock.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotificationBlock(self.n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(self.n_id, strict=True)
|
||||
|
||||
def test_deleteNotificationBlock_not_logged(self):
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': self.user_id}
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
# self.set_queries = ([
|
||||
# [{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
# ])
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.deleteNotificationBlock(self.n_id)
|
||||
self.assertEqual('Not logged-in', str(cm.exception))
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(self.n_id, strict=True)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
self.assertEqual(len(self.queries), 0)
|
||||
|
||||
def test_deleteNotificationBlock_no_perm2(self):
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': self.user_id}
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.deleteNotificationBlock(self.n_id)
|
||||
self.assertEqual(f'user 1 cannot delete notification blocks for user {self.user_id}',
|
||||
str(cm.exception))
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(self.n_id, strict=True)
|
||||
self._dml.assert_not_called()
|
||||
|
|
@ -28,7 +28,13 @@ class TestDisableChannel(unittest.TestCase):
|
|||
self.get_channel.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.disableChannel(self.channelname)
|
||||
self.assertEqual("No such channel: %s" % self.channelname, str(cm.exception))
|
||||
self.assertEqual(f"No such channel: {self.channelname}", str(cm.exception))
|
||||
|
||||
def test_wrong_type_channel(self):
|
||||
comment = ['test-comment']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.disableChannel(self.channelname, comment=comment)
|
||||
self.assertEqual(f"Invalid type for value '{comment}': {type(comment)}", str(cm.exception))
|
||||
|
||||
def test_valid(self):
|
||||
self.get_channel.return_value = {'comment': None, 'description': None,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class TestDistRepoInit(unittest.TestCase):
|
|||
self.get_event = mock.patch('kojihub.get_event').start()
|
||||
self.nextval = mock.patch('kojihub.nextval').start()
|
||||
self.copyfile = mock.patch('shutil.copyfile').start()
|
||||
self.lookup_name = mock.patch('kojihub.lookup_name').start()
|
||||
|
||||
self.get_tag.return_value = {'id': 42, 'name': 'tag'}
|
||||
self.get_event.return_value = 12345
|
||||
|
|
@ -70,6 +71,34 @@ class TestDistRepoInit(unittest.TestCase):
|
|||
|
||||
self.copyfile.assert_called_once()
|
||||
|
||||
def test_simple_dist_repo_init_wrong_type_keys(self):
|
||||
keys = 'key1 key2'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.dist_repo_init('tag', keys, {'arch': ['x86_64']})
|
||||
self.assertEqual(f"Invalid type for value '{keys}': {type(keys)}", str(cm.exception))
|
||||
self.InsertProcessor.assert_not_called()
|
||||
|
||||
def test_simple_dist_repo_init_wrong_type_task_opts(self):
|
||||
task_opts = 'opts'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.dist_repo_init('tag', ['key'], task_opts)
|
||||
self.assertEqual(f"Invalid type for value '{task_opts}': {type(task_opts)}",
|
||||
str(cm.exception))
|
||||
self.InsertProcessor.assert_not_called()
|
||||
|
||||
def test_simple_dist_repo_init_wrong_type_event(self):
|
||||
event = 'test-event'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.dist_repo_init('tag', ['key'], {'arch': ['x86_64'], 'event': event})
|
||||
self.assertEqual(f"Invalid type for value '{event}': {type(event)}", str(cm.exception))
|
||||
self.InsertProcessor.assert_not_called()
|
||||
|
||||
def test_simple_dist_repo_init_wrong_type_volume(self):
|
||||
self.lookup_name.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.dist_repo_init('tag', ['key'], {'arch': ['x86_64'], 'volume': 'test-volume'})
|
||||
self.InsertProcessor.assert_not_called()
|
||||
|
||||
|
||||
class TestDistRepo(unittest.TestCase):
|
||||
|
||||
|
|
@ -206,7 +235,7 @@ class TestDistRepoMove(unittest.TestCase):
|
|||
path = os.path.join(repodir, relpath)
|
||||
basename = os.path.basename(path)
|
||||
if not os.path.exists(path):
|
||||
raise Exception("Missing file: %s" % path)
|
||||
raise Exception(f"Missing file: {path}")
|
||||
data = open(path, 'rt', encoding='utf-8').read()
|
||||
data.strip()
|
||||
self.assertEqual(data, basename)
|
||||
|
|
|
|||
36
tests/test_hub/test_download_task_output.py
Normal file
36
tests/test_hub/test_download_task_output.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestDownloadTaskOutput(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getVolume = mock.MagicMock()
|
||||
self.task_id = 1
|
||||
self.filename = 'test-file'
|
||||
self.volumename = 'test-volume'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_size_wrong_type(self):
|
||||
size = 'test-size'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
self.exports.downloadTaskOutput(self.task_id, self.filename, size=size)
|
||||
self.assertEqual(f"Invalid type for value '{size}': {type(size)}", str(cm.exception))
|
||||
|
||||
def test_volume_non_exist_wrong_type(self):
|
||||
self.exports.getVolume.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.downloadTaskOutput(self.task_id, self.filename, volume=self.volumename)
|
||||
|
||||
def test_filename_wrong_format(self):
|
||||
filename = '../test-file'
|
||||
volumeinfo = {'id': 1, 'name': self.volumename}
|
||||
self.exports.getVolume.return_value = volumeinfo
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.downloadTaskOutput(self.task_id, filename, volume=self.volumename)
|
||||
self.assertEqual(f"Invalid file name: {filename}", str(cm.exception))
|
||||
|
|
@ -34,32 +34,28 @@ class TestEditChannel(unittest.TestCase):
|
|||
self.exports = kojihub.RootExports()
|
||||
self.channel_name = 'test-channel'
|
||||
self.channel_name_new = 'test-channel-2'
|
||||
self.channel_info = {'id': 123, 'name': self.channel_name, 'description': 'description',
|
||||
'comment': 'comment'}
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.verify_name_internal = mock.patch('kojihub.verify_name_internal').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
def test_edit_channel_missing(self, get_channel, verify_name_internal):
|
||||
def test_edit_channel_missing(self):
|
||||
expected = 'Invalid type for channelInfo: %s' % self.channel_name
|
||||
get_channel.side_effect = koji.GenericError(expected)
|
||||
self.get_channel.side_effect = koji.GenericError(expected)
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
self.exports.editChannel(self.channel_name, name=self.channel_name_new)
|
||||
get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
self.assertEqual(expected, str(ex.exception))
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
def test_edit_channel_already_exists(self, get_channel, verify_name_internal):
|
||||
verify_name_internal.return_value = None
|
||||
get_channel.side_effect = [
|
||||
{
|
||||
'id': 123,
|
||||
'name': self.channel_name,
|
||||
'description': 'description',
|
||||
},
|
||||
def test_edit_channel_already_exists(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
self.get_channel.side_effect = [
|
||||
self.channel_info,
|
||||
{
|
||||
'id': 124,
|
||||
'name': self.channel_name_new,
|
||||
|
|
@ -70,29 +66,22 @@ class TestEditChannel(unittest.TestCase):
|
|||
self.exports.editChannel(self.channel_name, name=self.channel_name_new)
|
||||
expected_calls = [mock.call(self.channel_name, strict=True),
|
||||
mock.call(self.channel_name_new, strict=False)]
|
||||
get_channel.assert_has_calls(expected_calls)
|
||||
self.get_channel.assert_has_calls(expected_calls)
|
||||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
self.assertEqual('channel %s already exists (id=124)' % self.channel_name_new,
|
||||
self.assertEqual(f'channel {self.channel_name_new} already exists (id=124)',
|
||||
str(ex.exception))
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
def test_edit_channel_valid(self, get_channel, verify_name_internal):
|
||||
verify_name_internal.return_value = None
|
||||
kojihub.get_channel.side_effect = [{
|
||||
'id': 123,
|
||||
'name': self.channel_name,
|
||||
'description': 'description',
|
||||
},
|
||||
{}]
|
||||
def test_edit_channel_valid(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
kojihub.get_channel.side_effect = [self.channel_info, {}]
|
||||
|
||||
r = self.exports.editChannel(self.channel_name, name=self.channel_name_new,
|
||||
description='description_new')
|
||||
self.assertTrue(r)
|
||||
expected_calls = [mock.call(self.channel_name, strict=True),
|
||||
mock.call(self.channel_name_new, strict=False)]
|
||||
get_channel.assert_has_calls(expected_calls)
|
||||
self.get_channel.assert_has_calls(expected_calls)
|
||||
|
||||
self.assertEqual(len(self.updates), 1)
|
||||
values = {'channelID': 123}
|
||||
|
|
@ -103,21 +92,56 @@ class TestEditChannel(unittest.TestCase):
|
|||
self.assertEqual(update.values, values)
|
||||
self.assertEqual(update.clauses, clauses)
|
||||
|
||||
@mock.patch('kojihub.verify_name_internal')
|
||||
@mock.patch('kojihub.get_channel')
|
||||
def test_edit_channel_wrong_format(self, get_channel, verify_name_internal):
|
||||
def test_edit_channel_wrong_name(self):
|
||||
channel_name_new = 'test-channel+'
|
||||
get_channel.return_value = {'id': 123,
|
||||
'name': self.channel_name,
|
||||
'description': 'description',
|
||||
}
|
||||
self.get_channel.return_value = self.channel_info
|
||||
|
||||
# name is longer as expected
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.editChannel(self.channel_name, name=channel_name_new)
|
||||
|
||||
# not except regex rules
|
||||
verify_name_internal.side_effect = koji.GenericError
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.editChannel(self.channel_name, name=channel_name_new)
|
||||
|
||||
def test_edit_channel_no_change(self):
|
||||
self.verify_name_internal.return_value = None
|
||||
kojihub.get_channel.return_value = self.channel_info
|
||||
|
||||
r = self.exports.editChannel(self.channel_name, description='description')
|
||||
self.assertFalse(r)
|
||||
self.assertEqual(self.updates, [])
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.verify_name_internal.assert_not_called()
|
||||
|
||||
def test_edit_channel_wrong_format_new_name(self):
|
||||
channel_name_new = 13568
|
||||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.editChannel(self.channel_name, name=channel_name_new)
|
||||
self.assertEqual(self.updates, [])
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.verify_name_internal.assert_called_once_with(channel_name_new)
|
||||
|
||||
def test_edit_channel_wrong_format_description(self):
|
||||
description = ['description']
|
||||
self.get_channel.return_value = self.channel_info
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.editChannel(self.channel_name, description=description)
|
||||
self.assertEqual(self.updates, [])
|
||||
self.assertEqual(f"Invalid type for value '{description}': {type(description)}",
|
||||
str(ex.exception))
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.verify_name_internal.assert_not_called()
|
||||
|
||||
def test_edit_channel_wrong_format_comment(self):
|
||||
comment = ['comment']
|
||||
self.get_channel.return_value = self.channel_info
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.editChannel(self.channel_name, comment=comment)
|
||||
self.assertEqual(self.updates, [])
|
||||
self.assertEqual(f"Invalid type for value '{comment}': {type(comment)}", str(ex.exception))
|
||||
self.get_channel.assert_called_once_with(self.channel_name, strict=True)
|
||||
self.verify_name_internal.assert_not_called()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ UP = kojihub.UpdateProcessor
|
|||
IP = kojihub.InsertProcessor
|
||||
|
||||
|
||||
class TestSetHostEnabled(unittest.TestCase):
|
||||
class TestEditHost(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
|
|
@ -22,6 +22,7 @@ class TestSetHostEnabled(unittest.TestCase):
|
|||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.diff = None
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
|
|
@ -34,12 +35,22 @@ class TestSetHostEnabled(unittest.TestCase):
|
|||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.get_host = mock.patch('kojihub.get_host').start()
|
||||
self.hostinfo = {
|
||||
'id': 123,
|
||||
'user_id': 234,
|
||||
'name': 'hostname',
|
||||
'arches': 'x86_64',
|
||||
'capacity': 100.0,
|
||||
'description': 'description',
|
||||
'comment': 'comment',
|
||||
'enabled': False,
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_edit_host_missing(self):
|
||||
kojihub.get_host = mock.MagicMock()
|
||||
kojihub.get_host.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.editHost('hostname')
|
||||
|
|
@ -47,23 +58,47 @@ class TestSetHostEnabled(unittest.TestCase):
|
|||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
|
||||
def test_edit_host_invalid_description(self):
|
||||
description = ['description']
|
||||
kojihub.get_host.return_value = self.hostinfo
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.editHost('hostname', description=description)
|
||||
self.assertEqual('Invalid type for description parameter: %s' % type(description),
|
||||
str(ex.exception))
|
||||
kojihub.get_host.assert_called_once_with('hostname', strict=True)
|
||||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
|
||||
def test_edit_host_invalid_comment_parameter(self):
|
||||
comment = ['comment']
|
||||
kojihub.get_host.return_value = self.hostinfo
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.editHost('hostname', comment=comment)
|
||||
self.assertEqual('Invalid type for comment parameter: %s' % type(comment),
|
||||
str(ex.exception))
|
||||
kojihub.get_host.assert_called_once_with('hostname', strict=True)
|
||||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
|
||||
def test_edit_host_invalid_arches_parameter(self):
|
||||
arches = ['arches arches']
|
||||
kojihub.get_host.return_value = self.hostinfo
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.editHost('hostname', arches=arches)
|
||||
self.assertEqual('Invalid type for arches parameter: %s' % type(arches),
|
||||
str(ex.exception))
|
||||
kojihub.get_host.assert_called_once_with('hostname', strict=True)
|
||||
self.assertEqual(self.inserts, [])
|
||||
self.assertEqual(self.updates, [])
|
||||
|
||||
def test_edit_host_valid(self):
|
||||
kojihub.get_host = mock.MagicMock()
|
||||
kojihub.get_host.return_value = {
|
||||
'id': 123,
|
||||
'user_id': 234,
|
||||
'name': 'hostname',
|
||||
'arches': ['x86_64'],
|
||||
'capacity': 100.0,
|
||||
'description': 'description',
|
||||
'comment': 'comment',
|
||||
'enabled': False,
|
||||
}
|
||||
kojihub.get_host.return_value = self.hostinfo
|
||||
self.context.event_id = 42
|
||||
self.context.session.user_id = 23
|
||||
|
||||
r = self.exports.editHost('hostname', arches=['x86_64', 'i386'],
|
||||
capacity=12.0, comment='comment_new', non_existing_kw='bogus')
|
||||
r = self.exports.editHost('hostname', arches='x86_64 i386', capacity=12.0,
|
||||
comment='comment_new', non_existing_kw='bogus')
|
||||
|
||||
self.assertTrue(r)
|
||||
kojihub.get_host.assert_called_once_with('hostname', strict=True)
|
||||
|
|
@ -87,12 +122,11 @@ class TestSetHostEnabled(unittest.TestCase):
|
|||
# insert
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
#data = kojihub.get_host.return_value
|
||||
data = {
|
||||
'create_event': 42,
|
||||
'creator_id': 23,
|
||||
'host_id': 123,
|
||||
'arches': ['x86_64', 'i386'],
|
||||
'arches': 'x86_64 i386',
|
||||
'capacity': 12.0,
|
||||
'comment': 'comment_new',
|
||||
'description': 'description',
|
||||
|
|
@ -105,16 +139,7 @@ class TestSetHostEnabled(unittest.TestCase):
|
|||
|
||||
def test_edit_host_no_change(self):
|
||||
kojihub.get_host = mock.MagicMock()
|
||||
kojihub.get_host.return_value = {
|
||||
'id': 123,
|
||||
'user_id': 234,
|
||||
'name': 'hostname',
|
||||
'arches': ['x86_64'],
|
||||
'capacity': 100.0,
|
||||
'description': 'description',
|
||||
'comment': 'comment',
|
||||
'enabled': False,
|
||||
}
|
||||
kojihub.get_host.return_value = self.hostinfo
|
||||
self.context.event_id = 42
|
||||
self.context.session.user_id = 23
|
||||
|
||||
|
|
|
|||
|
|
@ -42,3 +42,12 @@ class TestEditPermission(unittest.TestCase):
|
|||
self.assertEqual(up.table, 'permissions')
|
||||
self.assertEqual(up.rawdata, {})
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
||||
def test_edit_permission_wrong_type_permission(self):
|
||||
description = ['test-description']
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
self.exports.editPermission(self.perm_name, description=description)
|
||||
self.assertEqual(f"Invalid type for value '{description}': {type(description)}",
|
||||
str(ex.exception))
|
||||
self.update_processor.assert_not_called()
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ WHERE id = %(tagID)i""", {'name': 'newtag', 'tagID': 333})
|
|||
with self.assertRaises(koji.GenericError):
|
||||
kojihub._edit_tag('tag', **kwargs)
|
||||
|
||||
def test_edit_wrong_format_tag(self):
|
||||
def test_edit_wrong_tag(self):
|
||||
tag_name_new = 'new-test-tag+'
|
||||
tag_name = 'tag'
|
||||
self.get_tag.return_value = {'id': 333,
|
||||
|
|
@ -268,3 +268,36 @@ WHERE id = %(tagID)i""", {'name': 'newtag', 'tagID': 333})
|
|||
self.verify_name_internal.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub._edit_tag('tag', **kwargs)
|
||||
|
||||
def test_edit_tag_remove_extra_wrong_format(self):
|
||||
kwargs = {
|
||||
'perm': None,
|
||||
'name': 'tag_name_new',
|
||||
'arches': 'arch1 arch2',
|
||||
'locked': True,
|
||||
'maven_support': False,
|
||||
'maven_include_all': False,
|
||||
'extra': {},
|
||||
'remove_extra': 'remove-extra'
|
||||
}
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
kojihub._edit_tag('tag', **kwargs)
|
||||
self.assertEqual(f"Invalid type for value '{kwargs['remove_extra']}': "
|
||||
f"{type(kwargs['remove_extra'])}", str(ex.exception))
|
||||
|
||||
def test_edit_tag_block_extra_wrong_format(self):
|
||||
kwargs = {
|
||||
'perm': None,
|
||||
'name': 'tag_name_new',
|
||||
'arches': 'arch1 arch2',
|
||||
'locked': True,
|
||||
'maven_support': False,
|
||||
'maven_include_all': False,
|
||||
'extra': {},
|
||||
'remove_extra': [],
|
||||
'block_extra': 'block-extra'
|
||||
}
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
kojihub._edit_tag('tag', **kwargs)
|
||||
self.assertEqual(f"Invalid type for value '{kwargs['block_extra']}': "
|
||||
f"{type(kwargs['block_extra'])}", str(ex.exception))
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ class TestEditTagExternalRepo(unittest.TestCase):
|
|||
self.get_tag_external_repos.return_value = []
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.edit_tag_external_repo('tag', 'ext_repo', priority=6, merge_mode='bare')
|
||||
self.assertEqual(cm.exception.args[0],
|
||||
'external repo ext_repo not associated with tag tag')
|
||||
self.assertEqual('external repo ext_repo not associated with tag tag', str(cm.exception))
|
||||
self.get_tag.assert_called_once_with('tag', strict=True)
|
||||
self.get_external_repo.assert_called_once_with('ext_repo', strict=True)
|
||||
self.get_tag_external_repos.assert_called_once_with(tag_info=1, repo_info=11)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class TestEnableChannel(unittest.TestCase):
|
|||
self.get_channel.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.enableChannel(self.channelname)
|
||||
self.assertEqual("No such channel: %s" % self.channelname, str(cm.exception))
|
||||
self.assertEqual(f"No such channel: {self.channelname}", str(cm.exception))
|
||||
|
||||
def test_valid(self):
|
||||
self.get_channel.return_value = {'comment': None, 'description': None,
|
||||
|
|
@ -42,3 +42,9 @@ class TestEnableChannel(unittest.TestCase):
|
|||
self.assertEqual(update.values, {'comment': None, 'description': None, 'enabled': False,
|
||||
'id': 1, 'name': 'test-channel'})
|
||||
self.assertEqual(update.clauses, ['id = %(id)i'])
|
||||
|
||||
def test_wrong_type_channel(self):
|
||||
comment = ['test-comment']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.enableChannel(self.channelname, comment=comment)
|
||||
self.assertEqual(f"Invalid type for value '{comment}': {type(comment)}", str(cm.exception))
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class TestGetRPM(unittest.TestCase):
|
|||
rpminfo = ['test-user']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.get_rpm(rpminfo)
|
||||
self.assertEqual("Invalid type for rpminfo: %s" % type(rpminfo), str(cm.exception))
|
||||
self.assertEqual(f"Invalid type for rpminfo: {type(rpminfo)}", str(cm.exception))
|
||||
|
||||
|
||||
class TestGetRPMHeaders(unittest.TestCase):
|
||||
|
|
@ -41,7 +41,7 @@ class TestGetRPMHeaders(unittest.TestCase):
|
|||
filepath = '../test/path'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getRPMHeaders(taskID=99, filepath=filepath)
|
||||
self.assertEqual("Invalid filepath: %s" % filepath, str(cm.exception))
|
||||
self.assertEqual(f"Invalid filepath: {filepath}", str(cm.exception))
|
||||
self.get_rpm.assert_not_called()
|
||||
self.get_build.assert_not_called()
|
||||
self.get_header_fields.assert_not_called()
|
||||
|
|
|
|||
28
tests/test_hub/test_get_archive.py
Normal file
28
tests/test_hub/test_get_archive.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestGetArchive(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.list_archives = mock.patch('kojihub.list_archives').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_get_archive_non_exist_archive_with_strict(self):
|
||||
archive_id = 1
|
||||
self.list_archives.return_value = []
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.get_archive(archive_id, strict=True)
|
||||
self.assertEqual(f"No such archive: {archive_id}", str(cm.exception))
|
||||
|
||||
def test_get_archive_non_exist_archive_without_strict(self):
|
||||
archive_id = 1
|
||||
self.list_archives.return_value = []
|
||||
rv = kojihub.get_archive(archive_id)
|
||||
self.assertEqual(rv, None)
|
||||
20
tests/test_hub/test_get_archive_type.py
Normal file
20
tests/test_hub/test_get_archive_type.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestGetArchiveType(unittest.TestCase):
|
||||
|
||||
def test_get_archive_wrong_type_filename(self):
|
||||
filename = ['test-filename']
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.get_archive_type(filename=filename)
|
||||
self.assertEqual(f"Invalid type for value '{filename}': {type(filename)}",
|
||||
str(cm.exception))
|
||||
|
||||
def test_get_archive_without_opt(self):
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.get_archive_type()
|
||||
self.assertEqual("one of filename, type_name, or type_id must be specified",
|
||||
str(cm.exception))
|
||||
22
tests/test_hub/test_get_build_notification.py
Normal file
22
tests/test_hub/test_get_build_notification.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestGetBuildNotification(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor').start()
|
||||
self.query = self.QueryProcessor.return_value
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_empty_result_with_strict(self):
|
||||
notif_id = 1
|
||||
self.query.executeOne.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getBuildNotification(notif_id, strict=True)
|
||||
self.assertEqual(f"No notification with ID {notif_id} found", str(cm.exception))
|
||||
22
tests/test_hub/test_get_build_notification_block.py
Normal file
22
tests/test_hub/test_get_build_notification_block.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestGetBuildNotificationBlock(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor').start()
|
||||
self.query = self.QueryProcessor.return_value
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_empty_result_with_strict(self):
|
||||
notif_id = 1
|
||||
self.query.executeOne.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getBuildNotificationBlock(notif_id, strict=True)
|
||||
self.assertEqual(f"No notification block with ID {notif_id} found", str(cm.exception))
|
||||
29
tests/test_hub/test_get_build_notification_blocks.py
Normal file
29
tests/test_hub/test_get_build_notification_blocks.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestGetBuildNotificationBlocks(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.exports = kojihub.RootExports()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self.get_build_notification_blocks = mock.patch(
|
||||
'kojihub.get_build_notification_blocks').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_loggedin_user(self):
|
||||
self.get_user.return_value = {'id': 1}
|
||||
self.exports.getBuildNotificationBlocks(None)
|
||||
self.get_user.assert_called_once_with(None, strict=True)
|
||||
self.get_build_notification_blocks.assert_called_once_with(1)
|
||||
|
||||
def test_user_not_found(self):
|
||||
self.get_user.side_effect = koji.GenericError('error msg')
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getBuildNotificationBlocks(1)
|
||||
self.get_user.assert_called_once_with(1, strict=True)
|
||||
self.get_build_notification_blocks.assert_not_called()
|
||||
self.assertEqual(cm.exception.args[0], 'error msg')
|
||||
|
|
@ -5,18 +5,21 @@ import kojihub
|
|||
|
||||
|
||||
class TestGetBuildNotifications(unittest.TestCase):
|
||||
@mock.patch('kojihub.get_user', return_value={'id': 1})
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
def test_loggedin_user(self, get_build_notifications, get_user):
|
||||
kojihub.RootExports().getBuildNotifications(None)
|
||||
get_user.assert_called_once_with(None, strict=True)
|
||||
get_build_notifications.assert_called_once_with(1)
|
||||
def setUp(self):
|
||||
self.exports = kojihub.RootExports()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self.get_build_notifications = mock.patch('kojihub.get_build_notifications').start()
|
||||
|
||||
@mock.patch('kojihub.get_user', side_effect=koji.GenericError('error msg'))
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
def test_user_not_found(self, get_build_notifications, get_user):
|
||||
def test_loggedin_user(self):
|
||||
self.get_user.return_value = {'id': 1}
|
||||
kojihub.RootExports().getBuildNotifications(None)
|
||||
self.get_user.assert_called_once_with(None, strict=True)
|
||||
self.get_build_notifications.assert_called_once_with(1)
|
||||
|
||||
def test_user_not_found(self):
|
||||
self.get_user.side_effect = koji.GenericError('error msg')
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.RootExports().getBuildNotifications(1)
|
||||
get_user.assert_called_once_with(1, strict=True)
|
||||
get_build_notifications.assert_not_called()
|
||||
self.get_user.assert_called_once_with(1, strict=True)
|
||||
self.get_build_notifications.assert_not_called()
|
||||
self.assertEqual(cm.exception.args[0], 'error msg')
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ class TestGetChangelogEntries(unittest.TestCase):
|
|||
self.get_build.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getChangelogEntries(buildID=build_id, strict=True)
|
||||
self.assertEqual("No such build: %s" % build_id, str(cm.exception))
|
||||
self.assertEqual(f"No such build: {build_id}", str(cm.exception))
|
||||
|
||||
def test_taskid_invalid_path(self):
|
||||
filepath = '../test/path'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getChangelogEntries(taskID=99, filepath=filepath)
|
||||
self.assertEqual("Invalid filepath: %s" % filepath, str(cm.exception))
|
||||
self.assertEqual(f"Invalid filepath: {filepath}", str(cm.exception))
|
||||
|
||||
def test_taskid_without_filepath(self):
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
|
|
@ -43,7 +43,7 @@ class TestGetChangelogEntries(unittest.TestCase):
|
|||
self.os_path_exists.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getChangelogEntries(taskID=99, before=before, filepath=filepath)
|
||||
self.assertEqual("Invalid type for before: %s" % type(before), str(cm.exception))
|
||||
self.assertEqual(f"Invalid type for before: {type(before)}", str(cm.exception))
|
||||
|
||||
def test_after_invalid_type(self):
|
||||
after = {'after': '1133456'}
|
||||
|
|
@ -51,7 +51,7 @@ class TestGetChangelogEntries(unittest.TestCase):
|
|||
self.os_path_exists.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getChangelogEntries(taskID=99, after=after, filepath=filepath)
|
||||
self.assertEqual("Invalid type for after: %s" % type(after), str(cm.exception))
|
||||
self.assertEqual(f"Invalid type for after: {type(after)}", str(cm.exception))
|
||||
|
||||
def test_srpm_path_not_exist(self):
|
||||
filepath = 'test/path'
|
||||
|
|
@ -62,4 +62,4 @@ class TestGetChangelogEntries(unittest.TestCase):
|
|||
self.os_path_exists.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getChangelogEntries(taskID=task_id, filepath=filepath, strict=True)
|
||||
self.assertEqual("SRPM %s doesn't exist" % srpm_path, str(cm.exception))
|
||||
self.assertEqual(f"SRPM {srpm_path} doesn't exist", str(cm.exception))
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class TestGetExternalRepo(unittest.TestCase):
|
|||
self.get_external_repos.return_value = []
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.getExternalRepo(repo, strict=True)
|
||||
self.assertEqual("No such repo: %s" % repo, str(cm.exception))
|
||||
self.assertEqual(f"No such repo: {repo}", str(cm.exception))
|
||||
|
||||
def test_non_exist_repo_without_strict(self):
|
||||
repo = 'test-repo'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import koji
|
||||
import kojihub
|
||||
from .utils import DBQueryTestCase
|
||||
|
||||
|
|
@ -97,9 +96,3 @@ class TestGetExternalRepos(DBQueryTestCase):
|
|||
self.assertEqual(rv, [{'id': 1,
|
||||
'name': 'ext_repo_1',
|
||||
'url': 'http://example.com/repo/'}])
|
||||
|
||||
def test_get_external_repos_wrong_type(self):
|
||||
info = {'info_key': 'info_value'}
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.get_external_repos(info=info)
|
||||
self.assertEqual("Invalid name or id value: %s" % info, str(cm.exception))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ import kojihub
|
|||
class TestGetNextRelease(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor').start()
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self.query = self.QueryProcessor.return_value
|
||||
self.binfo = {'name': 'name', 'version': 'version'}
|
||||
|
|
@ -25,7 +27,7 @@ class TestGetNextRelease(unittest.TestCase):
|
|||
for n in [1, 2, 3, 5, 8, 13, 21, 34, 55]:
|
||||
self.query.executeOne.return_value = {'release': str(n)}
|
||||
result = kojihub.get_next_release(self.binfo)
|
||||
self.assertEqual(result, str(n+1))
|
||||
self.assertEqual(result, str(n + 1))
|
||||
|
||||
def test_get_next_release_complex(self):
|
||||
data = [
|
||||
|
|
@ -59,10 +61,10 @@ class TestGetNextRelease(unittest.TestCase):
|
|||
# bad_incr_value
|
||||
"foo",
|
||||
None,
|
||||
1.1,
|
||||
{1:1},
|
||||
{1: 1},
|
||||
[1],
|
||||
]
|
||||
for val in data:
|
||||
with self.assertRaises(koji.ParameterError):
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
kojihub.get_next_release(self.binfo, incr=val)
|
||||
self.assertEqual('incr parameter must be an integer', str(ex.exception))
|
||||
|
|
|
|||
258
tests/test_hub/test_get_notification_recipients.py
Normal file
258
tests/test_hub/test_get_notification_recipients.py
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestGetNotificationRecipients(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self.readPackageList = mock.patch('kojihub.readPackageList').start()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_get_notification_recipients_watchers(self):
|
||||
# without build / tag_id
|
||||
build = None
|
||||
tag_id = None
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, [])
|
||||
|
||||
# only query to watchers
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s'])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
'''
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, ['user_id IN %(user_ids)s'])
|
||||
self.assertEqual(q.joins, [])
|
||||
self.assertEqual(q.values['user_ids'], None)
|
||||
'''
|
||||
self.readPackageList.assert_not_called()
|
||||
|
||||
def test_get_notification_recipients_build_without_tag(self):
|
||||
### with build without tag
|
||||
tag_id = None
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
self.queries = []
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
||||
# there should be only query to watchers
|
||||
self.assertEqual(len(self.queries), 2)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s'])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['package_id'], build['package_id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'tag_id IS NULL',
|
||||
'user_id IN %(user_ids)s',
|
||||
])
|
||||
self.assertEqual(q.joins, None)
|
||||
self.assertEqual(q.values['user_ids'], [5])
|
||||
|
||||
self.readPackageList.assert_not_called()
|
||||
|
||||
def test_get_notification_recipients_tag_without_build(self):
|
||||
### with tag without build makes no sense
|
||||
build = None
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.queries = []
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(self.queries, [])
|
||||
self.readPackageList.assert_not_called()
|
||||
|
||||
def set_queries(self, return_values):
|
||||
self.query_returns = return_values
|
||||
self.query_returns.reverse()
|
||||
|
||||
def getQuery(*args, **kwargs):
|
||||
q = QP(*args, **kwargs)
|
||||
q.execute = mock.MagicMock()
|
||||
q.execute.return_value = self.query_returns.pop()
|
||||
self.queries.append(q)
|
||||
return q
|
||||
self.QueryProcessor.side_effect = getQuery
|
||||
|
||||
def test_get_notification_recipients_tag_with_build(self):
|
||||
### with tag and build
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.readPackageList.return_value = {12345: {'blocked': False, 'owner_id': 'owner_id'}}
|
||||
self.get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(sorted(emails),
|
||||
['owner_name@test.domain.com', 'pkg_owner_name@test.domain.com'])
|
||||
|
||||
# there should be only query to watchers
|
||||
self.assertEqual(len(self.queries), 2)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id = %(tag_id)i OR tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s',
|
||||
])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['package_id'], build['package_id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'tag_id = %(tag_id)i OR tag_id IS NULL',
|
||||
'user_id IN %(user_ids)s',
|
||||
])
|
||||
self.assertEqual(q.joins, None)
|
||||
self.assertEqual(sorted(q.values['user_ids']), [5, 342])
|
||||
self.readPackageList.assert_called_once_with(
|
||||
pkgID=build['package_id'], tagID=tag_id, inherit=True)
|
||||
self.get_user.asssert_called_once_with(342, strict=True)
|
||||
|
||||
def test_get_notification_recipients_blocked_pkg_owner(self):
|
||||
# blocked package owner
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['BLOCKED'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
||||
def test_get_notification_recipients_optout(self):
|
||||
# blocked package owner
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[{'user_id': 5}]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, [])
|
||||
|
||||
def test_get_notification_recipients_machine(self):
|
||||
# package owner is machine
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['HOST']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
|
@ -122,3 +122,13 @@ class TestGrantPermission(unittest.TestCase):
|
|||
self.assertEqual(ip.table, 'user_perms')
|
||||
self.assertEqual(ip.rawdata, {})
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
||||
def test_grant_permission_description_wrong_type(self):
|
||||
description = ['test-description']
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.grantPermission(self.user_name, self.perms_name,
|
||||
description=description, create=True)
|
||||
self.assertEqual(f"Invalid type for value '{description}': {type(description)}",
|
||||
str(ex.exception))
|
||||
self.insert_processor.assert_not_called()
|
||||
self.context.session.assertPerm.assert_called_with('admin')
|
||||
|
|
|
|||
40
tests/test_hub/test_import_archive.py
Normal file
40
tests/test_hub/test_import_archive.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestImportArchive(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.filepath = 'path/to/file'
|
||||
self.buildinfo = 'build-1-1.4'
|
||||
self.type_archive = 'maven'
|
||||
self.typeinfo = {'group_id': 1, 'artifact_id': 2, 'version': 1}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_maven_not_enabled(self):
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.importArchive(self.filepath, self.buildinfo, self.type_archive,
|
||||
self.typeinfo)
|
||||
self.assertEqual("Maven support not enabled", str(cm.exception))
|
||||
|
||||
def test_win_not_enabled(self):
|
||||
type_archive = 'win'
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.importArchive(self.filepath, self.buildinfo, type_archive, self.typeinfo)
|
||||
self.assertEqual("Windows support not enabled", str(cm.exception))
|
||||
|
||||
def test_unsupported_type(self):
|
||||
type_archive = 'test-type'
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.importArchive(self.filepath, self.buildinfo, type_archive, self.typeinfo)
|
||||
self.assertEqual(f"unsupported archive type: {type_archive}", str(cm.exception))
|
||||
23
tests/test_hub/test_import_archive_internal.py
Normal file
23
tests/test_hub/test_import_archive_internal.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestImportArchiveInternal(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.os_path_exists = mock.patch('os.path.exists').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_import_archive_internal_non_exist_filepath(self):
|
||||
self.os_path_exists.return_value = False
|
||||
filepath = 'test/file/path/to/archive'
|
||||
buildinfo = {'id': 1, 'name': 'test-build'}
|
||||
type_archive = 'maven'
|
||||
typeInfo = {'group_id': 1, 'artifact_id': 2, 'version': 3}
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_archive_internal(filepath, buildinfo, type_archive, typeInfo)
|
||||
self.assertEqual(f"No such file: {filepath}", str(cm.exception))
|
||||
|
|
@ -1,203 +1,13 @@
|
|||
import copy
|
||||
import mock
|
||||
import unittest
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestImportRPM(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
self.filename = self.tempdir + "/name-version-release.arch.rpm"
|
||||
# Touch a file
|
||||
with open(self.filename, 'w'):
|
||||
pass
|
||||
self.src_filename = self.tempdir + "/name-version-release.src.rpm"
|
||||
# Touch a file
|
||||
with open(self.src_filename, 'w'):
|
||||
pass
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.cursor = mock.MagicMock()
|
||||
|
||||
self.rpm_header_retval = {
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
'sourcepackage': 2,
|
||||
1000: 'name',
|
||||
1001: 'version',
|
||||
1002: 'release',
|
||||
1003: 'epoch',
|
||||
1006: 'buildtime',
|
||||
1022: 'arch',
|
||||
1044: 'name-version-release.arch',
|
||||
1106: 'sourcepackage',
|
||||
261: 'payload hash',
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
|
||||
def test_nonexistant_rpm(self):
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.import_rpm("this does not exist")
|
||||
|
||||
@mock.patch('kojihub.get_build')
|
||||
@mock.patch('koji.get_rpm_header')
|
||||
def test_import_rpm_failed_build(self, get_rpm_header, get_build):
|
||||
get_rpm_header.return_value = self.rpm_header_retval
|
||||
get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['FAILED'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
}
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.import_rpm(self.filename)
|
||||
|
||||
@mock.patch('kojihub.new_typed_build')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
@mock.patch('kojihub.get_build')
|
||||
@mock.patch('koji.get_rpm_header')
|
||||
def test_import_rpm_completed_build(self, get_rpm_header, get_build,
|
||||
_singleValue, _dml,
|
||||
new_typed_build):
|
||||
get_rpm_header.return_value = self.rpm_header_retval
|
||||
get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['COMPLETE'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
'id': 12345,
|
||||
}
|
||||
_singleValue.return_value = 9876
|
||||
kojihub.import_rpm(self.filename)
|
||||
fields = [
|
||||
'arch',
|
||||
'build_id',
|
||||
'buildroot_id',
|
||||
'buildtime',
|
||||
'epoch',
|
||||
'external_repo_id',
|
||||
'id',
|
||||
'name',
|
||||
'payloadhash',
|
||||
'release',
|
||||
'size',
|
||||
'version',
|
||||
]
|
||||
statement = 'INSERT INTO rpminfo (%s) VALUES (%s)' % (
|
||||
", ".join(fields),
|
||||
", ".join(['%%(%s)s' % field for field in fields])
|
||||
)
|
||||
values = {
|
||||
'build_id': 12345,
|
||||
'name': 'name',
|
||||
'arch': 'arch',
|
||||
'buildtime': 'buildtime',
|
||||
'payloadhash': '7061796c6f61642068617368',
|
||||
'epoch': 'epoch',
|
||||
'version': 'version',
|
||||
'buildroot_id': None,
|
||||
'release': 'release',
|
||||
'external_repo_id': 0,
|
||||
'id': 9876,
|
||||
'size': 0,
|
||||
}
|
||||
_dml.assert_called_once_with(statement, values)
|
||||
|
||||
@mock.patch('kojihub.new_typed_build')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
@mock.patch('kojihub.get_build')
|
||||
@mock.patch('koji.get_rpm_header')
|
||||
def test_import_rpm_completed_source_build(self, get_rpm_header, get_build,
|
||||
_singleValue, _dml,
|
||||
new_typed_build):
|
||||
retval = copy.copy(self.rpm_header_retval)
|
||||
retval.update({
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
1044: 'name-version-release.src',
|
||||
1022: 'src',
|
||||
1106: 1,
|
||||
})
|
||||
get_rpm_header.return_value = retval
|
||||
get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['COMPLETE'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
'id': 12345,
|
||||
}
|
||||
_singleValue.return_value = 9876
|
||||
kojihub.import_rpm(self.src_filename)
|
||||
fields = [
|
||||
'arch',
|
||||
'build_id',
|
||||
'buildroot_id',
|
||||
'buildtime',
|
||||
'epoch',
|
||||
'external_repo_id',
|
||||
'id',
|
||||
'name',
|
||||
'payloadhash',
|
||||
'release',
|
||||
'size',
|
||||
'version',
|
||||
]
|
||||
statement = 'INSERT INTO rpminfo (%s) VALUES (%s)' % (
|
||||
", ".join(fields),
|
||||
", ".join(['%%(%s)s' % field for field in fields])
|
||||
)
|
||||
values = {
|
||||
'build_id': 12345,
|
||||
'name': 'name',
|
||||
'arch': 'src',
|
||||
'buildtime': 'buildtime',
|
||||
'payloadhash': '7061796c6f61642068617368',
|
||||
'epoch': 'epoch',
|
||||
'version': 'version',
|
||||
'buildroot_id': None,
|
||||
'release': 'release',
|
||||
'external_repo_id': 0,
|
||||
'id': 9876,
|
||||
'size': 0,
|
||||
}
|
||||
_dml.assert_called_once_with(statement, values)
|
||||
|
||||
@mock.patch('os.path.exists')
|
||||
def test_non_exist_file(self, os_path_exist):
|
||||
exports = kojihub.RootExports()
|
||||
basename = 'rpm-1-34'
|
||||
uploadpath = koji.pathinfo.work()
|
||||
filepath = '%s/%s/%s' % (uploadpath, self.filename, basename)
|
||||
os_path_exist.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
exports.importRPM(self.filename, basename)
|
||||
self.assertEqual("No such file: %s" % filepath, str(cm.exception))
|
||||
|
||||
@mock.patch('koji.get_rpm_header')
|
||||
@mock.patch('os.path.exists')
|
||||
@mock.patch('os.path.basename')
|
||||
def test_non_exist_file(self, os_path_basename, os_path_exist, get_rpm_header):
|
||||
self.cursor.fetchone.return_value = None
|
||||
self.context.cnx.cursor.return_value = self.cursor
|
||||
retval = copy.copy(self.rpm_header_retval)
|
||||
retval.update({
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
'sourcepackage': 2
|
||||
})
|
||||
get_rpm_header.return_value = retval
|
||||
os_path_exist.return_value = True
|
||||
os_path_basename.return_value = 'name-version-release.arch.rpm'
|
||||
kojihub.get_build.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_rpm(self.src_filename)
|
||||
self.assertEqual("No such build", str(cm.exception))
|
||||
|
||||
|
||||
class TestImportBuild(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
|
|
@ -210,6 +20,22 @@ class TestImportBuild(unittest.TestCase):
|
|||
with open(self.src_filename, 'w'):
|
||||
pass
|
||||
|
||||
self.check_volume_policy = mock.patch('kojihub.check_volume_policy').start()
|
||||
self.new_typed_build = mock.patch('kojihub.new_typed_build').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self._singleValue = mock.patch('kojihub._singleValue').start()
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
self.add_rpm_sig = mock.patch('kojihub.add_rpm_sig').start()
|
||||
self.rip_rpm_sighdr = mock.patch('koji.rip_rpm_sighdr').start()
|
||||
self.import_rpm_file = mock.patch('kojihub.import_rpm_file').start()
|
||||
self.import_rpm = mock.patch('kojihub.import_rpm').start()
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor').start()
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.new_package = mock.patch('kojihub.new_package').start()
|
||||
self.get_rpm_header = mock.patch('koji.get_rpm_header').start()
|
||||
self.pathinfo_work = mock.patch('koji.pathinfo.work').start()
|
||||
self.os_path_exists = mock.patch('os.path.exists').start()
|
||||
|
||||
self.rpm_header_retval = {
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
1000: 'name',
|
||||
|
|
@ -225,39 +51,21 @@ class TestImportBuild(unittest.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
mock.patch.stopall()
|
||||
|
||||
@mock.patch('kojihub.check_volume_policy')
|
||||
@mock.patch('kojihub.new_typed_build')
|
||||
@mock.patch('kojihub._dml')
|
||||
@mock.patch('kojihub._singleValue')
|
||||
@mock.patch('kojihub.get_build')
|
||||
@mock.patch('kojihub.add_rpm_sig')
|
||||
@mock.patch('koji.rip_rpm_sighdr')
|
||||
@mock.patch('kojihub.import_rpm_file')
|
||||
@mock.patch('kojihub.import_rpm')
|
||||
@mock.patch('kojihub.QueryProcessor')
|
||||
@mock.patch('kojihub.context')
|
||||
@mock.patch('kojihub.new_package')
|
||||
@mock.patch('koji.get_rpm_header')
|
||||
@mock.patch('koji.pathinfo.work')
|
||||
def test_import_build_completed_build(self, work, get_rpm_header,
|
||||
new_package, context, query,
|
||||
import_rpm, import_rpm_file,
|
||||
rip_rpm_sighdr, add_rpm_sig,
|
||||
get_build, _singleValue, _dml,
|
||||
new_typed_build, check_volume_policy):
|
||||
def test_import_build_completed_build(self):
|
||||
|
||||
rip_rpm_sighdr.return_value = (0, 0)
|
||||
self.rip_rpm_sighdr.return_value = (0, 0)
|
||||
|
||||
processor = mock.MagicMock()
|
||||
processor.executeOne.return_value = None
|
||||
query.return_value = processor
|
||||
self.QueryProcessor.return_value = processor
|
||||
|
||||
context.session.user_id = 99
|
||||
self.context.session.user_id = 99
|
||||
|
||||
work.return_value = '/'
|
||||
self.pathinfo_work.return_value = '/'
|
||||
|
||||
check_volume_policy.return_value = {'id':0, 'name': 'DEFAULT'}
|
||||
self.check_volume_policy.return_value = {'id': 0, 'name': 'DEFAULT'}
|
||||
|
||||
retval = copy.copy(self.rpm_header_retval)
|
||||
retval.update({
|
||||
|
|
@ -266,7 +74,7 @@ class TestImportBuild(unittest.TestCase):
|
|||
1022: 'src',
|
||||
1106: 1,
|
||||
})
|
||||
get_rpm_header.return_value = retval
|
||||
self.get_rpm_header.return_value = retval
|
||||
binfo = {
|
||||
'state': koji.BUILD_STATES['COMPLETE'],
|
||||
'name': 'name',
|
||||
|
|
@ -277,7 +85,7 @@ class TestImportBuild(unittest.TestCase):
|
|||
# get_build called once to check for existing,
|
||||
# if it doesn't exist, called another time after creating
|
||||
# then 3rd later to get the build info
|
||||
get_build.side_effect = [None, binfo, binfo]
|
||||
self.get_build.side_effect = [None, binfo, binfo]
|
||||
|
||||
kojihub.import_build(self.src_filename, [self.filename])
|
||||
|
||||
|
|
@ -315,13 +123,29 @@ class TestImportBuild(unittest.TestCase):
|
|||
'pkg_id': mock.ANY,
|
||||
'id': mock.ANY,
|
||||
}
|
||||
_dml.assert_called_once_with(statement, values)
|
||||
self._dml.assert_called_once_with(statement, values)
|
||||
|
||||
@mock.patch('os.path.exists')
|
||||
def test_import_build_non_exist_file(self, os_path_exists):
|
||||
def test_import_build_non_exist_file(self):
|
||||
uploadpath = koji.pathinfo.work()
|
||||
os_path_exists.return_value = False
|
||||
self.os_path_exists.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_build(self.src_filename, [self.filename])
|
||||
self.assertEqual("No such file: %s/%s" % (uploadpath, self.src_filename),
|
||||
self.assertEqual(f"No such file: {uploadpath}/{self.src_filename}", str(cm.exception))
|
||||
|
||||
def test_import_build_wrong_type_brmap(self):
|
||||
brmap = 'test-brmap'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_build(self.src_filename, [self.filename], brmap=brmap)
|
||||
self.assertEqual(f"Invalid type for value '{brmap}': {type(brmap)}", str(cm.exception))
|
||||
|
||||
def test_import_build_wrong_type_srpm(self):
|
||||
srpm = ['test-srpm']
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_build(srpm, [self.filename])
|
||||
self.assertEqual(f"Invalid type for value '{srpm}': {type(srpm)}", str(cm.exception))
|
||||
|
||||
def test_import_build_wrong_type_rpms(self):
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_build(self.src_filename, self.filename)
|
||||
self.assertEqual(f"Invalid type for value '{self.filename}': {type(self.filename)}",
|
||||
str(cm.exception))
|
||||
|
|
|
|||
187
tests/test_hub/test_import_rpm.py
Normal file
187
tests/test_hub/test_import_rpm.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
import mock
|
||||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import shutil
|
||||
import tempfile
|
||||
import copy
|
||||
|
||||
|
||||
class TestImportRPM(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.exports = kojihub.RootExports()
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
self.filename = self.tempdir + "/name-version-release.arch.rpm"
|
||||
# Touch a file
|
||||
with open(self.filename, 'w'):
|
||||
pass
|
||||
self.src_filename = self.tempdir + "/name-version-release.src.rpm"
|
||||
# Touch a file
|
||||
with open(self.src_filename, 'w'):
|
||||
pass
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.cursor = mock.MagicMock()
|
||||
|
||||
self.rpm_header_retval = {
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
'sourcepackage': 2,
|
||||
1000: 'name',
|
||||
1001: 'version',
|
||||
1002: 'release',
|
||||
1003: 'epoch',
|
||||
1006: 'buildtime',
|
||||
1022: 'arch',
|
||||
1044: 'name-version-release.arch',
|
||||
1106: 'sourcepackage',
|
||||
261: 'payload hash',
|
||||
}
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
self.get_rpm_header = mock.patch('koji.get_rpm_header').start()
|
||||
self.new_typed_build = mock.patch('kojihub.new_typed_build').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self._singleValue = mock.patch('kojihub._singleValue').start()
|
||||
self.os_path_exists = mock.patch('os.path.exists').start()
|
||||
self.os_path_basename = mock.patch('os.path.basename').start()
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_nonexistant_rpm(self):
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.import_rpm("this does not exist")
|
||||
|
||||
def test_import_rpm_failed_build(self):
|
||||
self.get_rpm_header.return_value = self.rpm_header_retval
|
||||
self.get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['FAILED'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
}
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.import_rpm(self.filename)
|
||||
|
||||
def test_import_rpm_completed_build(self):
|
||||
self.os_path_basename.return_value = 'name-version-release.arch.rpm'
|
||||
self.get_rpm_header.return_value = self.rpm_header_retval
|
||||
self.get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['COMPLETE'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
'id': 12345,
|
||||
}
|
||||
self._singleValue.return_value = 9876
|
||||
kojihub.import_rpm(self.filename)
|
||||
fields = [
|
||||
'arch',
|
||||
'build_id',
|
||||
'buildroot_id',
|
||||
'buildtime',
|
||||
'epoch',
|
||||
'external_repo_id',
|
||||
'id',
|
||||
'name',
|
||||
'payloadhash',
|
||||
'release',
|
||||
'size',
|
||||
'version',
|
||||
]
|
||||
statement = 'INSERT INTO rpminfo (%s) VALUES (%s)' % (
|
||||
", ".join(fields),
|
||||
", ".join(['%%(%s)s' % field for field in fields])
|
||||
)
|
||||
values = {
|
||||
'build_id': 12345,
|
||||
'name': 'name',
|
||||
'arch': 'arch',
|
||||
'buildtime': 'buildtime',
|
||||
'payloadhash': '7061796c6f61642068617368',
|
||||
'epoch': 'epoch',
|
||||
'version': 'version',
|
||||
'buildroot_id': None,
|
||||
'release': 'release',
|
||||
'external_repo_id': 0,
|
||||
'id': 9876,
|
||||
'size': 0,
|
||||
}
|
||||
self._dml.assert_called_once_with(statement, values)
|
||||
|
||||
def test_import_rpm_completed_source_build(self):
|
||||
self.os_path_basename.return_value = 'name-version-release.src.rpm'
|
||||
retval = copy.copy(self.rpm_header_retval)
|
||||
retval.update({
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
1044: 'name-version-release.src',
|
||||
1022: 'src',
|
||||
1106: 1,
|
||||
})
|
||||
self.get_rpm_header.return_value = retval
|
||||
self.get_build.return_value = {
|
||||
'state': koji.BUILD_STATES['COMPLETE'],
|
||||
'name': 'name',
|
||||
'version': 'version',
|
||||
'release': 'release',
|
||||
'id': 12345,
|
||||
}
|
||||
self._singleValue.return_value = 9876
|
||||
kojihub.import_rpm(self.src_filename)
|
||||
fields = [
|
||||
'arch',
|
||||
'build_id',
|
||||
'buildroot_id',
|
||||
'buildtime',
|
||||
'epoch',
|
||||
'external_repo_id',
|
||||
'id',
|
||||
'name',
|
||||
'payloadhash',
|
||||
'release',
|
||||
'size',
|
||||
'version',
|
||||
]
|
||||
statement = 'INSERT INTO rpminfo (%s) VALUES (%s)' % (
|
||||
", ".join(fields),
|
||||
", ".join(['%%(%s)s' % field for field in fields])
|
||||
)
|
||||
values = {
|
||||
'build_id': 12345,
|
||||
'name': 'name',
|
||||
'arch': 'src',
|
||||
'buildtime': 'buildtime',
|
||||
'payloadhash': '7061796c6f61642068617368',
|
||||
'epoch': 'epoch',
|
||||
'version': 'version',
|
||||
'buildroot_id': None,
|
||||
'release': 'release',
|
||||
'external_repo_id': 0,
|
||||
'id': 9876,
|
||||
'size': 0,
|
||||
}
|
||||
self._dml.assert_called_once_with(statement, values)
|
||||
|
||||
def test_non_exist_file(self):
|
||||
basename = 'rpm-1-34'
|
||||
self.os_path_exists.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_rpm(self.filename, basename)
|
||||
self.assertEqual(f"No such file: {self.filename}", str(cm.exception))
|
||||
|
||||
def test_non_exist_build(self):
|
||||
self.cursor.fetchone.return_value = None
|
||||
self.context.cnx.cursor.return_value = self.cursor
|
||||
retval = copy.copy(self.rpm_header_retval)
|
||||
retval.update({
|
||||
'filename': 'name-version-release.arch.rpm',
|
||||
'sourcepackage': 2
|
||||
})
|
||||
self.get_rpm_header.return_value = retval
|
||||
self.os_path_exists.return_value = True
|
||||
self.os_path_basename.return_value = 'name-version-release.arch.rpm'
|
||||
kojihub.get_build.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.import_rpm(self.src_filename)
|
||||
self.assertEqual("No such build", str(cm.exception))
|
||||
|
|
@ -1,265 +1,224 @@
|
|||
import mock
|
||||
from .utils import DBQueryTestCase
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
|
||||
class TestListArchives(DBQueryTestCase):
|
||||
maxDiff = None
|
||||
|
||||
class TestListArchives(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
self.get_host = mock.patch('kojihub.get_host').start()
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.get_query).start()
|
||||
self.queries = []
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def get_query(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def test_list_archives_simple(self):
|
||||
rv = kojihub.list_archives()
|
||||
kojihub.list_archives()
|
||||
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=[],
|
||||
values={})
|
||||
self.assertEqual(rv, [])
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, [])
|
||||
self.assertEqual(query.joins, ['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
|
||||
def test_list_archives_strict(self):
|
||||
@mock.patch('kojihub.QueryProcessor')
|
||||
def test_list_archives_strict(self, QueryProcessor):
|
||||
query = QueryProcessor.return_value
|
||||
query.execute.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.list_archives(strict=True)
|
||||
self.assertEqual(cm.exception.args[0], 'No archives found.')
|
||||
|
||||
def test_list_archives_buildid(self):
|
||||
kojihub.list_archives(buildID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['build_id = %(build_id)i'],
|
||||
values={'build_id': 1})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['build_id = %(build_id)i'])
|
||||
self.assertEqual(query.joins, ['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'build_id': 1})
|
||||
|
||||
def test_list_archives_buildrootid(self):
|
||||
kojihub.list_archives(buildrootID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['buildroot_id = %(buildroot_id)i'],
|
||||
values={'buildroot_id': 1})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['buildroot_id = %(buildroot_id)i'])
|
||||
self.assertEqual(query.joins, ['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'buildroot_id': 1})
|
||||
|
||||
def test_list_archives_componentbuildrootid(self):
|
||||
kojihub.list_archives(componentBuildrootID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'buildroot_archives on archiveinfo.id = buildroot_archives.archive_id'],
|
||||
clauses=['buildroot_archives.buildroot_id = %(component_buildroot_id)i'],
|
||||
values={'component_buildroot_id': 1},
|
||||
colsByAlias={'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'component_buildroot_id': 'buildroot_archives.buildroot_id',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'project': 'buildroot_archives.project_dep',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses,
|
||||
['buildroot_archives.buildroot_id = %(component_buildroot_id)i'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'buildroot_archives on archiveinfo.id = buildroot_archives.archive_id'])
|
||||
self.assertEqual(query.values, {'component_buildroot_id': 1})
|
||||
|
||||
def test_list_archives_imageid(self):
|
||||
kojihub.list_archives(imageID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'archive_components ON archiveinfo.id = archive_components.component_id'],
|
||||
clauses=['archive_components.archive_id = %(imageID)i'],
|
||||
values={'imageID': 1})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['archive_components.archive_id = %(imageID)i'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'archive_components ON archiveinfo.id = '
|
||||
'archive_components.component_id'])
|
||||
self.assertEqual(query.values, {'imageID': 1})
|
||||
|
||||
def test_list_archives_hostid(self):
|
||||
kojihub.list_archives(hostID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'standard_buildroot on archiveinfo.buildroot_id = standard_buildroot.buildroot_id'],
|
||||
clauses=['standard_buildroot.host_id = %(host_id)i'],
|
||||
values={'host_id': 1},
|
||||
colsByAlias={'host_id': 'standard_buildroot.host_id',
|
||||
'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['standard_buildroot.host_id = %(host_id)i'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'standard_buildroot on archiveinfo.buildroot_id = '
|
||||
'standard_buildroot.buildroot_id'])
|
||||
self.assertEqual(query.values, {'host_id': 1})
|
||||
|
||||
def test_list_archives_filename(self):
|
||||
kojihub.list_archives(filename='somefile.txt')
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['filename = %(filename)s'],
|
||||
values={'filename': 'somefile.txt'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['filename = %(filename)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'filename': 'somefile.txt'})
|
||||
|
||||
def test_list_archives_size(self):
|
||||
kojihub.list_archives(size=1231831)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['size = %(size)i'],
|
||||
values={'size': 1231831})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['size = %(size)i'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'size': 1231831})
|
||||
|
||||
def test_list_archives_checksum(self):
|
||||
kojihub.list_archives(checksum='7873f0a6dbf3abc07724e000ac9b3941')
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['checksum = %(checksum)s'],
|
||||
values={'checksum': '7873f0a6dbf3abc07724e000ac9b3941'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['checksum = %(checksum)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'checksum': '7873f0a6dbf3abc07724e000ac9b3941'})
|
||||
|
||||
def test_list_archives_checksum_type(self):
|
||||
kojihub.list_archives(checksum_type=koji.CHECKSUM_TYPES['sha256'])
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['checksum_type = %(checksum_type)s'],
|
||||
values={'checksum_type': koji.CHECKSUM_TYPES['sha256']})
|
||||
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['checksum_type = %(checksum_type)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'checksum_type': koji.CHECKSUM_TYPES['sha256']})
|
||||
|
||||
def test_list_archives_archiveid(self):
|
||||
kojihub.list_archives(archiveID=1)
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['archiveinfo.id = %(archive_id)s'],
|
||||
values={'archive_id': 1})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['archiveinfo.id = %(archive_id)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'archive_id': 1})
|
||||
|
||||
def test_list_archives_type_maven(self):
|
||||
kojihub.list_archives(type='maven', typeInfo={'group_id': 'gid',
|
||||
'artifact_id': 'aid',
|
||||
'version': '1.0.1'})
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'maven_archives ON archiveinfo.id = maven_archives.archive_id'],
|
||||
clauses=['maven_archives.artifact_id = %(artifact_id)s',
|
||||
'maven_archives.group_id = %(group_id)s',
|
||||
'maven_archives.version = %(version)s'],
|
||||
values={'group_id': 'gid',
|
||||
'artifact_id': 'aid',
|
||||
'version': '1.0.1'},
|
||||
colsByAlias={'group_id': 'maven_archives.group_id',
|
||||
'artifact_id': 'maven_archives.artifact_id',
|
||||
'version': 'maven_archives.version',
|
||||
'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['maven_archives.artifact_id = %(artifact_id)s',
|
||||
'maven_archives.group_id = %(group_id)s',
|
||||
'maven_archives.version = %(version)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'maven_archives ON archiveinfo.id = maven_archives.archive_id'])
|
||||
self.assertEqual(query.values, {'group_id': 'gid',
|
||||
'artifact_id': 'aid',
|
||||
'version': '1.0.1'})
|
||||
|
||||
def test_list_archives_type_win(self):
|
||||
kojihub.list_archives(type='win', typeInfo={'relpath': 'somerelpath',
|
||||
'platforms': 'all',
|
||||
'flags': ['A', 'B']})
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=sorted([
|
||||
'archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'win_archives ON archiveinfo.id = win_archives.archive_id']),
|
||||
clauses=sorted([
|
||||
'win_archives.relpath = %(relpath)s',
|
||||
r"platforms ~ %(platforms_pattern_0)s",
|
||||
r"flags ~ %(flags_pattern_0)s",
|
||||
r"flags ~ %(flags_pattern_1)s"]),
|
||||
values={'relpath': 'somerelpath',
|
||||
'flags_pattern_0': '\\mA\\M',
|
||||
'flags_pattern_1': '\\mB\\M',
|
||||
'platforms_pattern_0': '\\mall\\M',
|
||||
},
|
||||
colsByAlias={'relpath': 'win_archives.relpath',
|
||||
'platforms': 'win_archives.platforms',
|
||||
'flags': 'win_archives.flags',
|
||||
'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, sorted(['win_archives.relpath = %(relpath)s',
|
||||
r"platforms ~ %(platforms_pattern_0)s",
|
||||
r"flags ~ %(flags_pattern_0)s",
|
||||
r"flags ~ %(flags_pattern_1)s"]))
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'win_archives ON archiveinfo.id = win_archives.archive_id'])
|
||||
self.assertEqual(query.values, {'relpath': 'somerelpath',
|
||||
'flags_pattern_0': '\\mA\\M',
|
||||
'flags_pattern_1': '\\mB\\M',
|
||||
'platforms_pattern_0': '\\mall\\M'})
|
||||
|
||||
def test_list_archives_type_image(self):
|
||||
kojihub.list_archives(type='image', typeInfo={'arch': 'i386'})
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'image_archives ON archiveinfo.id = image_archives.archive_id'],
|
||||
clauses=['image_archives.arch = %(arch)s'],
|
||||
values={'arch': 'i386'},
|
||||
colsByAlias={'arch': 'image_archives.arch',
|
||||
'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['image_archives.arch = %(arch)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id',
|
||||
'image_archives ON archiveinfo.id = image_archives.archive_id'])
|
||||
self.assertEqual(query.values, {'arch': 'i386'})
|
||||
|
||||
@mock.patch('kojihub.lookup_name', return_value={'id': 111, 'name': 'other'})
|
||||
def test_list_archives_type_others(self, lookup_name):
|
||||
kojihub.list_archives(type='other')
|
||||
self.assertLastQueryEqual(tables=['archiveinfo'],
|
||||
joins=['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'],
|
||||
clauses=['archiveinfo.btype_id = %(btype_id)s'],
|
||||
values={'btype_id': 111},
|
||||
colsByAlias={'build_id': 'archiveinfo.build_id',
|
||||
'type_name': 'archivetypes.name',
|
||||
'type_id': 'archiveinfo.type_id',
|
||||
'checksum': 'archiveinfo.checksum',
|
||||
'extra': 'archiveinfo.extra',
|
||||
'filename': 'archiveinfo.filename',
|
||||
'type_description': 'archivetypes.description',
|
||||
'metadata_only': 'archiveinfo.metadata_only',
|
||||
'type_extensions': 'archivetypes.extensions',
|
||||
'btype': 'btype.name',
|
||||
'checksum_type': 'archiveinfo.checksum_type',
|
||||
'btype_id': 'archiveinfo.btype_id',
|
||||
'buildroot_id': 'archiveinfo.buildroot_id',
|
||||
'id': 'archiveinfo.id',
|
||||
'size': 'archiveinfo.size'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['archiveinfo'])
|
||||
self.assertEqual(query.clauses, ['archiveinfo.btype_id = %(btype_id)s'])
|
||||
self.assertEqual(query.joins,
|
||||
['archivetypes on archiveinfo.type_id = archivetypes.id',
|
||||
'btype ON archiveinfo.btype_id = btype.id'])
|
||||
self.assertEqual(query.values, {'btype_id': 111})
|
||||
|
||||
@mock.patch('kojihub.lookup_name', return_value=None)
|
||||
def test_list_archives_type_not_found(self, lookup_name):
|
||||
|
|
|
|||
|
|
@ -8,64 +8,58 @@ QP = kojihub.QueryProcessor
|
|||
|
||||
class TestListBTypes(unittest.TestCase):
|
||||
|
||||
@mock.patch('kojihub.QueryProcessor')
|
||||
def test_list_btypes(self, QueryProcessor):
|
||||
def setUp(self):
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.get_query).start()
|
||||
self.queries = []
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
# default query
|
||||
query = QueryProcessor.return_value
|
||||
query.execute.return_value = "return value"
|
||||
ret = kojihub.list_btypes()
|
||||
QueryProcessor.assert_called_once()
|
||||
query.execute.assert_called_once()
|
||||
self.assertEqual(ret, "return value")
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
args, kwargs = QueryProcessor.call_args
|
||||
def get_query(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def test_list_btypes_default(self):
|
||||
kojihub.list_btypes()
|
||||
self.QueryProcessor.assert_called_once()
|
||||
|
||||
args, kwargs = self.QueryProcessor.call_args
|
||||
self.assertEqual(args, ())
|
||||
qp = QP(**kwargs)
|
||||
self.assertEqual(qp.tables, ['btype'])
|
||||
self.assertEqual(qp.columns, ['id', 'name'])
|
||||
self.assertEqual(qp.clauses, [])
|
||||
self.assertEqual(qp.joins, None)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['btype'])
|
||||
self.assertEqual(query.columns, ['id', 'name'])
|
||||
self.assertEqual(query.clauses, [])
|
||||
self.assertEqual(query.joins, None)
|
||||
|
||||
QueryProcessor.reset_mock()
|
||||
def test_list_btypes_by_name(self):
|
||||
kojihub.list_btypes({'name': 'rpm'})
|
||||
self.QueryProcessor.assert_called_once()
|
||||
|
||||
# query by name
|
||||
query = QueryProcessor.return_value
|
||||
query.execute.return_value = "return value"
|
||||
ret = kojihub.list_btypes({'name': 'rpm'})
|
||||
QueryProcessor.assert_called_once()
|
||||
query.execute.assert_called_once()
|
||||
self.assertEqual(ret, "return value")
|
||||
|
||||
args, kwargs = QueryProcessor.call_args
|
||||
args, kwargs = self.QueryProcessor.call_args
|
||||
self.assertEqual(args, ())
|
||||
qp = QP(**kwargs)
|
||||
self.assertEqual(qp.tables, ['btype'])
|
||||
self.assertEqual(qp.columns, ['id', 'name'])
|
||||
self.assertEqual(qp.clauses, ['btype.name = %(name)s'])
|
||||
self.assertEqual(qp.values, {'name': 'rpm'})
|
||||
self.assertEqual(qp.joins, None)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['btype'])
|
||||
self.assertEqual(query.columns, ['id', 'name'])
|
||||
self.assertEqual(query.clauses, ['btype.name = %(name)s'])
|
||||
self.assertEqual(query.values, {'name': 'rpm'})
|
||||
self.assertEqual(query.joins, None)
|
||||
|
||||
QueryProcessor.reset_mock()
|
||||
def test_list_btypes_by_it_with_opts(self):
|
||||
kojihub.list_btypes({'id': 1}, {'order': 'id'})
|
||||
self.QueryProcessor.assert_called_once()
|
||||
|
||||
# query by id, with opts
|
||||
query = QueryProcessor.return_value
|
||||
query.execute.return_value = "return value"
|
||||
ret = kojihub.list_btypes({'id': 1}, {'order': 'id'})
|
||||
QueryProcessor.assert_called_once()
|
||||
query.execute.assert_called_once()
|
||||
self.assertEqual(ret, "return value")
|
||||
|
||||
args, kwargs = QueryProcessor.call_args
|
||||
args, kwargs = self.QueryProcessor.call_args
|
||||
self.assertEqual(args, ())
|
||||
qp = QP(**kwargs)
|
||||
self.assertEqual(qp.tables, ['btype'])
|
||||
self.assertEqual(qp.columns, ['id', 'name'])
|
||||
self.assertEqual(qp.clauses, ['btype.id = %(id)s'])
|
||||
self.assertEqual(qp.values, {'id': 1})
|
||||
self.assertEqual(qp.opts, {'order': 'id'})
|
||||
self.assertEqual(qp.joins, None)
|
||||
|
||||
QueryProcessor.reset_mock()
|
||||
|
||||
# query by name
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['btype'])
|
||||
self.assertEqual(query.columns, ['id', 'name'])
|
||||
self.assertEqual(query.clauses, ['btype.id = %(id)s'])
|
||||
self.assertEqual(query.values, {'id': 1})
|
||||
self.assertEqual(query.opts, {'order': 'id'})
|
||||
self.assertEqual(query.joins, None)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ class TestListBuilds(unittest.TestCase):
|
|||
self.queries = []
|
||||
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.get_package_id = mock.patch('kojihub.get_package_id').start()
|
||||
self.get_user = mock.patch('kojihub.get_user').start()
|
||||
self.cursor = mock.MagicMock()
|
||||
self.build_list = [{'build_id': 9,
|
||||
'epoch': 0,
|
||||
|
|
@ -41,18 +43,16 @@ class TestListBuilds(unittest.TestCase):
|
|||
'volume_id': 0,
|
||||
'volume_name': 'DEFAULT'}]
|
||||
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_wrong_package(self, get_package_id):
|
||||
def test_wrong_package(self):
|
||||
package = 'test-package'
|
||||
get_package_id.return_value = None
|
||||
self.get_package_id.return_value = None
|
||||
rv = self.exports.listBuilds(packageID=package)
|
||||
self.assertEqual(rv, [])
|
||||
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_package_string(self, get_package_id):
|
||||
def test_package_string(self):
|
||||
package = 'test-package'
|
||||
package_id = 1
|
||||
get_package_id.return_value = package_id
|
||||
self.get_package_id.return_value = package_id
|
||||
self.query_executeOne.return_value = None
|
||||
self.exports.listBuilds(packageID=package)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
|
|
@ -76,9 +76,8 @@ class TestListBuilds(unittest.TestCase):
|
|||
'LEFT JOIN volume ON build.volume_id = volume.id',
|
||||
'LEFT JOIN users ON build.owner = users.id'])
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
def test_wrong_user(self, get_user):
|
||||
def test_wrong_user(self):
|
||||
user = 'test-user'
|
||||
get_user.return_value = None
|
||||
self.get_user.return_value = None
|
||||
rv = self.exports.listBuilds(userID=user)
|
||||
self.assertEqual(rv, [])
|
||||
|
|
|
|||
40
tests/test_hub/test_list_packages_simple.py
Normal file
40
tests/test_hub/test_list_packages_simple.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import unittest
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
|
||||
|
||||
class TestListPackagesSimple(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.maxDiff = None
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.get_query).start()
|
||||
self.queries = []
|
||||
self.exports = kojihub.RootExports()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def get_query(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def test_prefix_not_none(self):
|
||||
self.exports.listPackagesSimple('test-prefix')
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['package'])
|
||||
self.assertEqual(query.clauses, ["package.name ILIKE %(prefix)s || '%%'"])
|
||||
self.assertEqual(query.joins, None)
|
||||
|
||||
def test_prefix_is_none(self):
|
||||
self.exports.listPackagesSimple()
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['package'])
|
||||
self.assertEqual(query.clauses, None)
|
||||
self.assertEqual(query.joins, None)
|
||||
|
|
@ -1,14 +1,87 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
|
||||
|
||||
class TestListRpms(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.get_query).start()
|
||||
self.queries = []
|
||||
self.get_build = mock.patch('kojihub.get_build').start()
|
||||
self.get_host = mock.patch('kojihub.get_host').start()
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self.list_rpms = {'arch': 'x86_64',
|
||||
'build_id': 1,
|
||||
'buildroot_id': 2,
|
||||
'buildtime': 1596090711,
|
||||
'epoch': 2,
|
||||
'external_repo_id': 1,
|
||||
'external_repo_name': 'fedora-34-released',
|
||||
'extra': None,
|
||||
'id': 277,
|
||||
'metadata_only': False,
|
||||
'name': 'shadow-utils',
|
||||
'nvr': 'shadow-utils-4.8.1-4.fc33',
|
||||
'payloadhash': 'c5bfe5267dc6e0ca127092a82b4f260b',
|
||||
'release': '4.fc33',
|
||||
'size': 3891272,
|
||||
'version': '4.8.1'}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def get_query(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def test_wrong_type_arches(self):
|
||||
arches = {'test-arch': 'val'}
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.list_rpms(arches=arches)
|
||||
self.assertEqual('Invalid type for "arches" parameter: %s' % type(arches),
|
||||
str(cm.exception))
|
||||
self.assertEqual(f'Invalid type for "arches" parameter: {type(arches)}', str(cm.exception))
|
||||
|
||||
def test_int_values(self):
|
||||
build_id = 1
|
||||
buildroot_id = 1
|
||||
host_id = 1
|
||||
arches = 'x86_64'
|
||||
kojihub.list_rpms(arches=arches, buildID=build_id, buildrootID=buildroot_id,
|
||||
hostID=host_id)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['rpminfo'])
|
||||
self.assertEqual(query.joins,
|
||||
['LEFT JOIN external_repo ON rpminfo.external_repo_id = external_repo.id',
|
||||
'standard_buildroot ON rpminfo.buildroot_id = '
|
||||
'standard_buildroot.buildroot_id'])
|
||||
self.assertEqual(query.clauses, [
|
||||
'rpminfo.arch = %(arches)s',
|
||||
'rpminfo.build_id = %(buildID)i',
|
||||
'rpminfo.buildroot_id = %(buildrootID)i',
|
||||
'standard_buildroot.host_id = %(hostID)i',
|
||||
])
|
||||
|
||||
def test_compoenent_buldroot_image_list_arch_values(self):
|
||||
comp_buildroot_id = 1
|
||||
image_id = 1
|
||||
arches = ['x86_64']
|
||||
kojihub.list_rpms(componentBuildrootID=comp_buildroot_id, imageID=image_id, arches=arches)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
self.assertEqual(query.tables, ['rpminfo'])
|
||||
self.assertEqual(query.joins,
|
||||
['LEFT JOIN external_repo ON rpminfo.external_repo_id = external_repo.id',
|
||||
'buildroot_listing ON rpminfo.id = buildroot_listing.rpm_id',
|
||||
'archive_rpm_components ON rpminfo.id = archive_rpm_components.rpm_id'])
|
||||
self.assertEqual(query.clauses, [
|
||||
'archive_rpm_components.archive_id = %(imageID)i',
|
||||
'buildroot_listing.buildroot_id = %(componentBuildrootID)i',
|
||||
'rpminfo.arch IN %(arches)s',
|
||||
])
|
||||
|
|
|
|||
|
|
@ -44,12 +44,11 @@ class TestLookupName(unittest.TestCase):
|
|||
{'id': 'not a valid int'},
|
||||
['something'],
|
||||
set(),
|
||||
]
|
||||
]
|
||||
for value in bad_values:
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.lookup_name('mytable', value)
|
||||
self.assertEqual('Invalid name or id value: %s' % value,
|
||||
str(cm.exception))
|
||||
self.assertEqual(f'Invalid name or id value: {value}', str(cm.exception))
|
||||
self.assertEqual(len(self.queries), 0)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
|
|
@ -78,7 +77,7 @@ class TestLookupName(unittest.TestCase):
|
|||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_query_by_dict(self):
|
||||
kojihub.lookup_name('some_table', {'id':12345, 'name': 'whatever'})
|
||||
kojihub.lookup_name('some_table', {'id': 12345, 'name': 'whatever'})
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
clauses = ['(some_table.id = %(some_table_id)s)']
|
||||
|
|
@ -110,7 +109,7 @@ class TestLookupName(unittest.TestCase):
|
|||
|
||||
def test_lookup_name_strict(self):
|
||||
self.query_executeOne.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.lookup_name('package', 'python', strict=True)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
|
@ -134,7 +133,7 @@ class TestLookupName(unittest.TestCase):
|
|||
bad_values = [
|
||||
{'id': 100},
|
||||
100
|
||||
]
|
||||
]
|
||||
for value in bad_values:
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.lookup_name('package', value, create=True)
|
||||
|
|
|
|||
49
tests/test_hub/test_maven_build.py
Normal file
49
tests/test_hub/test_maven_build.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestMaven(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.url = 'https://test-url.com'
|
||||
self.target = 'test-target'
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_maven_not_supported(self):
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.mavenBuild(self.url, self.target)
|
||||
self.assertEqual("Maven support not enabled", str(cm.exception))
|
||||
|
||||
def test_url_not_str(self):
|
||||
url = ['test-url']
|
||||
self.context.opts.get.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.mavenBuild(url, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{url}': {type(url)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.opts.get.return_value = True
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.mavenBuild(self.url, self.target, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
priority = 10
|
||||
self.context.opts.get.return_value = True
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 2, 'name': 'maven'}
|
||||
self.make_task.return_value = 123
|
||||
self.exports.mavenBuild(self.url, self.target, priority=priority, channel=2)
|
||||
|
|
@ -6,6 +6,7 @@ import kojihub
|
|||
|
||||
IP = kojihub.InsertProcessor
|
||||
|
||||
|
||||
class TestNewBuild(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.get_rpm = mock.patch('kojihub.get_rpm').start()
|
||||
|
|
@ -13,7 +14,7 @@ class TestNewBuild(unittest.TestCase):
|
|||
self.nextval = mock.patch('kojihub.nextval').start()
|
||||
self.Savepoint = mock.patch('kojihub.Savepoint').start()
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.insert_execute = mock.MagicMock()
|
||||
self.lookup_package = mock.patch('kojihub.lookup_package').start()
|
||||
|
|
@ -35,7 +36,7 @@ class TestNewBuild(unittest.TestCase):
|
|||
|
||||
def test_valid(self):
|
||||
self.get_build.return_value = None
|
||||
self._singleValue.return_value = 65 # free build id
|
||||
self._singleValue.return_value = 65 # free build id
|
||||
self.new_package.return_value = 54
|
||||
self.get_user.return_value = {'id': 123}
|
||||
data = {
|
||||
|
|
@ -99,10 +100,11 @@ class TestNewBuild(unittest.TestCase):
|
|||
'extra': {'extra_key': 'extra_value'},
|
||||
}
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.new_build(data)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual("No name or package id provided for build", str(cm.exception))
|
||||
|
||||
def test_wrong_owner(self):
|
||||
self.get_user.side_effect = koji.GenericError
|
||||
|
|
@ -121,7 +123,6 @@ class TestNewBuild(unittest.TestCase):
|
|||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
def test_missing_vre(self):
|
||||
self.get_user.side_effect = koji.GenericError
|
||||
data = {
|
||||
'name': 'test_name',
|
||||
'version': 'test_version',
|
||||
|
|
|
|||
|
|
@ -1,821 +0,0 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
class TestNotifications(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.exports.getUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.exports.getBuildNotification = mock.MagicMock()
|
||||
self.exports.getBuildNotificationBlock = mock.MagicMock()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_watchers(self, readPackageList, get_user):
|
||||
# without build / tag_id
|
||||
build = None
|
||||
tag_id = None
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, [])
|
||||
|
||||
# only query to watchers
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s'])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
'''
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, ['user_id IN %(user_ids)s'])
|
||||
self.assertEqual(q.joins, [])
|
||||
self.assertEqual(q.values['user_ids'], None)
|
||||
'''
|
||||
readPackageList.assert_not_called()
|
||||
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_build_without_tag(self, readPackageList, get_user):
|
||||
### with build without tag
|
||||
tag_id = None
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
self.queries = []
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
||||
# there should be only query to watchers
|
||||
self.assertEqual(len(self.queries), 2)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s'])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['package_id'], build['package_id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, [
|
||||
'package_id = %(package_id)i OR package_id IS NULL',
|
||||
'tag_id IS NULL',
|
||||
'user_id IN %(user_ids)s',
|
||||
])
|
||||
self.assertEqual(q.joins, None)
|
||||
self.assertEqual(q.values['user_ids'], [5])
|
||||
|
||||
readPackageList.assert_not_called()
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_tag_without_build(self, readPackageList, get_user):
|
||||
### with tag without build makes no sense
|
||||
build = None
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
self.queries = []
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(self.queries, [])
|
||||
readPackageList.assert_not_called()
|
||||
|
||||
def set_queries(self, return_values):
|
||||
self.query_returns = return_values
|
||||
self.query_returns.reverse()
|
||||
def getQuery(*args, **kwargs):
|
||||
q = QP(*args, **kwargs)
|
||||
q.execute = mock.MagicMock()
|
||||
q.execute.return_value = self.query_returns.pop()
|
||||
self.queries.append(q)
|
||||
return q
|
||||
self.QueryProcessor.side_effect = getQuery
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_tag_with_build(self, readPackageList, get_user):
|
||||
### with tag and build
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
readPackageList.return_value = {12345: {'blocked': False, 'owner_id': 'owner_id'}}
|
||||
get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(sorted(emails), ['owner_name@test.domain.com', 'pkg_owner_name@test.domain.com'])
|
||||
|
||||
|
||||
# there should be only query to watchers
|
||||
self.assertEqual(len(self.queries), 2)
|
||||
q = self.queries[0]
|
||||
self.assertEqual(q.columns, ['email', 'user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications'])
|
||||
self.assertEqual(q.clauses, ['package_id = %(package_id)i OR package_id IS NULL',
|
||||
'status = %(users_status)i',
|
||||
'success_only = FALSE',
|
||||
'tag_id = %(tag_id)i OR tag_id IS NULL',
|
||||
'usertype IN %(users_usertypes)s',
|
||||
])
|
||||
self.assertEqual(q.joins, ['JOIN users ON build_notifications.user_id = users.id'])
|
||||
self.assertEqual(q.values['package_id'], build['package_id'])
|
||||
self.assertEqual(q.values['state'], state)
|
||||
self.assertEqual(q.values['build'], build)
|
||||
self.assertEqual(q.values['tag_id'], tag_id)
|
||||
|
||||
q = self.queries[1]
|
||||
self.assertEqual(q.columns, ['user_id'])
|
||||
self.assertEqual(q.tables, ['build_notifications_block'])
|
||||
self.assertEqual(q.clauses, [
|
||||
'package_id = %(package_id)i OR package_id IS NULL',
|
||||
'tag_id = %(tag_id)i OR tag_id IS NULL',
|
||||
'user_id IN %(user_ids)s',
|
||||
])
|
||||
self.assertEqual(q.joins, None)
|
||||
self.assertEqual(sorted(q.values['user_ids']), [5, 342])
|
||||
readPackageList.assert_called_once_with(pkgID=build['package_id'], tagID=tag_id, inherit=True)
|
||||
get_user.asssert_called_once_with(342, strict=True)
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_blocked_pkg_owner(self, readPackageList, get_user):
|
||||
# blocked package owner
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['BLOCKED'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_optout(self, readPackageList, get_user):
|
||||
# blocked package owner
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['NORMAL']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[{'user_id': 5}]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, [])
|
||||
|
||||
|
||||
@mock.patch('kojihub.get_user')
|
||||
@mock.patch('kojihub.readPackageList')
|
||||
def test_get_notification_recipients_machine(self, readPackageList, get_user):
|
||||
# package owner is machine
|
||||
build = {'package_id': 12345, 'owner_name': 'owner_name', 'owner_id': 5}
|
||||
tag_id = 123
|
||||
state = koji.BUILD_STATES['CANCELED']
|
||||
get_user.return_value = {
|
||||
'id': 342,
|
||||
'name': 'pkg_owner_name',
|
||||
'status': koji.USER_STATUS['NORMAL'],
|
||||
'usertype': koji.USERTYPES['HOST']
|
||||
}
|
||||
self.set_queries([
|
||||
[{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
[]
|
||||
])
|
||||
emails = kojihub.get_notification_recipients(build, tag_id, state)
|
||||
self.assertEqual(emails, ['owner_name@test.domain.com'])
|
||||
|
||||
#####################
|
||||
# Create notification
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'username'}
|
||||
self.exports.hasPerm.return_value = True
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notifications.return_value = []
|
||||
|
||||
r = self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.getUser.asssert_called_once_with(user_id)
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
get_package_id.assert_called_once_with(package_id, strict=True)
|
||||
get_tag_id.assert_called_once_with(tag_id, strict=True)
|
||||
get_build_notifications.assert_called_once_with(2)
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
self.assertEqual(insert.table, 'build_notifications')
|
||||
self.assertEqual(insert.data, {
|
||||
'package_id': package_id,
|
||||
'user_id': 2,
|
||||
'tag_id': tag_id,
|
||||
'success_only': success_only,
|
||||
'email': 'username@test.domain.com',
|
||||
})
|
||||
self.assertEqual(insert.rawdata, {})
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_unauthentized(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_invalid_user(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_no_perm(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'b'}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_invalid_pkg(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_invalid_tag(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotification_exists(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notifications.return_value = [{
|
||||
'package_id': package_id,
|
||||
'tag_id': tag_id,
|
||||
'success_only': success_only,
|
||||
}]
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotification(user_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
#####################
|
||||
# Delete notification
|
||||
@mock.patch('kojihub._dml')
|
||||
def test_deleteNotification(self, _dml):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
|
||||
self.exports.deleteNotification(n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(n_id, strict=True)
|
||||
self.exports.getLoggedInUser.assert_called_once_with()
|
||||
_dml.assert_called_once()
|
||||
|
||||
def test_deleteNotification_missing(self):
|
||||
n_id = 543
|
||||
self.exports.getBuildNotification.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotification(n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(n_id, strict=True)
|
||||
|
||||
def test_deleteNotification_not_logged(self):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
#self.set_queries = ([
|
||||
# [{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
#])
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotification(n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(n_id, strict=True)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
self.assertEqual(len(self.queries), 0)
|
||||
|
||||
@mock.patch('kojihub._dml')
|
||||
def test_deleteNotification_no_perm(self, _dml):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotification(n_id)
|
||||
|
||||
self.exports.getBuildNotification.assert_called_once_with(n_id, strict=True)
|
||||
_dml.assert_not_called()
|
||||
|
||||
|
||||
#####################
|
||||
# Update notification
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = True
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notifications.return_value = [{
|
||||
'tag_id': tag_id,
|
||||
'user_id': user_id,
|
||||
'package_id': package_id,
|
||||
'success_only': not success_only,
|
||||
}]
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
|
||||
r = self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
get_package_id.assert_called_once_with(package_id, strict=True)
|
||||
get_tag_id.assert_called_once_with(tag_id, strict=True)
|
||||
get_build_notifications.assert_called_once_with(user_id)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 1)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification_not_logged(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification_missing(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getBuildNotification.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification_no_perm(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 132}
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification_exists(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = True
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notifications.return_value = [{
|
||||
'tag_id': tag_id,
|
||||
'user_id': user_id,
|
||||
'package_id': package_id,
|
||||
'success_only': success_only,
|
||||
}]
|
||||
self.exports.getBuildNotification.return_value = {'user_id': user_id}
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
get_package_id.assert_called_once_with(package_id, strict=True)
|
||||
get_tag_id.assert_called_once_with(tag_id, strict=True)
|
||||
get_build_notifications.assert_called_once_with(user_id)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notifications')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_updateNotification_not_logged(self, get_package_id, get_tag_id,
|
||||
get_build_notifications):
|
||||
n_id = 5432
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(n_id, package_id, tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
###########################
|
||||
# Create notification block
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'username'}
|
||||
self.exports.hasPerm.return_value = True
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notification_blocks.return_value = []
|
||||
|
||||
r = self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.getUser.asssert_called_once_with(user_id)
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
get_package_id.assert_called_once_with(package_id, strict=True)
|
||||
get_tag_id.assert_called_once_with(tag_id, strict=True)
|
||||
get_build_notification_blocks.assert_called_once_with(2)
|
||||
self.assertEqual(len(self.inserts), 1)
|
||||
insert = self.inserts[0]
|
||||
self.assertEqual(insert.table, 'build_notifications_block')
|
||||
self.assertEqual(insert.data, {
|
||||
'package_id': package_id,
|
||||
'user_id': 2,
|
||||
'tag_id': tag_id,
|
||||
})
|
||||
self.assertEqual(insert.rawdata, {})
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_unauthentized(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 1
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_invalid_user(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_no_perm(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'b'}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_invalid_pkg(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_invalid_tag(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.side_effect = ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
@mock.patch('kojihub.get_build_notification_blocks')
|
||||
@mock.patch('kojihub.get_tag_id')
|
||||
@mock.patch('kojihub.get_package_id')
|
||||
def test_createNotificationBlock_exists(self, get_package_id, get_tag_id,
|
||||
get_build_notification_blocks):
|
||||
user_id = 2
|
||||
package_id = 234
|
||||
tag_id = 345
|
||||
self.exports.getLoggedInUser.return_value = {'id': 2, 'name': 'a'}
|
||||
self.exports.getUser.return_value = {'id': 2, 'name': 'a'}
|
||||
get_package_id.return_value = package_id
|
||||
get_tag_id.return_value = tag_id
|
||||
get_build_notification_blocks.return_value = [{
|
||||
'package_id': package_id,
|
||||
'tag_id': tag_id,
|
||||
}]
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.createNotificationBlock(user_id, package_id, tag_id)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
|
||||
###########################
|
||||
# Delete notification block
|
||||
@mock.patch('kojihub._dml')
|
||||
def test_deleteNotificationBlock(self, _dml):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': user_id}
|
||||
|
||||
self.exports.deleteNotificationBlock(n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(n_id, strict=True)
|
||||
self.exports.getLoggedInUser.assert_called_once_with()
|
||||
_dml.assert_called_once()
|
||||
|
||||
def test_deleteNotificationBlock_missing(self):
|
||||
n_id = 543
|
||||
self.exports.getBuildNotificationBlock.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotificationBlock(n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(n_id, strict=True)
|
||||
|
||||
def test_deleteNotificationBlock_not_logged(self):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': user_id}
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
#self.set_queries = ([
|
||||
# [{'user_id': 5, 'email': 'owner_name@%s' % self.context.opts['EmailDomain']}],
|
||||
#])
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotificationBlock(n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(n_id, strict=True)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
self.assertEqual(len(self.queries), 0)
|
||||
|
||||
@mock.patch('kojihub._dml')
|
||||
def test_deleteNotificationBlock_no_perm2(self, _dml):
|
||||
user_id = 752
|
||||
n_id = 543
|
||||
self.exports.getBuildNotificationBlock.return_value = {'user_id': user_id}
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.deleteNotificationBlock(n_id)
|
||||
|
||||
self.exports.getBuildNotificationBlock.assert_called_once_with(n_id, strict=True)
|
||||
_dml.assert_not_called()
|
||||
13
tests/test_hub/test_repo_delete.py
Normal file
13
tests/test_hub/test_repo_delete.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestRepoDelete(unittest.TestCase):
|
||||
|
||||
def test_repo_delete_wrong_type_typeID(self):
|
||||
repo_id = 'test-repo-id'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.repo_delete(repo_id)
|
||||
self.assertEqual(f"Invalid type for value '{repo_id}': {type(repo_id)}", str(cm.exception))
|
||||
13
tests/test_hub/test_repo_init.py
Normal file
13
tests/test_hub/test_repo_init.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestRepoInit(unittest.TestCase):
|
||||
|
||||
def test_repo_init_wrong_type_typeID(self):
|
||||
task_id = 'test-task_id'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.repo_init('test-tag', task_id)
|
||||
self.assertEqual(f"Invalid type for value '{task_id}': {type(task_id)}", str(cm.exception))
|
||||
13
tests/test_hub/test_repo_set_state.py
Normal file
13
tests/test_hub/test_repo_set_state.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestRepoSetState(unittest.TestCase):
|
||||
|
||||
def test_set_state_wrong_type_typeID(self):
|
||||
repo_id = 'test-repo-id'
|
||||
with self.assertRaises(koji.ParameterError) as cm:
|
||||
kojihub.repo_set_state(repo_id, 'failed')
|
||||
self.assertEqual(f"Invalid type for value '{repo_id}': {type(repo_id)}", str(cm.exception))
|
||||
|
|
@ -26,6 +26,7 @@ class TestRepoFunctions(unittest.TestCase):
|
|||
self.updates = []
|
||||
self._dml = mock.patch('kojihub._dml').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.get_tag = mock.patch('kojihub.get_tag').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
|
@ -83,7 +84,8 @@ class TestRepoFunctions(unittest.TestCase):
|
|||
'state': 0,
|
||||
'task_id': 15,
|
||||
'create_event': 32,
|
||||
'creation_time': datetime.datetime(2021, 3, 30, 12, 34, 5, 204023, tzinfo=datetime.timezone.utc),
|
||||
'creation_time': datetime.datetime(2021, 3, 30, 12, 34, 5, 204023,
|
||||
tzinfo=datetime.timezone.utc),
|
||||
'create_ts': 1617107645.204023,
|
||||
'tag_id': 3,
|
||||
'tag_name': 'test-tag',
|
||||
|
|
@ -92,8 +94,8 @@ class TestRepoFunctions(unittest.TestCase):
|
|||
rv = kojihub.repo_info(3)
|
||||
self.assertEqual(rv, repo_row)
|
||||
|
||||
def test_get_repo(self):
|
||||
rv = self.exports.getRepo(2)
|
||||
def test_get_repo_default(self):
|
||||
self.exports.getRepo(2)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
# make sure the following does not error
|
||||
|
|
@ -105,3 +107,17 @@ class TestRepoFunctions(unittest.TestCase):
|
|||
self.assertEqual(query.joins, ['events ON repo.create_event = events.id'])
|
||||
self.assertEqual(query.clauses, ['repo.dist is false', 'repo.state = %(state)s',
|
||||
'repo.tag_id = %(id)i'])
|
||||
|
||||
def test_get_repo_with_dist_and_event(self):
|
||||
self.exports.getRepo(2, event=111, dist=True)
|
||||
self.assertEqual(len(self.queries), 1)
|
||||
query = self.queries[0]
|
||||
# make sure the following does not error
|
||||
str(query)
|
||||
self.assertEqual(query.tables, ['repo'])
|
||||
columns = ['repo.id', 'repo.state', 'repo.task_id', 'repo.create_event',
|
||||
'EXTRACT(EPOCH FROM events.time)', 'repo.dist', 'events.time']
|
||||
self.assertEqual(set(query.columns), set(columns))
|
||||
self.assertEqual(query.joins, ['events ON repo.create_event = events.id'])
|
||||
self.assertEqual(query.clauses, ['create_event <= %(event)i', 'repo.dist is true',
|
||||
'repo.tag_id = %(id)i'])
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import unittest
|
|||
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
|
|
@ -13,12 +14,18 @@ class TestRestartHosts(unittest.TestCase):
|
|||
self.context.session.assertPerm = mock.MagicMock()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
|
||||
def options_is_none(self):
|
||||
def test_options_is_none(self):
|
||||
self.make_task.return_value = 13
|
||||
rv = self.exports.restartHosts()
|
||||
self.assertEqual(rv, 13)
|
||||
|
||||
def options_is_not_none(self):
|
||||
def test_options_is_not_none(self):
|
||||
self.make_task.return_value = 13
|
||||
rv = self.exports.restartHosts(options={'opt': 'open'})
|
||||
self.assertEqual(rv, 13)
|
||||
|
||||
def test_options_wrong_type(self):
|
||||
options = 'test-options'
|
||||
with self.assertRaises(koji.ParameterError) as ex:
|
||||
self.exports.restartHosts(options=options)
|
||||
self.assertEqual(f"Invalid type of options: {type(options)}", str(ex.exception))
|
||||
|
|
|
|||
|
|
@ -18,4 +18,4 @@ class TestSearch(unittest.TestCase):
|
|||
type = 'test-type'
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.search('item', type, 'glob')
|
||||
self.assertEqual("No such search type: %s" % type, str(cm.exception))
|
||||
self.assertEqual(f"No such search type: {type}", str(cm.exception))
|
||||
|
|
|
|||
|
|
@ -252,16 +252,22 @@ class TestGetTag(unittest.TestCase):
|
|||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.tagname = 'test-tag'
|
||||
|
||||
def test_get_tag_invalid_taginfo(self):
|
||||
taginfo = {'test-tag': 'value'}
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.get_tag(taginfo, strict=True)
|
||||
self.assertEqual("Invalid name or id value: %s" % taginfo, str(ex.exception))
|
||||
self.assertEqual(f"Invalid name or id value: {taginfo}", str(ex.exception))
|
||||
|
||||
def test_get_tag_non_exist_tag(self):
|
||||
taginfo = 'test-tag'
|
||||
self.query_executeOne.return_value = None
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.get_tag(taginfo, strict=True)
|
||||
self.assertEqual("No such tagInfo: '%s'" % taginfo, str(ex.exception))
|
||||
kojihub.get_tag(self.tagname, strict=True)
|
||||
self.assertEqual(f"No such tagInfo: '{self.tagname}'", str(ex.exception))
|
||||
|
||||
def test_get_tag_wrong_event(self):
|
||||
event = 'unsupported-event'
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
kojihub.get_tag(self.tagname, event=event)
|
||||
self.assertEqual(f"Invalid event: '{event}'", str(ex.exception))
|
||||
|
|
|
|||
148
tests/test_hub/test_update_notification.py
Normal file
148
tests/test_hub/test_update_notification.py
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
QP = kojihub.QueryProcessor
|
||||
IP = kojihub.InsertProcessor
|
||||
UP = kojihub.UpdateProcessor
|
||||
|
||||
|
||||
class TestUpdateNotifications(unittest.TestCase):
|
||||
def getInsert(self, *args, **kwargs):
|
||||
insert = IP(*args, **kwargs)
|
||||
insert.execute = mock.MagicMock()
|
||||
self.inserts.append(insert)
|
||||
return insert
|
||||
|
||||
def getQuery(self, *args, **kwargs):
|
||||
query = QP(*args, **kwargs)
|
||||
query.execute = mock.MagicMock()
|
||||
self.queries.append(query)
|
||||
return query
|
||||
|
||||
def getUpdate(self, *args, **kwargs):
|
||||
update = UP(*args, **kwargs)
|
||||
update.execute = mock.MagicMock()
|
||||
self.updates.append(update)
|
||||
return update
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.context.opts = {
|
||||
'EmailDomain': 'test.domain.com',
|
||||
'NotifyOnSuccess': True,
|
||||
}
|
||||
|
||||
self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
|
||||
side_effect=self.getQuery).start()
|
||||
self.queries = []
|
||||
self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
|
||||
side_effect=self.getInsert).start()
|
||||
self.inserts = []
|
||||
self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
|
||||
side_effect=self.getUpdate).start()
|
||||
self.updates = []
|
||||
self.get_build_notifications = mock.patch('kojihub.get_build_notifications').start()
|
||||
self.get_tag_id = mock.patch('kojihub.get_tag_id').start()
|
||||
self.get_package_id = mock.patch('kojihub.get_package_id').start()
|
||||
|
||||
self.exports = kojihub.RootExports()
|
||||
self.exports.getLoggedInUser = mock.MagicMock()
|
||||
self.exports.hasPerm = mock.MagicMock()
|
||||
self.exports.getBuildNotification = mock.MagicMock()
|
||||
self.user_id = 1
|
||||
self.n_id = 5432
|
||||
self.package_id = 234
|
||||
self.tag_id = 345
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_updateNotification(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = True
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notifications.return_value = [{
|
||||
'tag_id': self.tag_id,
|
||||
'user_id': self.user_id,
|
||||
'package_id': self.package_id,
|
||||
'success_only': not success_only,
|
||||
}]
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
|
||||
r = self.exports.updateNotification(self.n_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual(r, None)
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
self.get_package_id.assert_called_once_with(self.package_id, strict=True)
|
||||
self.get_tag_id.assert_called_once_with(self.tag_id, strict=True)
|
||||
self.get_build_notifications.assert_called_once_with(self.user_id)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 1)
|
||||
|
||||
def test_updateNotification_not_logged(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = None
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.updateNotification(self.n_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual('Not logged-in', str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
def test_updateNotification_missing(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.getBuildNotification.side_effect = koji.GenericError
|
||||
|
||||
with self.assertRaises(koji.GenericError):
|
||||
self.exports.updateNotification(self.n_id, self.package_id, self.tag_id, success_only)
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
def test_updateNotification_no_perm(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 132}
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
self.exports.hasPerm.return_value = False
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.updateNotification(self.n_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual(f'user 132 cannot update notifications for user {self.user_id}',
|
||||
str(cm.exception))
|
||||
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
|
||||
def test_updateNotification_exists(self):
|
||||
success_only = True
|
||||
self.exports.getLoggedInUser.return_value = {'id': 1}
|
||||
self.exports.hasPerm.return_value = True
|
||||
self.get_package_id.return_value = self.package_id
|
||||
self.get_tag_id.return_value = self.tag_id
|
||||
self.get_build_notifications.return_value = [{
|
||||
'tag_id': self.tag_id,
|
||||
'user_id': self.user_id,
|
||||
'package_id': self.package_id,
|
||||
'success_only': success_only,
|
||||
}]
|
||||
self.exports.getBuildNotification.return_value = {'user_id': self.user_id}
|
||||
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.updateNotification(self.n_id, self.package_id, self.tag_id, success_only)
|
||||
self.assertEqual('notification already exists', str(cm.exception))
|
||||
|
||||
self.exports.getLoggedInUser.assert_called_once()
|
||||
self.exports.hasPerm.asssert_called_once_with('admin')
|
||||
self.get_package_id.assert_called_once_with(self.package_id, strict=True)
|
||||
self.get_tag_id.assert_called_once_with(self.tag_id, strict=True)
|
||||
self.get_build_notifications.assert_called_once_with(self.user_id)
|
||||
self.assertEqual(len(self.inserts), 0)
|
||||
self.assertEqual(len(self.updates), 0)
|
||||
68
tests/test_hub/test_win_build.py
Normal file
68
tests/test_hub/test_win_build.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestWinBuild(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.assert_policy = mock.patch('kojihub.assert_policy').start()
|
||||
self.get_build_target = mock.patch('kojihub.get_build_target').start()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.vm = 'test-vm'
|
||||
self.url = 'https://test-url.com'
|
||||
self.target = 'test-target'
|
||||
self.targetinfo = {'build_tag': 444,
|
||||
'build_tag_name': 'test-tag',
|
||||
'dest_tag': 445,
|
||||
'dest_tag_name': 'dest-test-tag',
|
||||
'id': 1,
|
||||
'name': self.target}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_win_not_supported(self):
|
||||
self.context.opts.get.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.winBuild(self.vm, self.url, self.target)
|
||||
self.assertEqual("Windows support not enabled", str(cm.exception))
|
||||
|
||||
def test_vm_wrong_type(self):
|
||||
vm = ['test-vm']
|
||||
self.context.opts.get.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.winBuild(vm, self.url, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{vm}': {type(vm)}", str(cm.exception))
|
||||
|
||||
def test_url_wrong_type(self):
|
||||
url = ['test-url']
|
||||
self.context.opts.get.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.winBuild(self.vm, url, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{url}': {type(url)}", str(cm.exception))
|
||||
|
||||
def test_priority_without_admin(self):
|
||||
priority = -10
|
||||
self.context.opts.get.return_value = True
|
||||
self.get_build_target.return_value = self.targetinfo
|
||||
self.assert_policy.return_value = True
|
||||
self.context.session.hasPerm.return_value = False
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.winBuild(self.vm, self.url, self.target, priority=priority)
|
||||
self.assertEqual("only admins may create high-priority tasks", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
self.context.opts.get.return_value = True
|
||||
self.get_build_target.return_value = self.targetinfo
|
||||
self.assert_policy.return_value = True
|
||||
self.make_task.return_value = 123
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 1, 'name': 'vm'}
|
||||
self.exports.winBuild(self.vm, self.url, self.target, channel=1, priority=10)
|
||||
56
tests/test_hub/test_wrapper_rpm.py
Normal file
56
tests/test_hub/test_wrapper_rpm.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import unittest
|
||||
import koji
|
||||
import kojihub
|
||||
import mock
|
||||
|
||||
|
||||
class TestWrapperRPM(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.context = mock.patch('kojihub.context').start()
|
||||
self.exports = kojihub.RootExports()
|
||||
self.context.session.assertLogin = mock.MagicMock()
|
||||
self.context.session.hasPerm = mock.MagicMock()
|
||||
self.get_channel = mock.patch('kojihub.get_channel').start()
|
||||
self.exports.getBuild = mock.MagicMock()
|
||||
self.make_task = mock.patch('kojihub.make_task').start()
|
||||
self.list_rpms = mock.patch('kojihub.list_rpms').start()
|
||||
self.exports.getTag = mock.MagicMock()
|
||||
self.exports.getBuildTarget = mock.MagicMock()
|
||||
self.exports.getRepo = mock.MagicMock()
|
||||
self.build = 'testbuild-1-1.4'
|
||||
self.target = 'test-target'
|
||||
self.url = 'https://test-url.com'
|
||||
self.buildinfo = {'name': 'testbuild', 'version': '1', 'release': '1.4',
|
||||
'nvr': self.build, 'id': 123}
|
||||
self.targetinfo = {'build_tag': 444,
|
||||
'build_tag_name': 'test-tag',
|
||||
'dest_tag': 445,
|
||||
'dest_tag_name': 'dest-test-tag',
|
||||
'id': 1,
|
||||
'name': self.target}
|
||||
self.taginfo = {'id': 159, 'name': 'test-tag'}
|
||||
self.repoinfo = {'id': 753}
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_url_wrong_type(self):
|
||||
url = ['test-url']
|
||||
self.context.opts.get.return_value = True
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
self.exports.wrapperRPM(self.build, url, self.target)
|
||||
self.assertEqual(f"Invalid type for value '{url}': {type(url)}", str(cm.exception))
|
||||
|
||||
def test_channel_not_str(self):
|
||||
priority = 10
|
||||
self.context.opts.get.return_value = True
|
||||
self.exports.getBuild.return_value = self.buildinfo
|
||||
self.list_rpms.return_value = []
|
||||
self.exports.getBuildTarget.return_value = self.targetinfo
|
||||
self.exports.getRepo.return_value = self.taginfo
|
||||
self.exports.getRepo.return_value = self.repoinfo
|
||||
self.make_task.return_value = 123
|
||||
self.get_channel.return_value = {'comment': None, 'description': None, 'enabled': True,
|
||||
'id': 2, 'name': 'maven'}
|
||||
self.exports.wrapperRPM(self.build, self.url, self.target, priority=priority, channel=2)
|
||||
23
tests/test_hub/test_write_signed_rpm.py
Normal file
23
tests/test_hub/test_write_signed_rpm.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import unittest
|
||||
import mock
|
||||
|
||||
import koji
|
||||
import kojihub
|
||||
|
||||
|
||||
class TestWriteSignedRPM(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.get_rpm = mock.patch('kojihub.get_rpm').start()
|
||||
|
||||
def tearDown(self):
|
||||
mock.patch.stopall()
|
||||
|
||||
def test_write_signed_rpm_not_internal_rpm(self):
|
||||
sigkey = 'test-sigkey'
|
||||
rpm_id = 1
|
||||
rpminfo = {'external_repo_id': 1, 'external_repo_name': 'test-external-repo'}
|
||||
self.get_rpm.return_value = rpminfo
|
||||
with self.assertRaises(koji.GenericError) as cm:
|
||||
kojihub.write_signed_rpm(rpm_id, sigkey)
|
||||
self.assertEqual(f"Not an internal rpm: {rpm_id} (from {rpminfo['external_repo_name']})",
|
||||
str(cm.exception))
|
||||
|
|
@ -48,8 +48,8 @@ class TestRunrootHub(unittest.TestCase):
|
|||
context.handlers = mock.MagicMock()
|
||||
context.handlers.call = mock.MagicMock()
|
||||
context.handlers.call.side_effect = [
|
||||
{'id': 2, 'name': 'runroot'}, # getChannel
|
||||
[ # listHosts
|
||||
{'id': 2, 'name': 'runroot'}, # getChannel
|
||||
[ # listHosts
|
||||
{
|
||||
'arches': 'i386 x86_64',
|
||||
'capacity': 20.0,
|
||||
|
|
@ -105,8 +105,8 @@ class TestRunrootHub(unittest.TestCase):
|
|||
context.handlers = mock.MagicMock()
|
||||
context.handlers.call = mock.MagicMock()
|
||||
context.handlers.call.side_effect = [
|
||||
{'id': 2, 'name': 'runroot'}, # getChannel
|
||||
[ # listHosts
|
||||
{'id': 2, 'name': 'runroot'}, # getChannel
|
||||
[ # listHosts
|
||||
{
|
||||
'arches': 'i386 x86_64',
|
||||
'capacity': 20.0,
|
||||
|
|
@ -147,3 +147,31 @@ class TestRunrootHub(unittest.TestCase):
|
|||
mock.call('listHosts', channelID=2, enabled=True),
|
||||
])
|
||||
make_task.assert_not_called()
|
||||
|
||||
@mock.patch('kojihub.get_channel')
|
||||
@mock.patch('kojihub.get_tag')
|
||||
@mock.patch('kojihub.make_task')
|
||||
@mock.patch('runroot_hub.context')
|
||||
def test_non_exist_channel(self, context, make_task, get_tag, get_channel):
|
||||
context.session.assertPerm = mock.MagicMock()
|
||||
get_channel.side_effect = koji.GenericError
|
||||
with self.assertRaises(koji.GenericError):
|
||||
runroot_hub.runroot(tagInfo='some_tag', arch='x86_64', command='ls',
|
||||
channel='non-exist-channel')
|
||||
make_task.assert_not_called()
|
||||
get_tag.assert_not_called()
|
||||
|
||||
@mock.patch('kojihub.get_channel')
|
||||
@mock.patch('kojihub.get_tag')
|
||||
@mock.patch('kojihub.make_task')
|
||||
@mock.patch('runroot_hub.context')
|
||||
def test_commang_wrong_format(self, context, make_task, get_tag, get_channel):
|
||||
context.session.assertPerm = mock.MagicMock()
|
||||
command = ['ls']
|
||||
with self.assertRaises(koji.GenericError) as ex:
|
||||
runroot_hub.runroot(tagInfo='some_tag', arch='x86_64', command=command,
|
||||
channel='non-exist-channel')
|
||||
self.assertEqual(f"Invalid type for value '{command}': {type(command)}", str(ex.exception))
|
||||
make_task.assert_not_called()
|
||||
get_tag.assert_not_called()
|
||||
get_channel.assert_not_called()
|
||||
|
|
|
|||
23
util/koji-gc
23
util/koji-gc
|
|
@ -168,6 +168,8 @@ def get_options():
|
|||
# figure out actions
|
||||
actions = ('prune', 'trash', 'delete', 'salvage')
|
||||
if options.action:
|
||||
if not isinstance(options.action, str):
|
||||
raise koji.ParameterError('Invalid type of action: %s' % type(options.action))
|
||||
options.action = options.action.lower().replace(',', ' ').split()
|
||||
for x in options.action:
|
||||
if x not in actions:
|
||||
|
|
@ -177,6 +179,9 @@ def get_options():
|
|||
|
||||
# split patterns for unprotected keys
|
||||
if options.unprotected_keys:
|
||||
if not isinstance(options.unprotected_keys, str):
|
||||
raise koji.ParameterError('Invalid type of unprotected_keys: %s'
|
||||
% type(options.unprotected_keys))
|
||||
options.unprotected_key_patterns = options.unprotected_keys.replace(',', ' ').split()
|
||||
else:
|
||||
options.unprotected_key_patterns = []
|
||||
|
|
@ -250,10 +255,15 @@ def check_tag(name):
|
|||
Returns True if we should process the tag, False otherwise
|
||||
"""
|
||||
if options.ignore_tags:
|
||||
if not isinstance(options.ignore_tags, list):
|
||||
raise koji.ParameterError('Invalid type of ignore_tags: %s'
|
||||
% type(options.ignore_tags))
|
||||
for pattern in options.ignore_tags:
|
||||
if fnmatch.fnmatch(name, pattern):
|
||||
return False
|
||||
if options.tag_filter:
|
||||
if not isinstance(options.tag_filter, list):
|
||||
raise koji.ParameterError('Invalid type of tag_filter: %s' % type(options.tag_filter))
|
||||
for pattern in options.tag_filter:
|
||||
if fnmatch.fnmatch(name, pattern):
|
||||
return True
|
||||
|
|
@ -270,6 +280,8 @@ def check_package(name):
|
|||
Returns True if we should process the package, False otherwise
|
||||
"""
|
||||
if options.pkg_filter:
|
||||
if not isinstance(options.pkg_filter, list):
|
||||
raise koji.ParameterError('Invalid type of pkg_filter: %s' % type(options.pkg_filter))
|
||||
for pattern in options.pkg_filter:
|
||||
if fnmatch.fnmatch(name, pattern):
|
||||
return True
|
||||
|
|
@ -417,13 +429,21 @@ Build: %%(name)s-%%(version)s-%%(release)s
|
|||
msg['Subject'] = "1 build marked for deletion"
|
||||
else:
|
||||
msg['Subject'] = "%i builds marked for deletion" % len(builds)
|
||||
if not isinstance(options.from_addr, str):
|
||||
raise koji.ParameterError('Invalid type of from_addr: %s' % type(options.from_addr))
|
||||
msg['From'] = options.from_addr
|
||||
if not isinstance(options.email_domain, str):
|
||||
raise koji.ParameterError('Invalid type of email_domain: %s' % type(options.email_domain))
|
||||
msg['To'] = "%s@%s" % (owner_name, options.email_domain) # XXX!
|
||||
emails = [msg['To']]
|
||||
if options.cc_addr:
|
||||
if not isinstance(options.cc_addr, str):
|
||||
raise koji.ParameterError('Invalid type of cc_addr: %s' % type(options.cc_addr))
|
||||
msg['Cc'] = ','.join(options.cc_addr)
|
||||
emails += options.cc_addr
|
||||
if options.bcc_addr:
|
||||
if not isinstance(options.bcc_addr, str):
|
||||
raise koji.ParameterError('Invalid type of bcc_addr: %s' % type(options.bcc_addr))
|
||||
emails += options.bcc_addr
|
||||
msg['X-Koji-Builder'] = owner_name
|
||||
if options.test:
|
||||
|
|
@ -894,6 +914,9 @@ def handle_prune():
|
|||
bypass = False
|
||||
if taginfo['locked']:
|
||||
if options.bypass_locks:
|
||||
if not isinstance(options.bypass_locks, list):
|
||||
raise koji.ParameterError('Invalid type of bypass_locks: %s'
|
||||
% type(options.bypass_locks))
|
||||
for pattern in options.bypass_locks:
|
||||
if fnmatch.fnmatch(tagname, pattern):
|
||||
bypass = True
|
||||
|
|
|
|||
|
|
@ -389,6 +389,8 @@ class TrackedBuild(object):
|
|||
log("Downloading %s" % url)
|
||||
# XXX - this is not really the right place for this
|
||||
resp = request_with_retry().get(url, stream=True)
|
||||
if not isinstance(options.workpath, str):
|
||||
raise koji.ParameterError('Invalid type of workpath: %s' % type(options.workpath))
|
||||
fn = "%s/%s.src.rpm" % (options.workpath, self.nvr)
|
||||
koji.ensuredir(os.path.dirname(fn))
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -141,6 +141,11 @@ def activate_session(session):
|
|||
elif options.keytab and options.principal:
|
||||
try:
|
||||
if options.keytab and options.principal:
|
||||
if not isinstance(options.keytab, str):
|
||||
raise koji.ParameterError('Invalid type of keytab: %s' % type(options.keytab))
|
||||
if not isinstance(options.principal, str):
|
||||
raise koji.ParameterError('Invalid type of principal: %s'
|
||||
% type(options.principal))
|
||||
session.gssapi_login(
|
||||
principal=options.principal,
|
||||
keytab=options.keytab,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue