Merge "Refactor functional tests"
This commit is contained in:
commit
290caff95f
|
@ -41,7 +41,10 @@ from six.moves import range
|
|||
import six.moves.urllib.parse as urlparse
|
||||
import testtools
|
||||
|
||||
from glare.api.v1 import resource
|
||||
from glare.api.v1 import router
|
||||
from glare.common import utils
|
||||
from glare.common import wsgi
|
||||
from glare.db.sqlalchemy import api as db_api
|
||||
from glare import tests as glare_tests
|
||||
from glare.tests import utils as test_utils
|
||||
|
@ -323,7 +326,7 @@ pipeline = faultwrapper versionnegotiation context glarev1api
|
|||
|
||||
[app:glarev1api]
|
||||
paste.app_factory =
|
||||
glare.tests.functional.test_artifacts:TestRouter.factory
|
||||
glare.tests.functional:TestRouter.factory
|
||||
|
||||
[filter:faultwrapper]
|
||||
paste.filter_factory =
|
||||
|
@ -631,3 +634,11 @@ class FunctionalTest(test_utils.BaseTestCase):
|
|||
for log in logs:
|
||||
if os.path.exists(log):
|
||||
testtools.content.attach_file(self, log)
|
||||
|
||||
|
||||
class TestRouter(router.API):
|
||||
def _get_artifacts_resource(self):
|
||||
deserializer = resource.RequestDeserializer()
|
||||
serializer = resource.ResponseSerializer()
|
||||
controller = resource.ArtifactsController()
|
||||
return wsgi.Resource(controller, deserializer, serializer)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,599 @@
|
|||
# Copyright 2016 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import jsonschema
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
import requests
|
||||
|
||||
from glare.tests import functional
|
||||
|
||||
|
||||
class TestArtifact(functional.FunctionalTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestArtifact, self).setUp()
|
||||
self.glare_server.deployment_flavor = 'noauth'
|
||||
self.glare_server.enabled_artifact_types = 'sample_artifact'
|
||||
self.glare_server.custom_artifact_types_modules = (
|
||||
'glare.tests.functional.sample_artifact')
|
||||
self.start_servers(**self.__dict__.copy())
|
||||
|
||||
def tearDown(self):
|
||||
self.stop_servers()
|
||||
self._reset_database(self.glare_server.sql_connection)
|
||||
super(TestArtifact, self).tearDown()
|
||||
|
||||
def _url(self, path):
|
||||
return 'http://127.0.0.1:%d%s' % (self.glare_port, path)
|
||||
|
||||
def _check_artifact_method(self, url, status=200):
|
||||
headers = {
|
||||
'X-Identity-Status': 'Confirmed',
|
||||
}
|
||||
response = requests.get(self._url(url), headers=headers)
|
||||
self.assertEqual(status, response.status_code, response.text)
|
||||
if status >= 400:
|
||||
return response.text
|
||||
if ("application/json" in response.headers["content-type"] or
|
||||
"application/schema+json" in response.headers["content-type"]):
|
||||
return jsonutils.loads(response.text)
|
||||
return response.text
|
||||
|
||||
def get(self, url, status=200, headers=None):
|
||||
return self._check_artifact_method(url, status=status)
|
||||
|
||||
def test_schemas(self):
|
||||
schema_sample_artifact = {
|
||||
u'sample_artifact': {
|
||||
u'name': u'sample_artifact',
|
||||
u'properties': {u'activated_at': {
|
||||
u'description': u'Datetime when artifact has became '
|
||||
u'active.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'format': u'date-time',
|
||||
u'readOnly': True,
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [
|
||||
u'string',
|
||||
u'null']},
|
||||
u'blob': {u'additionalProperties': False,
|
||||
u'description': u'I am Blob',
|
||||
u'filter_ops': [],
|
||||
u'mutable': True,
|
||||
u'properties': {u'checksum': {
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'content_type': {
|
||||
u'type': u'string'},
|
||||
u'external': {
|
||||
u'type': u'boolean'},
|
||||
u'size': {u'type': [
|
||||
u'number',
|
||||
u'null']},
|
||||
u'status': {
|
||||
u'enum': [
|
||||
u'saving',
|
||||
u'active',
|
||||
u'pending_delete'],
|
||||
u'type': u'string'}},
|
||||
u'required': [u'size',
|
||||
u'checksum',
|
||||
u'external',
|
||||
u'status',
|
||||
u'content_type'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'bool1': {u'default': False,
|
||||
u'filter_ops': [u'eq'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'bool2': {u'default': False,
|
||||
u'filter_ops': [u'eq'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'created_at': {
|
||||
u'description': u'Datetime when artifact has been '
|
||||
u'created.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'format': u'date-time',
|
||||
u'readOnly': True,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'dependency1': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'dependency2': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'description': {u'default': u'',
|
||||
u'description': u'Artifact description.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 4096,
|
||||
u'mutable': True,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'dict_of_blobs': {
|
||||
u'additionalProperties': {
|
||||
u'additionalProperties': False,
|
||||
u'properties': {u'checksum': {
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'content_type': {
|
||||
u'type': u'string'},
|
||||
u'external': {
|
||||
u'type': u'boolean'},
|
||||
u'size': {
|
||||
u'type': [
|
||||
u'number',
|
||||
u'null']},
|
||||
u'status': {
|
||||
u'enum': [
|
||||
u'saving',
|
||||
u'active',
|
||||
u'pending_delete'],
|
||||
u'type': u'string'}},
|
||||
u'required': [u'size',
|
||||
u'checksum',
|
||||
u'external',
|
||||
u'status',
|
||||
u'content_type'],
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'default': {},
|
||||
u'filter_ops': [],
|
||||
u'maxProperties': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'dict_of_int': {
|
||||
u'additionalProperties': {
|
||||
u'type': u'string'},
|
||||
u'default': {},
|
||||
u'filter_ops': [u'eq'],
|
||||
u'maxProperties': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'dict_of_str': {
|
||||
u'additionalProperties': {
|
||||
u'type': u'string'},
|
||||
u'default': {},
|
||||
u'filter_ops': [u'eq'],
|
||||
u'maxProperties': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'dict_validators': {
|
||||
u'additionalProperties': False,
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxProperties': 3,
|
||||
u'properties': {
|
||||
u'abc': {u'type': [u'string',
|
||||
u'null']},
|
||||
u'def': {u'type': [u'string',
|
||||
u'null']},
|
||||
u'ghi': {u'type': [u'string',
|
||||
u'null']},
|
||||
u'jkl': {u'type': [u'string',
|
||||
u'null']}},
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'float1': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [u'number',
|
||||
u'null']},
|
||||
u'float2': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [u'number',
|
||||
u'null']},
|
||||
u'icon': {u'additionalProperties': False,
|
||||
u'description': u'Artifact icon.',
|
||||
u'filter_ops': [],
|
||||
u'properties': {u'checksum': {
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'content_type': {
|
||||
u'type': u'string'},
|
||||
u'external': {
|
||||
u'type': u'boolean'},
|
||||
u'size': {
|
||||
u'type': [
|
||||
u'number',
|
||||
u'null']},
|
||||
u'status': {
|
||||
u'enum': [
|
||||
u'saving',
|
||||
u'active',
|
||||
u'pending_delete'],
|
||||
u'type': u'string'}},
|
||||
u'required': [u'size',
|
||||
u'checksum',
|
||||
u'external',
|
||||
u'status',
|
||||
u'content_type'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'id': {u'description': u'Artifact UUID.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'pattern': u'^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-'
|
||||
u'([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-'
|
||||
u'([0-9a-fA-F]){12}$',
|
||||
u'readOnly': True,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'int1': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [u'integer',
|
||||
u'null']},
|
||||
u'int2': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [u'integer',
|
||||
u'null']},
|
||||
u'int_validators': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'maximum': 20,
|
||||
u'minumum': 10,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'integer',
|
||||
u'null']},
|
||||
u'license': {
|
||||
u'description': u'Artifact license type.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'license_url': {
|
||||
u'description': u'URL to artifact license.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'list_of_int': {u'default': [],
|
||||
u'filter_ops': [u'eq'],
|
||||
u'items': {
|
||||
u'type': u'string'},
|
||||
u'maxItems': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'array',
|
||||
u'null']},
|
||||
u'list_of_str': {u'default': [],
|
||||
u'filter_ops': [u'eq'],
|
||||
u'items': {
|
||||
u'type': u'string'},
|
||||
u'maxItems': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'array',
|
||||
u'null']},
|
||||
u'list_validators': {u'default': [],
|
||||
u'filter_ops': [
|
||||
u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'items': {
|
||||
u'type': u'string'},
|
||||
u'maxItems': 3,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'array',
|
||||
u'null'],
|
||||
u'unique': True},
|
||||
u'metadata': {u'additionalProperties': {
|
||||
u'type': u'string'},
|
||||
u'default': {},
|
||||
u'description': u'Key-value dict with useful '
|
||||
u'information about an artifact.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq'],
|
||||
u'maxProperties': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'name': {u'description': u'Artifact Name.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'owner': {
|
||||
u'description': u'ID of user/tenant who uploaded '
|
||||
u'artifact.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'readOnly': True,
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'provided_by': {
|
||||
u'additionalProperties': False,
|
||||
u'description': u'Info about artifact authors.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxProperties': 255,
|
||||
u'properties': {
|
||||
u'company': {u'type': u'string'},
|
||||
u'href': {u'type': u'string'},
|
||||
u'name': {u'type': u'string'}},
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'release': {
|
||||
u'default': [],
|
||||
u'description': u'Target Openstack release for '
|
||||
u'artifact. It is usually the same '
|
||||
u'when artifact was uploaded.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'items': {u'type': u'string'},
|
||||
u'maxItems': 255,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'array',
|
||||
u'null'],
|
||||
u'unique': True},
|
||||
u'small_blob': {u'additionalProperties': False,
|
||||
u'filter_ops': [],
|
||||
u'mutable': True,
|
||||
u'properties': {u'checksum': {
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'content_type': {
|
||||
u'type': u'string'},
|
||||
u'external': {
|
||||
u'type': u'boolean'},
|
||||
u'size': {
|
||||
u'type': [
|
||||
u'number',
|
||||
u'null']},
|
||||
u'status': {
|
||||
u'enum': [
|
||||
u'saving',
|
||||
u'active',
|
||||
u'pending_delete'],
|
||||
u'type': u'string'}},
|
||||
u'required': [u'size',
|
||||
u'checksum',
|
||||
u'external',
|
||||
u'status',
|
||||
u'content_type'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'status': {u'default': u'drafted',
|
||||
u'description': u'Artifact status.',
|
||||
u'enum': [u'drafted',
|
||||
u'active',
|
||||
u'deactivated',
|
||||
u'deleted'],
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'str1': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'maxLength': 255,
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'string_mutable': {u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'maxLength': 255,
|
||||
u'mutable': True,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'string_required': {
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'maxLength': 255,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'string_validators': {
|
||||
u'enum': [u'aa',
|
||||
u'bb',
|
||||
u'ccccccccccc',
|
||||
None],
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'maxLength': 10,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'supported_by': {
|
||||
u'additionalProperties': {
|
||||
u'type': u'string'},
|
||||
u'description': u'Info about persons who responsible '
|
||||
u'for artifact support',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxProperties': 255,
|
||||
u'required': [u'name'],
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'system_attribute': {u'default': u'default',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'maxLength': 255,
|
||||
u'readOnly': True,
|
||||
u'sortable': True,
|
||||
u'type': [u'string',
|
||||
u'null']},
|
||||
u'tags': {u'default': [],
|
||||
u'description': u'List of tags added to '
|
||||
u'Artifact.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'items': {u'type': u'string'},
|
||||
u'maxItems': 255,
|
||||
u'mutable': True,
|
||||
u'required_on_activate': False,
|
||||
u'type': [u'array',
|
||||
u'null']},
|
||||
u'updated_at': {
|
||||
u'description': u'Datetime when artifact has been '
|
||||
u'updated last time.',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'format': u'date-time',
|
||||
u'readOnly': True,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'version': {u'default': u'0.0.0',
|
||||
u'description': u'Artifact version(semver).',
|
||||
u'filter_ops': [u'eq',
|
||||
u'neq',
|
||||
u'in',
|
||||
u'gt',
|
||||
u'gte',
|
||||
u'lt',
|
||||
u'lte'],
|
||||
u'pattern': u'/^([0-9]+)\\.([0-9]+)\\.'
|
||||
u'([0-9]+)(?:-([0-9A-Za-z-]+'
|
||||
u'(?:\\.[0-9A-Za-z-]+)*))?'
|
||||
u'(?:\\+[0-9A-Za-z-]+)?$/',
|
||||
u'required_on_activate': False,
|
||||
u'sortable': True,
|
||||
u'type': u'string'},
|
||||
u'visibility': {
|
||||
u'default': u'private',
|
||||
u'description': u'Artifact visibility that defines if '
|
||||
u'artifact can be available to other '
|
||||
u'users.',
|
||||
u'filter_ops': [u'eq'],
|
||||
u'maxLength': 255,
|
||||
u'sortable': True,
|
||||
u'type': u'string'}},
|
||||
u'required': [u'name'],
|
||||
u'title': u'Artifact type sample_artifact of version 1.0',
|
||||
u'type': u'object'}}
|
||||
|
||||
# Get list schemas of artifacts
|
||||
result = self.get(url='/schemas')
|
||||
self.assertEqual({u'schemas': schema_sample_artifact}, result)
|
||||
|
||||
# Get schema of sample_artifact
|
||||
result = self.get(url='/schemas/sample_artifact')
|
||||
self.assertEqual({u'schemas': schema_sample_artifact}, result)
|
||||
|
||||
# Validation of schemas
|
||||
result = self.get(url='/schemas')['schemas']
|
||||
for artifact_type, schema in result.items():
|
||||
jsonschema.Draft4Validator.check_schema(schema)
|
Loading…
Reference in New Issue