Merge "Add API Tests for flavors"

This commit is contained in:
Jenkins 2014-10-20 14:50:38 +00:00 committed by Gerrit Code Review
commit 4cd92e850b
11 changed files with 425 additions and 46 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.py[cod]
.DS_Store
# C extensions
*.so
@ -38,4 +39,4 @@ tests/logs
.project
.pydevproject
venv
docker_rsa*
docker_rsa*

View File

View File

@ -0,0 +1,45 @@
{
"all_fields":
{"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "http://www.chinacache.com",
"rel": "provider_url"}]}]},
"non_ASCII_flavor":
{"flavor_id": "երանգ",
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "Armenia",
"links": [{"href": "http://www.armenia.com",
"rel": "provider_url"}]}]},
"non_ASCII_provider":
{
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "नेपाललिपि",
"links": [{"href": "http://العربية.com",
"rel": "provider_url"}]}]},
"multiple_providers":
{
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "http://www.chinacache.com",
"rel": "provider_url"}]},
{"provider": "OUIIICache",
"links": [{"href": "http://111.222.333.444",
"rel": "provider_url"}]}
]}
}

View File

@ -0,0 +1,131 @@
{
"empty_provider_list": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": []},
"no_provider_url": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "fastly",
"links": [
{"href": "http://fastly.com", "rel": "no_provider_url"}]}]
},
"no_rel_field": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "http://www.chinacache.com"}]},
{"provider": "maxCDN",
"links": [{"href": "http://www.maxcdn.com/", "rel": "provider_url"}]}]
},
"empty_string_rel_field": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "http://www.chinacache.com", "rel": ""}]},
{"provider": "maxCDN",
"links": [{"href": "http://www.maxcdn.com/", "rel": "provider_url"}]}]
},
"empty_href": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "", "rel": "provider_url"}]}]},
"invalid_href": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "watermelon", "rel": "provider_url"}]}]},
"empty_limits": {
"limits": [],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "watermelon", "rel": "provider_url"}]}]},
"missing_limits_origins": {
"limits": [
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"missing_limits_domains": {
"limits": [
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"missing_limits_caching": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"empty_limits_origins": {
"limits": [
{"origins": {}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"empty_limits_domains": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"empty_limits_caching": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"invalid_limits_origins": {
"limits": [
{"origins": {"min": 1, "max": -5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"invalid_limits_domains": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 100000000000000000000000000000000000000, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": 300}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]},
"invalid_limits_caching": {
"limits": [
{"origins": {"min": 1, "max": 5}},
{"domains": {"min": 1, "max": 5}},
{"caching": {"min": 3600, "max": 604800, "incr": "string"}}],
"provider_list": [
{"provider": "ChinaCache",
"links": [{"href": "www.watermelon.com", "rel": "provider_url"}]}]}
}

View File

@ -0,0 +1,112 @@
# Copyright (c) 2014 Rackspace, Inc.
#
# 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 uuid
import ddt
from tests.api import base
from tests.api.utils.schema import flavors
@ddt.ddt
class TestCreateFlavors(base.TestBase):
"""Tests for Flavors."""
def setUp(self):
super(TestCreateFlavors, self).setUp()
self.flavor_id = str(uuid.uuid1())
@ddt.file_data('data_create_flavor.json')
def test_create_flavor(self, test_data):
provider_list = test_data['provider_list']
limits = test_data['limits']
if 'flavor_id' in test_data:
flavor_id = test_data['flavor_id']
else:
flavor_id = self.flavor_id
resp = self.client.create_flavor(flavor_id=flavor_id,
provider_list=provider_list,
limits=limits)
self.assertEqual(resp.status_code, 204)
# Get on Created Flavor
location = resp.headers['location']
resp = self.client.get_flavor(flavor_location=location)
self.assertEqual(resp.status_code, 200)
response_body = resp.json()
self.assertSchema(response_body, flavors.get_flavor)
self.assertEqual(response_body['providers'], provider_list)
@ddt.file_data('data_create_flavor_negative.json')
def test_create_flavor_negative_tests(self, test_data):
provider_list = test_data['provider_list']
limits = test_data['limits']
if 'flavor_id' in test_data:
flavor_id = test_data['flavor_id']
else:
flavor_id = self.flavor_id
resp = self.client.create_flavor(flavor_id=flavor_id,
provider_list=provider_list,
limits=limits)
self.assertEqual(resp.status_code, 400)
def tearDown(self):
self.client.delete_flavor(flavor_id=self.flavor_id)
super(TestCreateFlavors, self).tearDown()
@ddt.ddt
class TestFlavorActions(base.TestBase):
"""Tests for GET & DELETE Flavors."""
def setUp(self):
super(TestFlavorActions, self).setUp()
self.flavor_id = str(uuid.uuid1())
self.provider_list = [
{"provider": "ChinaCache",
"links": [{"href": "http://www.chinacache.com",
"rel": "provider_url"}]}]
self.client.create_flavor(flavor_id=self.flavor_id,
provider_list=self.provider_list)
def test_get_flavor(self):
resp = self.client.get_flavor(flavor_id=self.flavor_id)
self.assertEqual(resp.status_code, 200)
response_body = resp.json()
self.assertSchema(response_body, flavors.get_flavor)
self.assertEqual(response_body['providers'], self.provider_list)
def test_delete_flavor(self):
resp = self.client.delete_flavor(flavor_id=self.flavor_id)
self.assertEqual(resp.status_code, 204)
resp = self.client.get_flavor(flavor_id=self.flavor_id)
self.assertEqual(resp.status_code, 404)
def tearDown(self):
self.client.delete_flavor(flavor_id=self.flavor_id)
super(TestFlavorActions, self).tearDown()

View File

@ -22,7 +22,7 @@ import ddt
from tests.api import base
from tests.api import providers
from tests.api.utils.schema import response
from tests.api.utils.schema import services
@ddt.ddt
@ -53,7 +53,7 @@ class TestCreateService(providers.TestProviderBase):
self.assertEqual(resp.status_code, 200)
body = resp.json()
self.assertSchema(body, response.get_service)
self.assertSchema(body, services.get_service)
self.assertEqual(body['domains'], domain_list)
self.assertEqual(body['origins'], origin_list)
@ -142,7 +142,7 @@ class TestListServices(base.TestBase):
self.assertEqual(resp.status_code, 200)
body = resp.json()
self.assertSchema(body, response.list_services)
self.assertSchema(body, services.list_services)
def test_list_services_no_service(self):
resp = self.client.list_services()
@ -162,7 +162,7 @@ class TestListServices(base.TestBase):
body = resp.json()
self.assertEqual(len(body['services']), limit)
self.assertSchema(body, response.list_services)
self.assertSchema(body, services.list_services)
def test_list_services_multiple_page(self):
self.skipTest('Exceeds max number of services allowed by Fastly')
@ -173,7 +173,7 @@ class TestListServices(base.TestBase):
body = resp.json()
# TODO(malini): remove hard coded value with configurable value
self.assertEqual(len(body['services']), 10)
self.assertSchema(body, response.list_services)
self.assertSchema(body, services.list_services)
@ddt.data(-1, -10000000000, 0, 10000000, 'invalid', '学校', '')
def test_list_services_invalid_limits(self, limit):
@ -229,7 +229,7 @@ class TestServiceActions(base.TestBase):
self.assertEqual(resp.status_code, 200)
body = resp.json()
self.assertSchema(body, response.get_service)
self.assertSchema(body, services.get_service)
self.assertEqual(body['domains'], self.domain_list)
self.assertEqual(body['origins'], self.origin_list)
# TODO(malini): uncomment below after caching list is implemented.

View File

@ -31,7 +31,7 @@ class AuthClient(client.HTTPClient):
self.default_headers['Accept'] = 'application/json'
def authenticate_user(self, auth_url, user_name, api_key):
"""Get Auth Token using api_key
"""Get Auth Token & Project ID using api_key
TODO (malini-kamalambal): Support getting token with password (or)
api key.
@ -87,8 +87,7 @@ class PoppyClient(client.AutoMarshallingHTTPClient):
origin_list=origin_list,
caching_list=caching_list,
flavorRef=flavorRef)
return self.request('POST', url,
request_entity=request_object,
return self.request('POST', url, request_entity=request_object,
requestslib_kwargs=requestslib_kwargs)
def get_service(self, service_name):
@ -147,3 +146,50 @@ class PoppyClient(client.AutoMarshallingHTTPClient):
url = '{0}/v1.0/ping'.format(self.url)
return self.request('GET', url)
def create_flavor(self, flavor_id=None, provider_list=None, limits=None,
requestslib_kwargs=None):
"""Create flavor
:return: Response Object containing response code 204 and header with
Location
PUT
flavors/{flavor_id}
"""
url = '{0}/v1.0/flavors'.format(self.url)
request_object = requests.CreateFlavor(
flavor_id=flavor_id,
provider_list=provider_list,
limits=limits)
return self.request('POST', url,
request_entity=request_object,
requestslib_kwargs=requestslib_kwargs)
def get_flavor(self, flavor_location=None, flavor_id=None):
"""Get Flavor
:return: Response Object containing response code 200 and body with
details of flavor
GET
flavors/{flavor_id}
"""
if flavor_location:
url = flavor_location
else:
url = '{0}/v1.0/flavors/{1}'.format(self.url, flavor_id)
return self.request('GET', url)
def delete_flavor(self, flavor_location=None, flavor_id=None):
"""Delete Flavor
:return: Response Object containing response code 204
DELETE
flavors/{flavor_id}
"""
if flavor_location:
url = flavor_location
else:
url = '{0}/v1.0/flavors/{1}'.format(self.url, flavor_id)
return self.request('DELETE', url)

View File

@ -38,3 +38,20 @@ class CreateService(base.AutoMarshallingModel):
"caching": self.caching_list,
"flavorRef": self.flavorRef}
return json.dumps(create_service_request)
class CreateFlavor(base.AutoMarshallingModel):
"""Marshalling for Create Flavor requests."""
def __init__(self, flavor_id=None, provider_list=None, limits=None):
super(CreateFlavor, self).__init__()
self.flavor_id = flavor_id
self.provider_list = provider_list
self.limits = limits
def _obj_to_json(self):
create_flavor_request = {"id": self.flavor_id,
"providers": self.provider_list,
"limits": self.limits}
return json.dumps(create_flavor_request)

View File

@ -1,35 +0,0 @@
# Copyright (c) 2014 Rackspace, Inc.
#
# 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 json
from cafe.engine.models import base
class CreateService(base.AutoMarshallingModel):
"""Marshalling for Create Service requests."""
def __init__(self, domain_list=None, origin_list=None, caching_list=None):
super(CreateService, self).__init__()
self.domain_list = domain_list or []
self.origin_list = origin_list or []
self.caching_list = caching_list or []
def _obj_to_json(self):
create_service_request = {"domains": self.domain_list,
"origins": self.origin_list,
"caching": self.caching_list}
return json.dumps(create_service_request)

View File

@ -0,0 +1,60 @@
# Copyright (c) 2014 Rackspace, Inc.
#
# 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.
# Definition for components of Get Flavor API Schema
provider_link = {'type': 'object',
'properties': {
'href': {'type': 'string', 'format': 'uri'},
'rel': {'type': 'string', 'enum': ['provider_url']}},
'required': ['href', 'rel'],
'additionalProperties': False}
provider = {'type': 'object',
'properties': {'provider': {'type': 'string'},
'links': {'type': 'array',
'items': provider_link,
'minItems': 1,
'maxItems': 1}},
'required': ['provider', 'links'],
'additionalProperties': False}
link = {'type': 'object',
'properties': {
'href': {'type': 'string',
'pattern':
'^(https?)(:/{1,3})([a-z0-9\.\-:]{1,400})'
'/v1\.0/flavors/[a-zA-Z0-9_-]{1,64}$'},
'rel': {'type': 'string', 'enum': ['self']}},
'required': ['href', 'rel'],
'additionalProperties': False}
# Response Schema definition for Get Flavor API
get_flavor = {
'type': 'object',
'properties': {
'id': {'type': 'string'},
'providers': {'type': 'array',
'items': provider,
'minItems': 1
},
'links': {'type': 'array',
'items': link,
'minItems': 1,
'maxItems': 1}
},
'required': ['id', 'providers', 'links'],
'additionalProperties': False
}

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Definition for components of Create Service API Schema
domain = {
'type': 'object',
'properties': {
@ -104,4 +105,5 @@ list_services = {
'type': 'array',
'items': get_service}},
'required': ['links', 'services'],
'additionalProperties': False}
'additionalProperties': False
}