Merge "Test tempest decorators used on integration tests"
diff --git a/README.rst b/README.rst
index bff2bf8..9daf873 100644
--- a/README.rst
+++ b/README.rst
@@ -118,3 +118,15 @@
Alternatively, you can use the run_tests.sh script which will create a venv and
run the unit tests. There are also the py26, py27, or py33 tox jobs which will
run the unit tests with the corresponding version of python.
+
+Python 2.6
+----------
+
+Tempest can be run with Python 2.6 however the unit tests and the gate
+currently only run with Python 2.7, so there are no guarantees about the state
+of tempest when running with Python 2.6. Additionally, to enable testr to work
+with tempest using python 2.6 the discover module from the unittest-ext
+project has to be patched to switch the unittest.TestSuite to use
+unittest2.TestSuite instead. See::
+
+https://code.google.com/p/unittest-ext/issues/detail?id=79
diff --git a/doc/source/conf.py b/doc/source/conf.py
index e5444ae..bd4e553 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -30,7 +30,7 @@
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
- 'oslo.sphinx'
+ 'oslosphinx'
]
todo_include_todos = True
diff --git a/etc/schemas/compute/flavors/flavor_details.json b/etc/schemas/compute/flavors/flavor_details.json
index d1c1077..c16075c 100644
--- a/etc/schemas/compute/flavors/flavor_details.json
+++ b/etc/schemas/compute/flavors/flavor_details.json
@@ -2,5 +2,7 @@
"name": "get-flavor-details",
"http-method": "GET",
"url": "flavors/%s",
- "resources": ["flavor"]
+ "resources": [
+ {"name": "flavor", "expected_result": 404}
+ ]
}
diff --git a/etc/schemas/compute/servers/get_console_output.json b/etc/schemas/compute/servers/get_console_output.json
index 7c3860f..8d974ba 100644
--- a/etc/schemas/compute/servers/get_console_output.json
+++ b/etc/schemas/compute/servers/get_console_output.json
@@ -2,7 +2,9 @@
"name": "get-console-output",
"http-method": "POST",
"url": "servers/%s/action",
- "resources": ["server"],
+ "resources": [
+ {"name":"server", "expected_result": 404}
+ ],
"json-schema": {
"type": "object",
"properties": {
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index ab882cd..5b272ef 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -63,7 +63,7 @@
except Exception:
# ignore errors while auto removing created resource
pass
-
+ cls.clear_isolated_creds()
super(BaseDataProcessingTest, cls).tearDownClass()
@classmethod
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index b05f275..342bc6a 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -14,7 +14,7 @@
from tempest.api.network import base
from tempest.common import tempest_fixtures as fixtures
-from tempest.test import attr
+from tempest import test
class AgentManagementTestJSON(base.BaseAdminNetworkTest):
@@ -23,11 +23,14 @@
@classmethod
def setUpClass(cls):
super(AgentManagementTestJSON, cls).setUpClass()
+ if not test.is_extension_enabled('agent', 'network'):
+ msg = "agent extension not enabled."
+ raise cls.skipException(msg)
resp, body = cls.admin_client.list_agents()
agents = body['agents']
cls.agent = agents[0]
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_agent(self):
resp, body = self.admin_client.list_agents()
self.assertEqual('200', resp['status'])
@@ -38,20 +41,20 @@
agent.pop('heartbeat_timestamp', None)
self.assertIn(self.agent, agents)
- @attr(type=['smoke'])
+ @test.attr(type=['smoke'])
def test_list_agents_non_admin(self):
resp, body = self.client.list_agents()
self.assertEqual('200', resp['status'])
self.assertEqual(len(body["agents"]), 0)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_show_agent(self):
resp, body = self.admin_client.show_agent(self.agent['id'])
agent = body['agent']
self.assertEqual('200', resp['status'])
self.assertEqual(agent['id'], self.agent['id'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_update_agent_status(self):
origin_status = self.agent['admin_state_up']
# Try to update the 'admin_state_up' to the original
@@ -63,7 +66,7 @@
self.assertEqual('200', resp['status'])
self.assertEqual(origin_status, updated_status)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_update_agent_description(self):
self.useFixture(fixtures.LockFixture('agent_description'))
description = 'description for update agent.'
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index 13309cd..ecd992a 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -13,7 +13,7 @@
# under the License.
from tempest.api.network import base
-from tempest.test import attr
+from tempest import test
class DHCPAgentSchedulersTestJSON(base.BaseAdminNetworkTest):
@@ -22,6 +22,9 @@
@classmethod
def setUpClass(cls):
super(DHCPAgentSchedulersTestJSON, cls).setUpClass()
+ if not test.is_extension_enabled('dhcp_agent_scheduler', 'network'):
+ msg = "dhcp_agent_scheduler extension not enabled."
+ raise cls.skipException(msg)
# Create a network and make sure it will be hosted by a
# dhcp agent.
cls.network = cls.create_network()
@@ -29,13 +32,13 @@
cls.cidr = cls.subnet['cidr']
cls.port = cls.create_port(cls.network)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_dhcp_agent_hosting_network(self):
resp, body = self.admin_client.list_dhcp_agent_hosting_network(
self.network['id'])
self.assertEqual(resp['status'], '200')
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_networks_hosted_by_one_dhcp(self):
resp, body = self.admin_client.list_dhcp_agent_hosting_network(
self.network['id'])
@@ -55,7 +58,7 @@
network_ids.append(network['id'])
return network_id in network_ids
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_remove_network_from_dhcp_agent(self):
resp, body = self.admin_client.list_dhcp_agent_hosting_network(
self.network['id'])
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index a177d65..529f8e9 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -44,6 +44,8 @@
'agent', 'dhcp_agent_scheduler', 'provider',
'router', 'extraroute', 'external-net',
'allowed-address-pairs', 'extra_dhcp_opt']
+ expected_alias = [ext for ext in expected_alias if
+ test.is_extension_enabled(ext, 'network')]
actual_alias = list()
resp, extensions = self.client.list_extensions()
self.assertEqual('200', resp['status'])
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 69367ab..b31c090 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -16,7 +16,7 @@
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -46,6 +46,9 @@
@classmethod
def setUpClass(cls):
super(FloatingIPTestJSON, cls).setUpClass()
+ if not test.is_extension_enabled('router', 'network'):
+ msg = "router extension not enabled."
+ raise cls.skipException(msg)
cls.ext_net_id = CONF.network.public_network_id
# Create network, subnet, router and add interface
@@ -59,7 +62,7 @@
for i in range(2):
cls.create_port(cls.network)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_list_show_update_delete_floating_ip(self):
# Creates a floating IP
created_floating_ip = self.create_floating_ip(
@@ -110,7 +113,7 @@
self.assertIsNone(updated_floating_ip['fixed_ip_address'])
self.assertIsNone(updated_floating_ip['router_id'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_floating_ip_delete_port(self):
# Create a floating IP
created_floating_ip = self.create_floating_ip(self.ext_net_id)
@@ -133,7 +136,7 @@
self.assertIsNone(shown_floating_ip['fixed_ip_address'])
self.assertIsNone(shown_floating_ip['router_id'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_floating_ip_update_different_router(self):
# Associate a floating IP to a port on a router
created_floating_ip = self.create_floating_ip(
diff --git a/tempest/api/network/test_quotas.py b/tempest/api/network/test_quotas.py
index a5be395..38784d8 100644
--- a/tempest/api/network/test_quotas.py
+++ b/tempest/api/network/test_quotas.py
@@ -17,7 +17,7 @@
from tempest.api.network import base
from tempest import clients
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class QuotasTest(base.BaseNetworkTest):
@@ -46,11 +46,14 @@
@classmethod
def setUpClass(cls):
super(QuotasTest, cls).setUpClass()
+ if not test.is_extension_enabled('quotas', 'network'):
+ msg = "quotas extension not enabled."
+ raise cls.skipException(msg)
admin_manager = clients.AdminManager()
cls.admin_client = admin_manager.network_client
cls.identity_admin_client = admin_manager.identity_client
- @attr(type='gate')
+ @test.attr(type='gate')
def test_quotas(self):
# Add a tenant to conduct the test
test_tenant = data_utils.rand_name('test_tenant_')
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index f3fac93..d552c70 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -29,6 +29,9 @@
@classmethod
def setUpClass(cls):
super(RoutersTest, cls).setUpClass()
+ if not test.is_extension_enabled('router', 'network'):
+ msg = "router extension not enabled."
+ raise cls.skipException(msg)
@test.attr(type='smoke')
def test_create_show_list_update_delete_router(self):
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 0d65b64..e6ad4de 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -16,7 +16,7 @@
from tempest.api.network import base_routers as base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class RoutersNegativeTest(base.BaseRouterTest):
@@ -25,11 +25,14 @@
@classmethod
def setUpClass(cls):
super(RoutersNegativeTest, cls).setUpClass()
+ if not test.is_extension_enabled('router', 'network'):
+ msg = "router extension not enabled."
+ raise cls.skipException(msg)
cls.router = cls.create_router(data_utils.rand_name('router-'))
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_router_add_gateway_invalid_network_returns_404(self):
self.assertRaises(exceptions.NotFound,
self.client.update_router,
@@ -37,7 +40,7 @@
external_gateway_info={
'network_id': self.router['id']})
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_router_add_gateway_net_not_external_returns_400(self):
self.create_subnet(self.network)
self.assertRaises(exceptions.BadRequest,
@@ -46,7 +49,7 @@
external_gateway_info={
'network_id': self.network['id']})
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_router_remove_interface_in_use_returns_409(self):
self.client.add_router_interface_with_subnet_id(
self.router['id'], self.subnet['id'])
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index b95182d..6eebf5b 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -14,13 +14,20 @@
# under the License.
from tempest.api.network import base_security_groups as base
-from tempest.test import attr
+from tempest import test
class SecGroupTest(base.BaseSecGroupTest):
_interface = 'json'
- @attr(type='smoke')
+ @classmethod
+ def setUpClass(cls):
+ super(SecGroupTest, cls).setUpClass()
+ if not test.is_extension_enabled('security-group', 'network'):
+ msg = "security-group extension not enabled."
+ raise cls.skipException(msg)
+
+ @test.attr(type='smoke')
def test_list_security_groups(self):
# Verify the that security group belonging to tenant exist in list
resp, body = self.client.list_security_groups()
@@ -33,7 +40,7 @@
msg = "Security-group list doesn't contain default security-group"
self.assertIsNotNone(found, msg)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_show_delete_security_group(self):
group_create_body, name = self._create_security_group()
@@ -51,7 +58,7 @@
secgroup_list.append(secgroup['id'])
self.assertIn(group_create_body['security_group']['id'], secgroup_list)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_show_delete_security_group_rule(self):
group_create_body, _ = self._create_security_group()
@@ -80,7 +87,7 @@
for rule in rule_list_body['security_group_rules']]
self.assertIn(rule_create_body['security_group_rule']['id'], rule_list)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_security_group_rule_with_additional_args(self):
# Verify creating security group rule with the following
# arguments works: "protocol": "tcp", "port_range_max": 77,
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 98e109e..e1f4055 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -17,26 +17,33 @@
from tempest.api.network import base_security_groups as base
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class NegativeSecGroupTest(base.BaseSecGroupTest):
_interface = 'json'
- @attr(type=['negative', 'gate'])
+ @classmethod
+ def setUpClass(cls):
+ super(NegativeSecGroupTest, cls).setUpClass()
+ if not test.is_extension_enabled('security-group', 'network'):
+ msg = "security-group extension not enabled."
+ raise cls.skipException(msg)
+
+ @test.attr(type=['negative', 'gate'])
def test_show_non_existent_security_group(self):
non_exist_id = str(uuid.uuid4())
self.assertRaises(exceptions.NotFound, self.client.show_security_group,
non_exist_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_show_non_existent_security_group_rule(self):
non_exist_id = str(uuid.uuid4())
self.assertRaises(exceptions.NotFound,
self.client.show_security_group_rule,
non_exist_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_non_existent_security_group(self):
non_exist_id = str(uuid.uuid4())
self.assertRaises(exceptions.NotFound,
@@ -44,7 +51,7 @@
non_exist_id
)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_security_group_rule_with_bad_protocol(self):
group_create_body, _ = self._create_security_group()
@@ -55,7 +62,7 @@
group_create_body['security_group']['id'],
protocol=pname)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_security_group_rule_with_invalid_ports(self):
group_create_body, _ = self._create_security_group()
@@ -73,7 +80,7 @@
port_range_max=pmax)
self.assertIn(msg, str(ex))
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_create_additional_default_security_group_fails(self):
# Create security group named 'default', it should be failed.
name = 'default'
@@ -81,7 +88,7 @@
self.client.create_security_group,
name)
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_create_security_group_rule_with_non_existent_security_group(self):
# Create security group rules with not existing security group.
non_existent_sg = str(uuid.uuid4())
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 1f661a6..c4614c6 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -10,7 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.common.utils import data_utils
from tempest import config
+from tempest import exceptions
import tempest.test
CONF = config.CONF
@@ -22,6 +24,28 @@
@classmethod
def setUpClass(cls):
- super(BaseTelemetryTest, cls).setUpClass()
if not CONF.service_available.ceilometer:
raise cls.skipException("Ceilometer support is required")
+ super(BaseTelemetryTest, cls).setUpClass()
+ os = cls.get_client_manager()
+ cls.telemetry_client = os.telemetry_client
+ cls.alarm_ids = []
+
+ @classmethod
+ def create_alarm(cls, **kwargs):
+ resp, body = cls.telemetry_client.create_alarm(
+ name=data_utils.rand_name('telemetry_alarm'),
+ type='threshold', **kwargs)
+ if resp['status'] == '201':
+ cls.alarm_ids.append(body['alarm_id'])
+ return resp, body
+
+ @classmethod
+ def tearDownClass(cls):
+ for alarm_id in cls.alarm_ids:
+ try:
+ cls.telemetry_client.delete_alarm(alarm_id)
+ except exceptions.NotFound:
+ pass
+ cls.clear_isolated_creds()
+ super(BaseTelemetryTest, cls).tearDownClass()
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
new file mode 100644
index 0000000..907d3d0
--- /dev/null
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -0,0 +1,43 @@
+# 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 tempest.api.telemetry import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class TelemetryAlarmingAPITestJSON(base.BaseTelemetryTest):
+ _interface = 'json'
+
+ @attr(type="gate")
+ def test_alarm_list(self):
+ resp, _ = self.telemetry_client.list_alarms()
+ self.assertEqual(int(resp['status']), 200)
+
+ @attr(type="gate")
+ def test_create_alarm(self):
+ rules = {'meter_name': 'cpu_util',
+ 'comparison_operator': 'gt',
+ 'threshold': 80.0,
+ 'period': 70}
+ resp, body = self.create_alarm(threshold_rule=rules)
+ self.alarm_id = body['alarm_id']
+ self.assertEqual(int(resp['status']), 201)
+ self.assertDictContainsSubset(rules, body['threshold_rule'])
+ resp, body = self.telemetry_client.get_alarm(self.alarm_id)
+ self.assertEqual(int(resp['status']), 200)
+ self.assertDictContainsSubset(rules, body['threshold_rule'])
+ resp, _ = self.telemetry_client.delete_alarm(self.alarm_id)
+ self.assertEqual(int(resp['status']), 204)
+ self.assertRaises(exceptions.NotFound,
+ self.telemetry_client.get_alarm,
+ self.alarm_id)
diff --git a/tempest/cli/simple_read_only/test_neutron.py b/tempest/cli/simple_read_only/test_neutron.py
index ebf0dc4..cd81378 100644
--- a/tempest/cli/simple_read_only/test_neutron.py
+++ b/tempest/cli/simple_read_only/test_neutron.py
@@ -57,17 +57,20 @@
self.assertTableStruct(ext, ['alias', 'name'])
@test.attr(type='smoke')
+ @test.requires_ext(extension='dhcp_agent_scheduler', service='network')
def test_neutron_dhcp_agent_list_hosting_net(self):
self.neutron('dhcp-agent-list-hosting-net',
params=CONF.compute.fixed_network_name)
@test.attr(type='smoke')
+ @test.requires_ext(extension='agent', service='network')
def test_neutron_agent_list(self):
agents = self.parser.listing(self.neutron('agent-list'))
field_names = ['id', 'agent_type', 'host', 'alive', 'admin_state_up']
self.assertTableStruct(agents, field_names)
@test.attr(type='smoke')
+ @test.requires_ext(extension='router', service='network')
def test_neutron_floatingip_list(self):
self.neutron('floatingip-list')
@@ -83,6 +86,7 @@
def test_neutron_meter_label_rule_list(self):
self.neutron('meter-label-rule-list')
+ @test.requires_ext(extension='lbaas_agent_scheduler', service='network')
def _test_neutron_lbaas_command(self, command):
try:
self.neutron(command)
@@ -107,6 +111,7 @@
self._test_neutron_lbaas_command('lb-vip-list')
@test.attr(type='smoke')
+ @test.requires_ext(extension='external-net', service='network')
def test_neutron_net_external_list(self):
self.neutron('net-external-list')
@@ -115,19 +120,23 @@
self.neutron('port-list')
@test.attr(type='smoke')
+ @test.requires_ext(extension='quotas', service='network')
def test_neutron_quota_list(self):
self.neutron('quota-list')
@test.attr(type='smoke')
+ @test.requires_ext(extension='router', service='network')
def test_neutron_router_list(self):
self.neutron('router-list')
@test.attr(type='smoke')
+ @test.requires_ext(extension='security-group', service='network')
def test_neutron_security_group_list(self):
security_grp = self.parser.listing(self.neutron('security-group-list'))
self.assertTableStruct(security_grp, ['id', 'name', 'description'])
@test.attr(type='smoke')
+ @test.requires_ext(extension='security-group', service='network')
def test_neutron_security_group_rule_list(self):
self.neutron('security-group-rule-list')
diff --git a/tempest/common/generate_json.py b/tempest/common/generate_json.py
index 0a0afe4..c8e86dc 100644
--- a/tempest/common/generate_json.py
+++ b/tempest/common/generate_json.py
@@ -203,36 +203,62 @@
return invalids
-type_map_valid = {"string": generate_valid_string,
- "integer": generate_valid_integer,
- "object": generate_valid_object}
+type_map_valid = {
+ "string": generate_valid_string,
+ "integer": generate_valid_integer,
+ "object": generate_valid_object
+}
-type_map_invalid = {"string": [gen_int,
- gen_none,
- gen_str_min_length,
- gen_str_max_length],
- "integer": [gen_string,
- gen_none,
- gen_int_min,
- gen_int_max],
- "object": [gen_obj_remove_attr,
- gen_obj_add_attr,
- gen_inv_prop_obj]}
+type_map_invalid = {
+ "string": [
+ gen_int,
+ gen_none,
+ gen_str_min_length,
+ gen_str_max_length],
+ "integer": [
+ gen_string,
+ gen_none,
+ gen_int_min,
+ gen_int_max],
+ "object": [
+ gen_obj_remove_attr,
+ gen_obj_add_attr,
+ gen_inv_prop_obj]
+}
-schema = {"type": "object",
- "properties":
- {"name": {"type": "string"},
- "http-method": {"enum": ["GET", "PUT", "HEAD",
- "POST", "PATCH", "DELETE", 'COPY']},
- "url": {"type": "string"},
- "json-schema": jsonschema._utils.load_schema("draft4"),
- "resources": {"type": "array", "items": {"type": "string"}},
- "results": {"type": "object",
- "properties": {}}
- },
- "required": ["name", "http-method", "url"],
- "additionalProperties": False,
- }
+schema = {
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "http-method": {
+ "enum": ["GET", "PUT", "HEAD",
+ "POST", "PATCH", "DELETE", 'COPY']
+ },
+ "url": {"type": "string"},
+ "json-schema": jsonschema._utils.load_schema("draft4"),
+ "resources": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {"type": "string"},
+ {
+ "type": "object",
+ "properties": {
+ "name": {"type": "string"},
+ "expected_result": {"type": "integer"}
+ }
+ }
+ ]
+ }
+ },
+ "results": {
+ "type": "object",
+ "properties": {}
+ }
+ },
+ "required": ["name", "http-method", "url"],
+ "additionalProperties": False,
+}
def validate_negative_test_schema(nts):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 020a256..0c0234f 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -19,9 +19,7 @@
from tempest import config
from tempest.openstack.common import log as logging
from tempest.scenario import manager
-
-from tempest.test import attr
-from tempest.test import services
+from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -113,6 +111,10 @@
@classmethod
def setUpClass(cls):
super(TestNetworkBasicOps, cls).setUpClass()
+ for ext in ['router', 'security-group']:
+ if not test.is_extension_enabled(ext, 'network'):
+ msg = "%s extension not enabled." % ext
+ raise cls.skipException(msg)
cls.check_preconditions()
# TODO(mnewby) Consider looking up entities as needed instead
# of storing them as collections on the class.
@@ -235,8 +237,8 @@
self._associate_floating_ip(floating_ip, server)
self.floating_ips[floating_ip] = server
- @attr(type='smoke')
- @services('compute', 'network')
+ @test.attr(type='smoke')
+ @test.services('compute', 'network')
def test_network_basic_ops(self):
self._create_security_groups()
self._create_networks()
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 747d7c1..e666475 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -29,10 +29,6 @@
def serialize(self, body):
return json.dumps(body)
- def create_alarm(self, **kwargs):
- uri = "%s/alarms" % self.uri_prefix
- return self.post(uri, kwargs)
-
def add_sample(self, sample_list, meter_name, meter_unit, volume,
sample_type, resource_id, **kwargs):
sample = {"counter_name": meter_name, "counter_unit": meter_unit,
diff --git a/tempest/services/telemetry/telemetry_client_base.py b/tempest/services/telemetry/telemetry_client_base.py
index 200c94a..a35a1ab 100644
--- a/tempest/services/telemetry/telemetry_client_base.py
+++ b/tempest/services/telemetry/telemetry_client_base.py
@@ -77,7 +77,7 @@
return self.rest_client.put(uri, body, self.headers)
def get(self, uri):
- resp, body = self.rest_client.get(uri)
+ resp, body = self.rest_client.get(uri, self.headers)
body = self.deserialize(body)
return resp, body
@@ -124,9 +124,13 @@
return self.get(uri)
def get_alarm(self, alarm_id):
- uri = '%s/meter/%s' % (self.uri_prefix, alarm_id)
+ uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
return self.get(uri)
def delete_alarm(self, alarm_id):
uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
return self.delete(uri)
+
+ def create_alarm(self, **kwargs):
+ uri = "%s/alarms" % self.uri_prefix
+ return self.post(uri, kwargs)
diff --git a/tempest/test.py b/tempest/test.py
index 38b9102..dcba226 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -17,6 +17,7 @@
import functools
import json
import os
+import sys
import time
import urllib
import uuid
@@ -241,10 +242,23 @@
atexit.register(validate_tearDownClass)
-
-class BaseTestCase(testtools.TestCase,
+if sys.version_info >= (2, 7):
+ class BaseDeps(testtools.TestCase,
testtools.testcase.WithAttributes,
testresources.ResourcedTestCase):
+ pass
+else:
+ # Define asserts for py26
+ import unittest2
+
+ class BaseDeps(testtools.TestCase,
+ testtools.testcase.WithAttributes,
+ testresources.ResourcedTestCase,
+ unittest2.TestCase):
+ pass
+
+
+class BaseTestCase(BaseDeps):
setUpClassCalled = False
_service = None
@@ -424,11 +438,16 @@
schema = description.get("json-schema", None)
resources = description.get("resources", [])
scenario_list = []
+ expected_result = None
for resource in resources:
+ if isinstance(resource, dict):
+ expected_result = resource['expected_result']
+ resource = resource['name']
LOG.debug("Add resource to test %s" % resource)
scn_name = "inv_res_%s" % (resource)
scenario_list.append((scn_name, {"resource": (resource,
- str(uuid.uuid4()))
+ str(uuid.uuid4())),
+ "expected_result": expected_result
}))
if schema is not None:
for invalid in generate_json.generate_invalid(schema):
@@ -479,16 +498,12 @@
if schema:
valid = generate_json.generate_valid(schema)
new_url, body = self._http_arguments(valid, url, method)
- resp, resp_body = self.client.send_request(method, new_url,
- resources, body=body)
- self._check_negative_response(resp.status, resp_body)
- return
-
- if hasattr(self, "schema"):
+ elif hasattr(self, "schema"):
new_url, body = self._http_arguments(self.schema, url, method)
- resp, resp_body = self.client.send_request(method, new_url,
- resources, body=body)
- self._check_negative_response(resp.status, resp_body)
+
+ resp, resp_body = self.client.send_request(method, new_url,
+ resources, body=body)
+ self._check_negative_response(resp.status, resp_body)
def _http_arguments(self, json_dict, url, method):
LOG.debug("dict: %s url: %s method: %s" % (json_dict, url, method))
@@ -529,6 +544,8 @@
:param name: The name of the kind of resource such as "flavor", "role",
etc.
"""
+ if isinstance(name, dict):
+ name = name['name']
if hasattr(self, "resource") and self.resource[0] == name:
LOG.debug("Return invalid resource (%s) value: %s" %
(self.resource[0], self.resource[1]))
diff --git a/test-requirements.txt b/test-requirements.txt
index 3fe2f27..8d64167 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,7 +3,7 @@
docutils==0.9.1
sphinx>=1.1.2,<1.2
python-subunit>=0.0.18
-oslo.sphinx
+oslosphinx
mox>=0.5.3
mock>=1.0
coverage>=3.6