Merge pull request #7 from alvarolopez/refactor_tests
Refactor unit testing using a fake application
This commit is contained in:
commit
63839d2b55
|
@ -0,0 +1,167 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 Spanish National Research Council
|
||||
#
|
||||
# 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
|
||||
import uuid
|
||||
|
||||
import webob.dec
|
||||
|
||||
|
||||
tenants = {
|
||||
"foo": {"id": uuid.uuid4().hex,
|
||||
"name": "foo"},
|
||||
"bar": {"id": uuid.uuid4().hex,
|
||||
"name": "bar"}
|
||||
}
|
||||
|
||||
flavors = {
|
||||
1: {
|
||||
"id": 1,
|
||||
"name": "foo",
|
||||
"vcpus": 2,
|
||||
"ram": 256,
|
||||
"disk": 10,
|
||||
},
|
||||
2: {
|
||||
"id": 2,
|
||||
"name": "bar",
|
||||
"vcpus": 4,
|
||||
"ram": 2014,
|
||||
"disk": 20,
|
||||
}
|
||||
}
|
||||
|
||||
images = {
|
||||
"foo": {
|
||||
"id": "foo",
|
||||
"name": "foo",
|
||||
},
|
||||
"bar": {
|
||||
"id": "bar",
|
||||
"name": "bar",
|
||||
}
|
||||
}
|
||||
|
||||
servers = {
|
||||
tenants["foo"]["id"]: [
|
||||
{
|
||||
"id": uuid.uuid4().hex,
|
||||
"name": "foo",
|
||||
"flavor": {"id": flavors[1]["id"]},
|
||||
"image": {"id": images["foo"]["id"]},
|
||||
"status": "ACTIVE",
|
||||
},
|
||||
{
|
||||
"id": uuid.uuid4().hex,
|
||||
"name": "bar",
|
||||
"flavor": {"id": flavors[2]["id"]},
|
||||
"image": {"id": images["bar"]["id"]},
|
||||
"status": "SHUTOFF",
|
||||
},
|
||||
{
|
||||
"id": uuid.uuid4().hex,
|
||||
"name": "baz",
|
||||
"flavor": {"id": flavors[1]["id"]},
|
||||
"image": {"id": images["bar"]["id"]},
|
||||
"status": "ERROR",
|
||||
},
|
||||
],
|
||||
tenants["bar"]["id"]: [],
|
||||
}
|
||||
|
||||
|
||||
def fake_query_results():
|
||||
cats = []
|
||||
cats.append(
|
||||
'start; '
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; '
|
||||
'class="action"')
|
||||
cats.append(
|
||||
'stop; '
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; '
|
||||
'class="action"')
|
||||
cats.append(
|
||||
'restart; '
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; '
|
||||
'class="action"')
|
||||
cats.append(
|
||||
'suspend; '
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; '
|
||||
'class="action"')
|
||||
|
||||
result = []
|
||||
for c in cats:
|
||||
result.append(("Category", c))
|
||||
return result
|
||||
|
||||
|
||||
class FakeApp(object):
|
||||
"""Poor man's fake application."""
|
||||
|
||||
def __init__(self):
|
||||
self.routes = {}
|
||||
|
||||
for tenant in tenants.values():
|
||||
path = "/%s" % tenant["id"]
|
||||
|
||||
self._populate(path, "server", servers[tenant["id"]])
|
||||
# NOTE(aloga): dict_values un Py3 is not serializable in JSON
|
||||
self._populate(path, "image", list(images.values()))
|
||||
self._populate(path, "flavor", list(flavors.values()))
|
||||
|
||||
def _populate(self, path_base, obj_name, obj_list):
|
||||
objs_name = "%ss" % obj_name
|
||||
objs_path = "%s/%s" % (path_base, objs_name)
|
||||
self.routes[objs_path] = create_fake_json_resp({objs_name: obj_list})
|
||||
|
||||
for o in obj_list:
|
||||
obj_path = "%s/%s" % (objs_path, o["id"])
|
||||
self.routes[obj_path] = create_fake_json_resp({obj_name: o})
|
||||
|
||||
@webob.dec.wsgify()
|
||||
def __call__(self, req):
|
||||
if req.method == "GET":
|
||||
return self._do_get(req)
|
||||
elif req.method == "POST":
|
||||
return self._do_post(req)
|
||||
|
||||
def _do_create(self, req):
|
||||
s = {"server": {"id": "foo",
|
||||
"name": "foo",
|
||||
"flavor": {"id": "1"},
|
||||
"image": {"id": "2"},
|
||||
"status": "ACTIVE"}}
|
||||
return create_fake_json_resp(s)
|
||||
|
||||
def _do_post(self, req):
|
||||
if req.path_info.endswith("servers"):
|
||||
return self._do_create(req)
|
||||
raise Exception
|
||||
|
||||
def _do_get(self, req):
|
||||
try:
|
||||
ret = self.routes[req.path_info]
|
||||
except Exception:
|
||||
raise
|
||||
return ret
|
||||
|
||||
|
||||
def create_fake_json_resp(data):
|
||||
r = webob.Response()
|
||||
r.headers["Content-Type"] = "application/json"
|
||||
r.charset = "utf8"
|
||||
r.body = json.dumps(data).encode("utf8")
|
||||
return r
|
|
@ -14,45 +14,71 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
import webob
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
||||
from ooi.tests import fakes
|
||||
from ooi.tests.middleware import test_middleware
|
||||
|
||||
|
||||
def create_fake_json_resp(data):
|
||||
r = webob.Response()
|
||||
r.headers["Content-Type"] = "application/json"
|
||||
r.charset = "utf8"
|
||||
r.body = json.dumps(data).encode("utf8")
|
||||
return r
|
||||
def build_occi_server(server):
|
||||
name = server["name"]
|
||||
server_id = server["id"]
|
||||
flavor_name = fakes.flavors[server["flavor"]["id"]]["name"]
|
||||
ram = fakes.flavors[server["flavor"]["id"]]["ram"]
|
||||
cores = fakes.flavors[server["flavor"]["id"]]["vcpus"]
|
||||
image_id = server["image"]["id"]
|
||||
|
||||
status = server["status"].upper()
|
||||
if status in ("ACTIVE",):
|
||||
status = "active"
|
||||
elif status in ("PAUSED", "SUSPENDED", "STOPPED"):
|
||||
status = "suspended"
|
||||
else:
|
||||
status = "inactive"
|
||||
|
||||
cats = []
|
||||
cats.append('compute; '
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure"; '
|
||||
'class="kind"'),
|
||||
cats.append('%s; '
|
||||
'scheme="http://schemas.openstack.org/template/os"; '
|
||||
'class="mixin"' % image_id),
|
||||
cats.append('%s; '
|
||||
'scheme="http://schemas.openstack.org/template/resource"; '
|
||||
'class="mixin"' % flavor_name),
|
||||
|
||||
attrs = [
|
||||
'occi.core.title="%s"' % name,
|
||||
'occi.compute.state="%s"' % status,
|
||||
'occi.compute.memory=%s' % ram,
|
||||
'occi.compute.cores=%s' % cores,
|
||||
'occi.compute.hostname="%s"' % name,
|
||||
'occi.core.id="%s"' % server_id,
|
||||
]
|
||||
result = []
|
||||
for c in cats:
|
||||
result.append(("Category", c))
|
||||
for a in attrs:
|
||||
result.append(("X-OCCI-Attribute", a))
|
||||
return result
|
||||
|
||||
|
||||
class TestComputeController(test_middleware.TestMiddleware):
|
||||
"""Test OCCI compute controller."""
|
||||
|
||||
def test_list_vms_empty(self):
|
||||
tenant = uuid.uuid4().hex
|
||||
d = {"servers": []}
|
||||
fake_resp = {
|
||||
'/%s/servers' % tenant: create_fake_json_resp(d),
|
||||
}
|
||||
app = self.get_app(resp=fake_resp)
|
||||
tenant = fakes.tenants["bar"]
|
||||
app = self.get_app()
|
||||
|
||||
req = self._build_req("/compute", method="GET")
|
||||
req = self._build_req("/compute", tenant["id"], method="GET")
|
||||
|
||||
m = mock.MagicMock()
|
||||
m.user.project_id = tenant
|
||||
m.user.project_id = tenant["id"]
|
||||
req.environ["keystone.token_auth"] = m
|
||||
|
||||
resp = req.get_response(app)
|
||||
|
||||
self.assertEqual("/%s/servers" % tenant, req.environ["PATH_INFO"])
|
||||
self.assertEqual("/%s/servers" % tenant["id"], req.path_info)
|
||||
|
||||
expected_result = ""
|
||||
self.assertContentType(resp)
|
||||
|
@ -60,111 +86,56 @@ class TestComputeController(test_middleware.TestMiddleware):
|
|||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_list_vms_one_vm(self):
|
||||
tenant = uuid.uuid4().hex
|
||||
tenant = fakes.tenants["foo"]
|
||||
app = self.get_app()
|
||||
|
||||
d = {"servers": [{"id": uuid.uuid4().hex, "name": "foo"},
|
||||
{"id": uuid.uuid4().hex, "name": "bar"},
|
||||
{"id": uuid.uuid4().hex, "name": "baz"}]}
|
||||
|
||||
fake_resp = {
|
||||
'/%s/servers' % tenant: create_fake_json_resp(d),
|
||||
}
|
||||
|
||||
app = self.get_app(resp=fake_resp)
|
||||
req = self._build_req("/compute", method="GET")
|
||||
|
||||
m = mock.MagicMock()
|
||||
m.user.project_id = tenant
|
||||
req.environ["keystone.token_auth"] = m
|
||||
req = self._build_req("/compute", tenant["id"], method="GET")
|
||||
|
||||
resp = req.get_response(app)
|
||||
|
||||
self.assertEqual("/%s/servers" % tenant, req.environ["PATH_INFO"])
|
||||
self.assertEqual("/%s/servers" % tenant["id"], req.path_info)
|
||||
|
||||
self.assertEqual(200, resp.status_code)
|
||||
expected = []
|
||||
for s in d["servers"]:
|
||||
for s in fakes.servers[tenant["id"]]:
|
||||
expected.append(("X-OCCI-Location", "/compute/%s" % s["id"]))
|
||||
self.assertExpectedResult(expected, resp)
|
||||
|
||||
def test_show_vm(self):
|
||||
tenant = uuid.uuid4().hex
|
||||
server_id = uuid.uuid4().hex
|
||||
s = {"server": {"id": server_id,
|
||||
"name": "foo",
|
||||
"flavor": {"id": "1"},
|
||||
"image": {"id": "2"},
|
||||
"status": "ACTIVE"}}
|
||||
f = {"flavor": {"id": 1,
|
||||
"name": "foo",
|
||||
"vcpus": 2,
|
||||
"ram": 256,
|
||||
"disk": 10}}
|
||||
i = {"image": {"id": 2,
|
||||
"name": "bar"}}
|
||||
tenant = fakes.tenants["foo"]
|
||||
app = self.get_app()
|
||||
|
||||
fake_resp = {
|
||||
'/%s/servers/%s' % (tenant, server_id): create_fake_json_resp(s),
|
||||
'/%s/flavors/1' % tenant: create_fake_json_resp(f),
|
||||
'/%s/images/2' % tenant: create_fake_json_resp(i),
|
||||
}
|
||||
app = self.get_app(resp=fake_resp)
|
||||
req = self._build_req("/compute/%s" % server_id, method="GET")
|
||||
for server in fakes.servers[tenant["id"]]:
|
||||
req = self._build_req("/compute/%s" % server["id"],
|
||||
tenant["id"], method="GET")
|
||||
|
||||
m = mock.MagicMock()
|
||||
m.user.project_id = tenant
|
||||
req.environ["keystone.token_auth"] = m
|
||||
|
||||
resp = req.get_response(app)
|
||||
|
||||
expected = [
|
||||
('Category', 'compute; scheme="http://schemas.ogf.org/occi/infrastructure"; class="kind"'), # noqa
|
||||
('Category', '2; scheme="http://schemas.openstack.org/template/os"; class="mixin"'), # noqa
|
||||
('Category', 'foo; scheme="http://schemas.openstack.org/template/resource"; class="mixin"'), # noqa
|
||||
('X-OCCI-Attribute', 'occi.core.title="foo"'),
|
||||
('X-OCCI-Attribute', 'occi.compute.state="active"'),
|
||||
('X-OCCI-Attribute', 'occi.compute.memory=256'),
|
||||
('X-OCCI-Attribute', 'occi.compute.cores=2'),
|
||||
('X-OCCI-Attribute', 'occi.compute.hostname="foo"'),
|
||||
('X-OCCI-Attribute', 'occi.core.id="%s"' % server_id),
|
||||
]
|
||||
self.assertContentType(resp)
|
||||
self.assertExpectedResult(expected, resp)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
resp = req.get_response(app)
|
||||
expected = build_occi_server(server)
|
||||
self.assertContentType(resp)
|
||||
self.assertExpectedResult(expected, resp)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_create_vm(self):
|
||||
tenant = uuid.uuid4().hex
|
||||
server_id = uuid.uuid4().hex
|
||||
tenant = fakes.tenants["foo"]
|
||||
|
||||
s = {"server": {"id": server_id,
|
||||
"name": "foo",
|
||||
"flavor": {"id": "1"},
|
||||
"image": {"id": "2"},
|
||||
"status": "ACTIVE"}}
|
||||
|
||||
fake_resp = {"/%s/servers" % tenant: create_fake_json_resp(s)}
|
||||
app = self.get_app(resp=fake_resp)
|
||||
app = self.get_app()
|
||||
headers = {
|
||||
'Category': (
|
||||
'compute;'
|
||||
'scheme="http://schemas.ogf.org/occi/infrastructure#";'
|
||||
'class="kind",'
|
||||
'big;'
|
||||
'foo;'
|
||||
'scheme="http://schemas.openstack.org/template/resource#";'
|
||||
'class="mixin",'
|
||||
'cirros;'
|
||||
'bar;'
|
||||
'scheme="http://schemas.openstack.org/template/os#";'
|
||||
'class="mixin"')
|
||||
}
|
||||
req = self._build_req("/compute", method="POST", headers=headers)
|
||||
|
||||
m = mock.MagicMock()
|
||||
m.user.project_id = tenant
|
||||
req.environ["keystone.token_auth"] = m
|
||||
|
||||
req = self._build_req("/compute", tenant["id"], method="POST",
|
||||
headers=headers)
|
||||
resp = req.get_response(app)
|
||||
|
||||
expected = [("X-OCCI-Location", "/compute/%s" % server_id)]
|
||||
expected = [("X-OCCI-Location", "/compute/%s" % "foo")]
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertExpectedResult(expected, resp)
|
||||
self.assertContentType(resp)
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import webob
|
||||
|
||||
from ooi.tests import base
|
||||
from ooi.tests import fakes
|
||||
from ooi import wsgi
|
||||
|
||||
|
||||
|
@ -33,14 +35,7 @@ class TestMiddleware(base.TestCase):
|
|||
self.accept = None
|
||||
|
||||
def get_app(self, resp=None):
|
||||
if resp is None:
|
||||
resp = webob.Response()
|
||||
|
||||
@webob.dec.wsgify
|
||||
def app(req):
|
||||
# FIXME(aloga): raise some exception here
|
||||
return resp.get(req.path_info)
|
||||
return wsgi.OCCIMiddleware(app)
|
||||
return wsgi.OCCIMiddleware(fakes.FakeApp())
|
||||
|
||||
def assertContentType(self, result):
|
||||
expected = self.accept or "text/plain"
|
||||
|
@ -54,14 +49,18 @@ class TestMiddleware(base.TestCase):
|
|||
expected.sort()
|
||||
self.assertEqual(expected, results)
|
||||
|
||||
def _build_req(self, path, **kwargs):
|
||||
def _build_req(self, path, tenant_id, **kwargs):
|
||||
if self.accept is not None:
|
||||
kwargs["accept"] = self.accept
|
||||
return webob.Request.blank(path,
|
||||
**kwargs)
|
||||
|
||||
m = mock.MagicMock()
|
||||
m.user.project_id = tenant_id
|
||||
environ = {"keystone.token_auth": m}
|
||||
|
||||
return webob.Request.blank(path, environ=environ, **kwargs)
|
||||
|
||||
def test_404(self):
|
||||
result = self._build_req("/").get_response(self.get_app())
|
||||
result = self._build_req("/", "tenant").get_response(self.get_app())
|
||||
self.assertEqual(404, result.status_code)
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
from ooi.tests import fakes
|
||||
from ooi.tests.middleware import test_middleware
|
||||
|
||||
|
||||
|
@ -22,17 +23,9 @@ class TestQueryController(test_middleware.TestMiddleware):
|
|||
"""Test OCCI query controller."""
|
||||
|
||||
def test_query(self):
|
||||
result = self._build_req("/-/").get_response(self.get_app())
|
||||
|
||||
expected_result = [
|
||||
('Category', 'start; scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; class="action"'), # noqa
|
||||
('Category', 'stop; scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; class="action"'), # noqa
|
||||
('Category', 'restart; scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; class="action"'), # noqa
|
||||
('Category', 'suspend; scheme="http://schemas.ogf.org/occi/infrastructure/compute/action"; class="action"'), # noqa
|
||||
]
|
||||
|
||||
result = self._build_req("/-/", "tenant").get_response(self.get_app())
|
||||
self.assertContentType(result)
|
||||
self.assertExpectedResult(expected_result, result)
|
||||
self.assertExpectedResult(fakes.fake_query_results(), result)
|
||||
self.assertEqual(200, result.status_code)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue