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/*
|
||||
distil/tests/*
|
||||
distil/api/web.py
|
||||
distil/api/helpers.py
|
||||
distil/auth.py
|
||||
distil/database.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)
|
||||
|
||||
|
||||
# NOTE(lingxian): This method is not used anywhere but for testing purpose.
|
||||
def usage_add(project_id, resource_id, samples, unit,
|
||||
start_at, end_at):
|
||||
"""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)
|
||||
|
||||
|
||||
def resource_add(project_id, resource_id, resource_type, rawdata, metadata):
|
||||
return IMPL.resource_add(project_id, resource_id, resource_type,
|
||||
rawdata, metadata)
|
||||
# NOTE(lingxian): This method is not used anywhere but for testing purpose.
|
||||
def resource_add(project_id, resource_id, resource_info):
|
||||
return IMPL.resource_add(project_id, resource_id, resource_info)
|
||||
|
||||
|
||||
def project_add(values, last_collect=None):
|
||||
|
@ -207,8 +207,10 @@ def usage_add(project_id, resource_id, samples, unit,
|
||||
volume=volume,
|
||||
unit=unit,
|
||||
resource_id=resource_id,
|
||||
project_id=project_id,
|
||||
start_at=start_at, end_at=end_at)
|
||||
tenant_id=project_id,
|
||||
start=start_at,
|
||||
end=end_at,
|
||||
created=datetime.utcnow())
|
||||
resource_ref.save(session=session)
|
||||
except sa.exc.InvalidRequestError as e:
|
||||
# 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()
|
||||
metadata = _merge_resource_metadata({'type': resource_type}, raw, metadata)
|
||||
resource_ref = Resource(id=resource_id, project_id=project_id,
|
||||
resource_type=resource_type, meta_data=metadata)
|
||||
resource_ref = Resource(
|
||||
id=resource_id, tenant_id=project_id, info=json.dumps(resource_info),
|
||||
created=datetime.utcnow()
|
||||
)
|
||||
|
||||
try:
|
||||
resource_ref.save(session=session)
|
||||
@ -299,28 +302,6 @@ def resource_get_by_ids(project_id, resource_ids):
|
||||
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):
|
||||
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.db import api as db_api
|
||||
|
||||
class DistilTestCase(base.BaseTestCase):
|
||||
|
||||
class DistilTestCase(base.BaseTestCase):
|
||||
config_file = None
|
||||
|
||||
def setUp(self):
|
||||
|
@ -13,3 +13,4 @@ testscenarios>=0.4
|
||||
testtools>=0.9.34
|
||||
WebTest>=2.0 # MIT
|
||||
mock>=2.0 # BSD
|
||||
Flask>=0.10,!=0.11,<1.0 # BSD
|
||||
|
Loading…
Reference in New Issue
Block a user