initial import for Open Source 🎉
This commit is contained in:
parent
1898c361f3
commit
9c0dd3b722
2048 changed files with 218743 additions and 0 deletions
0
endpoints/test/__init__.py
Normal file
0
endpoints/test/__init__.py
Normal file
80
endpoints/test/shared.py
Normal file
80
endpoints/test/shared.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
import datetime
|
||||
import json
|
||||
import base64
|
||||
|
||||
from contextlib import contextmanager
|
||||
from data import model
|
||||
|
||||
from flask import g
|
||||
from flask_principal import Identity
|
||||
|
||||
CSRF_TOKEN_KEY = '_csrf_token'
|
||||
|
||||
@contextmanager
|
||||
def client_with_identity(auth_username, client):
|
||||
with client.session_transaction() as sess:
|
||||
if auth_username and auth_username is not None:
|
||||
loaded = model.user.get_user(auth_username)
|
||||
sess['user_id'] = loaded.uuid
|
||||
sess['login_time'] = datetime.datetime.now()
|
||||
else:
|
||||
sess['user_id'] = 'anonymous'
|
||||
|
||||
yield client
|
||||
|
||||
with client.session_transaction() as sess:
|
||||
sess['user_id'] = None
|
||||
sess['login_time'] = None
|
||||
sess[CSRF_TOKEN_KEY] = None
|
||||
|
||||
|
||||
@contextmanager
|
||||
def toggle_feature(name, enabled):
|
||||
""" Context manager which temporarily toggles a feature. """
|
||||
import features
|
||||
previous_value = getattr(features, name)
|
||||
setattr(features, name, enabled)
|
||||
yield
|
||||
setattr(features, name, previous_value)
|
||||
|
||||
|
||||
def add_csrf_param(client, params):
|
||||
""" Returns a params dict with the CSRF parameter added. """
|
||||
params = params or {}
|
||||
|
||||
with client.session_transaction() as sess:
|
||||
params[CSRF_TOKEN_KEY] = 'sometoken'
|
||||
sess[CSRF_TOKEN_KEY] = 'sometoken'
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def gen_basic_auth(username, password):
|
||||
""" Generates a basic auth header. """
|
||||
return 'Basic ' + base64.b64encode("%s:%s" % (username, password))
|
||||
|
||||
|
||||
def conduct_call(client, resource, url_for, method, params, body=None, expected_code=200,
|
||||
headers=None, raw_body=None):
|
||||
""" Conducts a call to a Flask endpoint. """
|
||||
params = add_csrf_param(client, params)
|
||||
|
||||
final_url = url_for(resource, **params)
|
||||
|
||||
headers = headers or {}
|
||||
headers.update({"Content-Type": "application/json"})
|
||||
|
||||
if body is not None:
|
||||
body = json.dumps(body)
|
||||
|
||||
if raw_body is not None:
|
||||
body = raw_body
|
||||
|
||||
# Required for anonymous calls to not exception.
|
||||
g.identity = Identity(None, 'none')
|
||||
|
||||
rv = client.open(final_url, method=method, data=body, headers=headers)
|
||||
msg = '%s %s: got %s expected: %s | %s' % (method, final_url, rv.status_code, expected_code,
|
||||
rv.data)
|
||||
assert rv.status_code == expected_code, msg
|
||||
return rv
|
27
endpoints/test/test_anon_checked.py
Normal file
27
endpoints/test/test_anon_checked.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import pytest
|
||||
|
||||
from app import app
|
||||
from endpoints.v1 import v1_bp
|
||||
from endpoints.v2 import v2_bp
|
||||
from endpoints.verbs import verbs
|
||||
|
||||
@pytest.mark.parametrize('blueprint', [
|
||||
v2_bp,
|
||||
v1_bp,
|
||||
verbs,
|
||||
])
|
||||
def test_verify_blueprint(blueprint):
|
||||
class Checker(object):
|
||||
def __init__(self):
|
||||
self.first_registration = True
|
||||
self.app = app
|
||||
|
||||
def add_url_rule(self, rule, endpoint, view_function, methods=None):
|
||||
result = ('__anon_protected' in dir(view_function) or
|
||||
'__anon_allowed' in dir(view_function))
|
||||
error_message = ('Missing anonymous access protection decorator on function ' +
|
||||
'%s under blueprint %s' % (endpoint, blueprint.name))
|
||||
assert result, error_message
|
||||
|
||||
for deferred_function in blueprint.deferred_functions:
|
||||
deferred_function(Checker())
|
97
endpoints/test/test_building.py
Normal file
97
endpoints/test/test_building.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
import pytest
|
||||
|
||||
from data import model
|
||||
from buildtrigger.triggerutil import raise_if_skipped_build, SkipRequestException
|
||||
from endpoints.building import (start_build, PreparedBuild, MaximumBuildsQueuedException,
|
||||
BuildTriggerDisabledException)
|
||||
|
||||
from test.fixtures import *
|
||||
|
||||
def test_maximum_builds(app):
|
||||
# Change the maximum number of builds to 1.
|
||||
user = model.user.create_user('foobar', 'password', 'foo@example.com')
|
||||
user.maximum_queued_builds_count = 1
|
||||
user.save()
|
||||
|
||||
repo = model.repository.create_repository('foobar', 'somerepo', user)
|
||||
|
||||
# Try to queue a build; should succeed.
|
||||
prepared_build = PreparedBuild()
|
||||
prepared_build.build_name = 'foo'
|
||||
prepared_build.is_manual = True
|
||||
prepared_build.dockerfile_id = 'foobar'
|
||||
prepared_build.archive_url = 'someurl'
|
||||
prepared_build.tags = ['latest']
|
||||
prepared_build.subdirectory = '/'
|
||||
prepared_build.context = '/'
|
||||
prepared_build.metadata = {}
|
||||
|
||||
start_build(repo, prepared_build)
|
||||
|
||||
# Try to queue a second build; should fail.
|
||||
with pytest.raises(MaximumBuildsQueuedException):
|
||||
start_build(repo, prepared_build)
|
||||
|
||||
|
||||
def test_start_build_disabled_trigger(app):
|
||||
trigger = model.build.list_build_triggers('devtable', 'building')[0]
|
||||
trigger.enabled = False
|
||||
trigger.save()
|
||||
|
||||
build = PreparedBuild(trigger=trigger)
|
||||
|
||||
with pytest.raises(BuildTriggerDisabledException):
|
||||
start_build(trigger.repository, build)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ref, expected_tags', [
|
||||
('ref/heads/somebranch', ['somebranch']),
|
||||
('ref/heads/master', ['master', 'latest']),
|
||||
|
||||
('ref/tags/somebranch', ['somebranch']),
|
||||
('ref/tags/master', ['master', 'latest']),
|
||||
|
||||
('ref/heads/slash/branch', ['slash_branch']),
|
||||
('ref/tags/slash/tag', ['slash_tag']),
|
||||
|
||||
('ref/heads/foobar#2', ['foobar_2']),
|
||||
])
|
||||
def test_tags_for_ref(ref, expected_tags):
|
||||
prepared = PreparedBuild()
|
||||
prepared.tags_from_ref(ref, default_branch='master')
|
||||
assert set(prepared._tags) == set(expected_tags)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('metadata, config', [
|
||||
({}, {}),
|
||||
pytest.param({'ref': 'ref/heads/master'}, {'branchtag_regex': 'nothing'}, id='branchtag regex'),
|
||||
pytest.param({
|
||||
'ref': 'ref/heads/master',
|
||||
'commit_info': {
|
||||
'message': '[skip build]',
|
||||
},
|
||||
}, {}, id='commit message'),
|
||||
])
|
||||
def test_skip(metadata, config):
|
||||
prepared = PreparedBuild()
|
||||
prepared.metadata = metadata
|
||||
config = config
|
||||
|
||||
with pytest.raises(SkipRequestException):
|
||||
raise_if_skipped_build(prepared, config)
|
||||
|
||||
|
||||
def test_does_not_skip():
|
||||
prepared = PreparedBuild()
|
||||
prepared.metadata = {
|
||||
'ref': 'ref/heads/master',
|
||||
'commit_info': {
|
||||
'message': 'some cool message',
|
||||
},
|
||||
}
|
||||
|
||||
config = {
|
||||
'branchtag_regex': '(master)|(heads/master)',
|
||||
}
|
||||
|
||||
raise_if_skipped_build(prepared, config)
|
29
endpoints/test/test_common.py
Normal file
29
endpoints/test/test_common.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import pytest
|
||||
|
||||
from endpoints.common import common_login
|
||||
from endpoints.csrf import QUAY_CSRF_UPDATED_HEADER_NAME
|
||||
|
||||
from test.fixtures import *
|
||||
from endpoints.common_models_pre_oci import pre_oci_model as model
|
||||
|
||||
@pytest.mark.parametrize('username, expect_success', [
|
||||
# Valid users.
|
||||
('devtable', True),
|
||||
('public', True),
|
||||
|
||||
# Org.
|
||||
('buynlarge', False),
|
||||
|
||||
# Robot.
|
||||
('devtable+dtrobot', False),
|
||||
|
||||
# Unverified user.
|
||||
('unverified', False),
|
||||
])
|
||||
def test_common_login(username, expect_success, app):
|
||||
uuid = model.get_namespace_uuid(username)
|
||||
with app.app_context():
|
||||
success, headers = common_login(uuid)
|
||||
assert success == expect_success
|
||||
if success:
|
||||
assert QUAY_CSRF_UPDATED_HEADER_NAME in headers
|
35
endpoints/test/test_decorators.py
Normal file
35
endpoints/test/test_decorators.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
from data import model
|
||||
from endpoints.api import api
|
||||
from endpoints.api.repository import Repository
|
||||
from endpoints.test.shared import conduct_call
|
||||
from test.fixtures import *
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user_agent, include_header, expected_code', [
|
||||
('curl/whatever', True, 200),
|
||||
('curl/whatever', False, 200),
|
||||
|
||||
('Mozilla/whatever', True, 200),
|
||||
('Mozilla/5.0', True, 200),
|
||||
('Mozilla/5.0 (Windows NT 5.1; Win64; x64)', False, 400),
|
||||
])
|
||||
def test_require_xhr_from_browser(user_agent, include_header, expected_code, app, client):
|
||||
# Create a public repo with a dot in its name.
|
||||
user = model.user.get_user('devtable')
|
||||
model.repository.create_repository('devtable', 'somerepo.bat', user, 'public')
|
||||
|
||||
# Retrieve the repository and ensure we either allow it through or fail, depending on the
|
||||
# user agent and header.
|
||||
params = {
|
||||
'repository': 'devtable/somerepo.bat'
|
||||
}
|
||||
|
||||
headers = {
|
||||
'User-Agent': user_agent,
|
||||
}
|
||||
|
||||
if include_header:
|
||||
headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||
|
||||
conduct_call(client, Repository, api.url_for, 'GET', params, headers=headers,
|
||||
expected_code=expected_code)
|
24
endpoints/test/test_webhooks.py
Normal file
24
endpoints/test/test_webhooks.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import base64
|
||||
import pytest
|
||||
|
||||
from flask import url_for
|
||||
|
||||
from data import model
|
||||
from endpoints.test.shared import conduct_call
|
||||
from test.fixtures import *
|
||||
|
||||
def test_start_build_disabled_trigger(app, client):
|
||||
trigger = model.build.list_build_triggers('devtable', 'building')[0]
|
||||
trigger.enabled = False
|
||||
trigger.save()
|
||||
|
||||
params = {
|
||||
'trigger_uuid': trigger.uuid,
|
||||
}
|
||||
|
||||
headers = {
|
||||
'Authorization': 'Basic ' + base64.b64encode('devtable:password'),
|
||||
}
|
||||
|
||||
conduct_call(client, 'webhooks.build_trigger_webhook', url_for, 'POST', params, None, 400,
|
||||
headers=headers)
|
Reference in a new issue