Add unit tests for api module
With this patch, distil coverage rate will be 71% Change-Id: Ie7136b509171d3c3636fa883f4308f5a61cf4bf0
This commit is contained in:
parent
ea4c07c57a
commit
0e183ccf0d
@ -5,6 +5,7 @@ omit =
|
|||||||
.tox/*
|
.tox/*
|
||||||
distil/tests/*
|
distil/tests/*
|
||||||
distil/api/web.py
|
distil/api/web.py
|
||||||
|
distil/api/helpers.py
|
||||||
distil/auth.py
|
distil/auth.py
|
||||||
distil/database.py
|
distil/database.py
|
||||||
distil/helpers.py
|
distil/helpers.py
|
||||||
|
@ -88,6 +88,7 @@ def usage_get(project_id, start_at, end_at):
|
|||||||
return IMPL.usage_get(project_id, start_at, end_at)
|
return IMPL.usage_get(project_id, start_at, end_at)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(lingxian): This method is not used anywhere but for testing purpose.
|
||||||
def usage_add(project_id, resource_id, samples, unit,
|
def usage_add(project_id, resource_id, samples, unit,
|
||||||
start_at, end_at):
|
start_at, end_at):
|
||||||
"""If a tenant exists does nothing,
|
"""If a tenant exists does nothing,
|
||||||
@ -101,9 +102,9 @@ def usages_add(project_id, resources, usage_entries, last_collect):
|
|||||||
return IMPL.usages_add(project_id, resources, usage_entries, last_collect)
|
return IMPL.usages_add(project_id, resources, usage_entries, last_collect)
|
||||||
|
|
||||||
|
|
||||||
def resource_add(project_id, resource_id, resource_type, rawdata, metadata):
|
# NOTE(lingxian): This method is not used anywhere but for testing purpose.
|
||||||
return IMPL.resource_add(project_id, resource_id, resource_type,
|
def resource_add(project_id, resource_id, resource_info):
|
||||||
rawdata, metadata)
|
return IMPL.resource_add(project_id, resource_id, resource_info)
|
||||||
|
|
||||||
|
|
||||||
def project_add(values, last_collect=None):
|
def project_add(values, last_collect=None):
|
||||||
|
@ -207,8 +207,10 @@ def usage_add(project_id, resource_id, samples, unit,
|
|||||||
volume=volume,
|
volume=volume,
|
||||||
unit=unit,
|
unit=unit,
|
||||||
resource_id=resource_id,
|
resource_id=resource_id,
|
||||||
project_id=project_id,
|
tenant_id=project_id,
|
||||||
start_at=start_at, end_at=end_at)
|
start=start_at,
|
||||||
|
end=end_at,
|
||||||
|
created=datetime.utcnow())
|
||||||
resource_ref.save(session=session)
|
resource_ref.save(session=session)
|
||||||
except sa.exc.InvalidRequestError as e:
|
except sa.exc.InvalidRequestError as e:
|
||||||
# FIXME(flwang): I assume there should be a DBDuplicateEntry error
|
# FIXME(flwang): I assume there should be a DBDuplicateEntry error
|
||||||
@ -271,11 +273,12 @@ def usages_add(project_id, resources, usage_entries, last_collect):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def resource_add(project_id, resource_id, resource_type, raw, metadata):
|
def resource_add(project_id, resource_id, resource_info):
|
||||||
session = get_session()
|
session = get_session()
|
||||||
metadata = _merge_resource_metadata({'type': resource_type}, raw, metadata)
|
resource_ref = Resource(
|
||||||
resource_ref = Resource(id=resource_id, project_id=project_id,
|
id=resource_id, tenant_id=project_id, info=json.dumps(resource_info),
|
||||||
resource_type=resource_type, meta_data=metadata)
|
created=datetime.utcnow()
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resource_ref.save(session=session)
|
resource_ref.save(session=session)
|
||||||
@ -299,28 +302,6 @@ def resource_get_by_ids(project_id, resource_ids):
|
|||||||
return query.all()
|
return query.all()
|
||||||
|
|
||||||
|
|
||||||
def _merge_resource_metadata(md_dict, entry, md_def):
|
|
||||||
"""Strips metadata from the entry as defined in the config,
|
|
||||||
and merges it with the given metadata dict.
|
|
||||||
"""
|
|
||||||
for field, parameters in md_def.iteritems():
|
|
||||||
for _, source in enumerate(parameters['sources']):
|
|
||||||
try:
|
|
||||||
value = entry['resource_metadata'][source]
|
|
||||||
if 'template' in parameters:
|
|
||||||
md_dict[field] = parameters['template'] % value
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
md_dict[field] = value
|
|
||||||
break
|
|
||||||
except KeyError:
|
|
||||||
# Just means we haven't found the right value yet.
|
|
||||||
# Or value isn't present.
|
|
||||||
pass
|
|
||||||
|
|
||||||
return md_dict
|
|
||||||
|
|
||||||
|
|
||||||
def get_project_locks(project_id):
|
def get_project_locks(project_id):
|
||||||
session = get_session()
|
session = get_session()
|
||||||
|
|
||||||
|
36
distil/tests/unit/api/base.py
Normal file
36
distil/tests/unit/api/base.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Copyright (C) 2017 Catalyst IT Ltd
|
||||||
|
#
|
||||||
|
# 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 flask
|
||||||
|
|
||||||
|
from distil.api import v2 as api_v2
|
||||||
|
from distil.common import api
|
||||||
|
from distil.tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
|
class APITest(base.DistilWithDbTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(APITest, self).setUp()
|
||||||
|
|
||||||
|
self.app = flask.Flask(__name__)
|
||||||
|
|
||||||
|
@self.app.route('/', methods=['GET'])
|
||||||
|
def version_list():
|
||||||
|
return api.render({
|
||||||
|
"versions": [
|
||||||
|
{"id": "v2", "status": "CURRENT"}
|
||||||
|
]})
|
||||||
|
|
||||||
|
self.app.register_blueprint(api_v2.rest, url_prefix="/v2")
|
||||||
|
self.client = self.app.test_client()
|
226
distil/tests/unit/api/test_api.py
Normal file
226
distil/tests/unit/api/test_api.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
# Copyright (C) 2017 Catalyst IT Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from datetime import date
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
|
from flask import url_for
|
||||||
|
import mock
|
||||||
|
from oslo_policy import policy as cpolicy
|
||||||
|
|
||||||
|
from distil.api import acl
|
||||||
|
from distil.common import constants
|
||||||
|
from distil.db import api as db_api
|
||||||
|
from distil.tests.unit.api import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestAPI(base.APITest):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
acl.setup_policy()
|
||||||
|
|
||||||
|
def _setup_policy(self, policy):
|
||||||
|
rules = cpolicy.Rules.from_dict(policy)
|
||||||
|
acl.ENFORCER.set_rules(rules, use_conf=False)
|
||||||
|
|
||||||
|
self.addCleanup(acl.ENFORCER.clear)
|
||||||
|
|
||||||
|
def test_get_versions(self):
|
||||||
|
ret = self.client.get('/')
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
{'versions': [{'id': 'v2', 'status': 'CURRENT'}]},
|
||||||
|
json.loads(ret.data)
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('distil.erp.drivers.odoo.OdooDriver.get_products')
|
||||||
|
@mock.patch('odoorpc.ODOO')
|
||||||
|
def test_products_get_without_regions(self, mock_odoo,
|
||||||
|
mock_odoo_get_products):
|
||||||
|
mock_odoo_get_products.return_value = []
|
||||||
|
|
||||||
|
ret = self.client.get('/v2/products')
|
||||||
|
|
||||||
|
self.assertEqual({'products': []}, json.loads(ret.data))
|
||||||
|
|
||||||
|
@mock.patch('distil.erp.drivers.odoo.OdooDriver.get_products')
|
||||||
|
@mock.patch('odoorpc.ODOO')
|
||||||
|
@mock.patch('distil.common.openstack.get_regions')
|
||||||
|
def test_products_get_with_regions(self, mock_regions, mock_odoo,
|
||||||
|
mock_odoo_get_products):
|
||||||
|
class Region(object):
|
||||||
|
def __init__(self, id):
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
mock_regions.return_value = [Region('nz_1'), Region('nz_2')]
|
||||||
|
mock_odoo_get_products.return_value = []
|
||||||
|
|
||||||
|
ret = self.client.get('/v2/products?regions=nz_1,nz_2')
|
||||||
|
|
||||||
|
mock_odoo_get_products.assert_called_once_with(['nz_1', 'nz_2'])
|
||||||
|
self.assertEqual({'products': []}, json.loads(ret.data))
|
||||||
|
|
||||||
|
@mock.patch('distil.common.openstack.get_regions')
|
||||||
|
def test_products_get_with_invalid_regions(self, mock_regions):
|
||||||
|
class Region(object):
|
||||||
|
def __init__(self, id):
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
mock_regions.return_value = [Region('nz_1'), Region('nz_2')]
|
||||||
|
|
||||||
|
ret = self.client.get('/v2/products?regions=nz_1,nz_3')
|
||||||
|
|
||||||
|
self.assertEqual(404, ret.status_code)
|
||||||
|
|
||||||
|
def test_measurements_get(self):
|
||||||
|
default_project = 'tenant_1'
|
||||||
|
start = '2014-06-01T00:00:00'
|
||||||
|
end = '2014-07-01T00:00:00'
|
||||||
|
res_id = 'instance_1'
|
||||||
|
|
||||||
|
db_api.project_add(
|
||||||
|
{
|
||||||
|
'id': default_project,
|
||||||
|
'name': 'default_project',
|
||||||
|
'description': 'project for test'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
db_api.resource_add(
|
||||||
|
default_project, res_id, {'type': 'Virtual Machine'}
|
||||||
|
)
|
||||||
|
db_api.usage_add(
|
||||||
|
default_project, res_id, {'instance': 100}, 'hour',
|
||||||
|
datetime.strptime(start, constants.iso_time),
|
||||||
|
datetime.strptime(end, constants.iso_time),
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
|
url = url_for(
|
||||||
|
'v2.measurements_get',
|
||||||
|
project_id=default_project,
|
||||||
|
start=start,
|
||||||
|
end=end
|
||||||
|
)
|
||||||
|
|
||||||
|
self._setup_policy({"rating:measurements:get": ""})
|
||||||
|
ret = self.client.get(url, headers={'X-Tenant-Id': default_project})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
{
|
||||||
|
'measurements': {
|
||||||
|
'start': '2014-06-01 00:00:00',
|
||||||
|
'end': '2014-07-01 00:00:00',
|
||||||
|
'project_name': 'default_project',
|
||||||
|
'project_id': default_project,
|
||||||
|
'resources': {
|
||||||
|
res_id: {
|
||||||
|
'type': 'Virtual Machine',
|
||||||
|
'services': [{
|
||||||
|
'name': 'instance',
|
||||||
|
'volume': '100.00',
|
||||||
|
'unit': 'hour'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
json.loads(ret.data)
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('distil.erp.drivers.odoo.OdooDriver.get_invoices')
|
||||||
|
@mock.patch('odoorpc.ODOO')
|
||||||
|
def test_invoices_get(self, mock_odoo, mock_get_invoices):
|
||||||
|
default_project = 'tenant_1'
|
||||||
|
start = '2014-06-01T00:00:00'
|
||||||
|
end = '2014-07-01T00:00:00'
|
||||||
|
|
||||||
|
db_api.project_add(
|
||||||
|
{
|
||||||
|
'id': default_project,
|
||||||
|
'name': 'default_project',
|
||||||
|
'description': 'project for test'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_get_invoices.return_value = {}
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
|
url = url_for(
|
||||||
|
'v2.invoices_get',
|
||||||
|
project_id=default_project,
|
||||||
|
start=start,
|
||||||
|
end=end
|
||||||
|
)
|
||||||
|
|
||||||
|
self._setup_policy({"rating:invoices:get": ""})
|
||||||
|
ret = self.client.get(url, headers={'X-Tenant-Id': default_project})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
{
|
||||||
|
'start': '2014-06-01 00:00:00',
|
||||||
|
'end': '2014-07-01 00:00:00',
|
||||||
|
'project_name': 'default_project',
|
||||||
|
'project_id': default_project,
|
||||||
|
'invoices': {}
|
||||||
|
},
|
||||||
|
json.loads(ret.data)
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('distil.erp.drivers.odoo.OdooDriver.get_quotations')
|
||||||
|
@mock.patch('odoorpc.ODOO')
|
||||||
|
def test_quotations_get(self, mock_odoo, mock_get_quotations):
|
||||||
|
self.override_config('keystone_authtoken', region_name='region-1')
|
||||||
|
|
||||||
|
default_project = 'tenant_1'
|
||||||
|
res_id = 'instance_1'
|
||||||
|
today = date.today()
|
||||||
|
datetime_today = datetime(today.year, today.month, today.day)
|
||||||
|
|
||||||
|
db_api.project_add(
|
||||||
|
{
|
||||||
|
'id': default_project,
|
||||||
|
'name': 'default_project',
|
||||||
|
'description': 'project for test'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
db_api.resource_add(
|
||||||
|
default_project, res_id, {'type': 'Virtual Machine'}
|
||||||
|
)
|
||||||
|
db_api.usage_add(
|
||||||
|
default_project, res_id, {'instance': 100}, 'hour',
|
||||||
|
datetime_today,
|
||||||
|
datetime_today,
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_get_quotations.return_value = {}
|
||||||
|
|
||||||
|
with self.app.test_request_context():
|
||||||
|
url = url_for(
|
||||||
|
'v2.quotations_get',
|
||||||
|
project_id=default_project,
|
||||||
|
)
|
||||||
|
|
||||||
|
self._setup_policy({"rating:quotations:get": ""})
|
||||||
|
ret = self.client.get(url, headers={'X-Tenant-Id': default_project})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
{
|
||||||
|
'start': str(datetime(today.year, today.month, 1)),
|
||||||
|
'end': str(datetime_today),
|
||||||
|
'project_name': 'default_project',
|
||||||
|
'project_id': default_project,
|
||||||
|
'quotations': {str(today): {}}
|
||||||
|
},
|
||||||
|
json.loads(ret.data)
|
||||||
|
)
|
@ -25,8 +25,8 @@ from distil import context
|
|||||||
from distil import config
|
from distil import config
|
||||||
from distil.db import api as db_api
|
from distil.db import api as db_api
|
||||||
|
|
||||||
class DistilTestCase(base.BaseTestCase):
|
|
||||||
|
|
||||||
|
class DistilTestCase(base.BaseTestCase):
|
||||||
config_file = None
|
config_file = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -13,3 +13,4 @@ testscenarios>=0.4
|
|||||||
testtools>=0.9.34
|
testtools>=0.9.34
|
||||||
WebTest>=2.0 # MIT
|
WebTest>=2.0 # MIT
|
||||||
mock>=2.0 # BSD
|
mock>=2.0 # BSD
|
||||||
|
Flask>=0.10,!=0.11,<1.0 # BSD
|
||||||
|
Loading…
x
Reference in New Issue
Block a user