Merge "Add multiple negative test generator support"
This commit is contained in:
commit
2c2c765de9
@ -562,6 +562,16 @@
|
||||
#ssh_user_regex=[["^.*[Cc]irros.*$", "root"]]
|
||||
|
||||
|
||||
[negative]
|
||||
|
||||
#
|
||||
# Options defined in tempest.config
|
||||
#
|
||||
|
||||
# Test generator class for all negative tests (string value)
|
||||
#test_generator=tempest.common.generator.negative_generator.NegativeTestGenerator
|
||||
|
||||
|
||||
[network]
|
||||
|
||||
#
|
||||
|
@ -1,265 +0,0 @@
|
||||
# Copyright 2014 Red Hat, Inc. & Deutsche Telekom AG
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 copy
|
||||
import jsonschema
|
||||
|
||||
from tempest.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_valid(schema):
|
||||
"""
|
||||
Create a valid dictionary based on the types in a json schema.
|
||||
"""
|
||||
LOG.debug("generate_valid: %s" % schema)
|
||||
schema_type = schema["type"]
|
||||
if isinstance(schema_type, list):
|
||||
# Just choose the first one since all are valid.
|
||||
schema_type = schema_type[0]
|
||||
return type_map_valid[schema_type](schema)
|
||||
|
||||
|
||||
def generate_valid_string(schema):
|
||||
size = schema.get("minLength", 0)
|
||||
# TODO(dkr mko): handle format and pattern
|
||||
return "x" * size
|
||||
|
||||
|
||||
def generate_valid_integer(schema):
|
||||
# TODO(dkr mko): handle multipleOf
|
||||
if "minimum" in schema:
|
||||
minimum = schema["minimum"]
|
||||
if "exclusiveMinimum" not in schema:
|
||||
return minimum
|
||||
else:
|
||||
return minimum + 1
|
||||
if "maximum" in schema:
|
||||
maximum = schema["maximum"]
|
||||
if "exclusiveMaximum" not in schema:
|
||||
return maximum
|
||||
else:
|
||||
return maximum - 1
|
||||
return 0
|
||||
|
||||
|
||||
def generate_valid_object(schema):
|
||||
obj = {}
|
||||
for k, v in schema["properties"].iteritems():
|
||||
obj[k] = generate_valid(v)
|
||||
return obj
|
||||
|
||||
|
||||
def generate_invalid(schema):
|
||||
"""
|
||||
Generate an invalid json dictionary based on a schema.
|
||||
Only one value is mis-generated for each dictionary created.
|
||||
|
||||
Any generator must return a list of tuples or a single tuple.
|
||||
The values of this tuple are:
|
||||
result[0]: Name of the test
|
||||
result[1]: json schema for the test
|
||||
result[2]: expected result of the test (can be None)
|
||||
"""
|
||||
LOG.debug("generate_invalid: %s" % schema)
|
||||
schema_type = schema["type"]
|
||||
if isinstance(schema_type, list):
|
||||
if "integer" in schema_type:
|
||||
schema_type = "integer"
|
||||
else:
|
||||
raise Exception("non-integer list types not supported")
|
||||
result = []
|
||||
for generator in type_map_invalid[schema_type]:
|
||||
ret = generator(schema)
|
||||
if ret is not None:
|
||||
if isinstance(ret, list):
|
||||
result.extend(ret)
|
||||
elif isinstance(ret, tuple):
|
||||
result.append(ret)
|
||||
else:
|
||||
raise Exception("generator (%s) returns invalid result"
|
||||
% generator)
|
||||
LOG.debug("result: %s" % result)
|
||||
return result
|
||||
|
||||
|
||||
def _check_for_expected_result(name, schema):
|
||||
expected_result = None
|
||||
if "results" in schema:
|
||||
if name in schema["results"]:
|
||||
expected_result = schema["results"][name]
|
||||
return expected_result
|
||||
|
||||
|
||||
def generator(fn):
|
||||
"""
|
||||
Decorator for simple generators that simply return one value
|
||||
"""
|
||||
def wrapped(schema):
|
||||
result = fn(schema)
|
||||
if result is not None:
|
||||
expected_result = _check_for_expected_result(fn.__name__, schema)
|
||||
return (fn.__name__, result, expected_result)
|
||||
return
|
||||
return wrapped
|
||||
|
||||
|
||||
@generator
|
||||
def gen_int(_):
|
||||
return 4
|
||||
|
||||
|
||||
@generator
|
||||
def gen_string(_):
|
||||
return "XXXXXX"
|
||||
|
||||
|
||||
def gen_none(schema):
|
||||
# Note(mkoderer): it's not using the decorator otherwise it'd be filtered
|
||||
expected_result = _check_for_expected_result('gen_none', schema)
|
||||
return ('gen_none', None, expected_result)
|
||||
|
||||
|
||||
@generator
|
||||
def gen_str_min_length(schema):
|
||||
min_length = schema.get("minLength", 0)
|
||||
if min_length > 0:
|
||||
return "x" * (min_length - 1)
|
||||
|
||||
|
||||
@generator
|
||||
def gen_str_max_length(schema):
|
||||
max_length = schema.get("maxLength", -1)
|
||||
if max_length > -1:
|
||||
return "x" * (max_length + 1)
|
||||
|
||||
|
||||
@generator
|
||||
def gen_int_min(schema):
|
||||
if "minimum" in schema:
|
||||
minimum = schema["minimum"]
|
||||
if "exclusiveMinimum" not in schema:
|
||||
minimum -= 1
|
||||
return minimum
|
||||
|
||||
|
||||
@generator
|
||||
def gen_int_max(schema):
|
||||
if "maximum" in schema:
|
||||
maximum = schema["maximum"]
|
||||
if "exclusiveMaximum" not in schema:
|
||||
maximum += 1
|
||||
return maximum
|
||||
|
||||
|
||||
def gen_obj_remove_attr(schema):
|
||||
invalids = []
|
||||
valid = generate_valid(schema)
|
||||
required = schema.get("required", [])
|
||||
for r in required:
|
||||
new_valid = copy.deepcopy(valid)
|
||||
del new_valid[r]
|
||||
invalids.append(("gen_obj_remove_attr", new_valid, None))
|
||||
return invalids
|
||||
|
||||
|
||||
@generator
|
||||
def gen_obj_add_attr(schema):
|
||||
valid = generate_valid(schema)
|
||||
if not schema.get("additionalProperties", True):
|
||||
new_valid = copy.deepcopy(valid)
|
||||
new_valid["$$$$$$$$$$"] = "xxx"
|
||||
return new_valid
|
||||
|
||||
|
||||
def gen_inv_prop_obj(schema):
|
||||
LOG.debug("generate_invalid_object: %s" % schema)
|
||||
valid = generate_valid(schema)
|
||||
invalids = []
|
||||
properties = schema["properties"]
|
||||
|
||||
for k, v in properties.iteritems():
|
||||
for invalid in generate_invalid(v):
|
||||
LOG.debug(v)
|
||||
new_valid = copy.deepcopy(valid)
|
||||
new_valid[k] = invalid[1]
|
||||
name = "prop_%s_%s" % (k, invalid[0])
|
||||
invalids.append((name, new_valid, invalid[2]))
|
||||
|
||||
LOG.debug("generate_invalid_object return: %s" % invalids)
|
||||
return invalids
|
||||
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
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):
|
||||
jsonschema.validate(nts, schema)
|
0
tempest/common/generator/__init__.py
Normal file
0
tempest/common/generator/__init__.py
Normal file
141
tempest/common/generator/base_generator.py
Normal file
141
tempest/common/generator/base_generator.py
Normal file
@ -0,0 +1,141 @@
|
||||
# Copyright 2014 Deutsche Telekom AG
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 jsonschema
|
||||
|
||||
from tempest.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _check_for_expected_result(name, schema):
|
||||
expected_result = None
|
||||
if "results" in schema:
|
||||
if name in schema["results"]:
|
||||
expected_result = schema["results"][name]
|
||||
return expected_result
|
||||
|
||||
|
||||
def generator_type(*args):
|
||||
def wrapper(func):
|
||||
func.types = args
|
||||
return func
|
||||
return wrapper
|
||||
|
||||
|
||||
def simple_generator(fn):
|
||||
"""
|
||||
Decorator for simple generators that return one value
|
||||
"""
|
||||
def wrapped(self, schema):
|
||||
result = fn(self, schema)
|
||||
if result is not None:
|
||||
expected_result = _check_for_expected_result(fn.__name__, schema)
|
||||
return (fn.__name__, result, expected_result)
|
||||
return
|
||||
return wrapped
|
||||
|
||||
|
||||
class BasicGeneratorSet(object):
|
||||
_instance = None
|
||||
|
||||
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 __new__(cls, *args, **kwargs):
|
||||
if not cls._instance:
|
||||
cls._instance = super(BasicGeneratorSet, cls).__new__(cls, *args,
|
||||
**kwargs)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
self.types_dict = {}
|
||||
for m in dir(self):
|
||||
if callable(getattr(self, m)) and not'__' in m:
|
||||
method = getattr(self, m)
|
||||
if hasattr(method, "types"):
|
||||
for type in method.types:
|
||||
if type not in self.types_dict:
|
||||
self.types_dict[type] = []
|
||||
self.types_dict[type].append(method)
|
||||
|
||||
def validate_schema(self, schema):
|
||||
jsonschema.validate(schema, self.schema)
|
||||
|
||||
def generate(self, schema):
|
||||
"""
|
||||
Generate an json dictionary based on a schema.
|
||||
Only one value is mis-generated for each dictionary created.
|
||||
|
||||
Any generator must return a list of tuples or a single tuple.
|
||||
The values of this tuple are:
|
||||
result[0]: Name of the test
|
||||
result[1]: json schema for the test
|
||||
result[2]: expected result of the test (can be None)
|
||||
"""
|
||||
LOG.debug("generate_invalid: %s" % schema)
|
||||
schema_type = schema["type"]
|
||||
if isinstance(schema_type, list):
|
||||
if "integer" in schema_type:
|
||||
schema_type = "integer"
|
||||
else:
|
||||
raise Exception("non-integer list types not supported")
|
||||
result = []
|
||||
if schema_type not in self.types_dict:
|
||||
raise Exception("generator (%s) doesn't support type: %s"
|
||||
% (self.__class__.__name__, schema_type))
|
||||
for generator in self.types_dict[schema_type]:
|
||||
ret = generator(schema)
|
||||
if ret is not None:
|
||||
if isinstance(ret, list):
|
||||
result.extend(ret)
|
||||
elif isinstance(ret, tuple):
|
||||
result.append(ret)
|
||||
else:
|
||||
raise Exception("generator (%s) returns invalid result: %s"
|
||||
% (generator, ret))
|
||||
LOG.debug("result: %s" % result)
|
||||
return result
|
111
tempest/common/generator/negative_generator.py
Normal file
111
tempest/common/generator/negative_generator.py
Normal file
@ -0,0 +1,111 @@
|
||||
# Copyright 2014 Deutsche Telekom AG
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 copy
|
||||
|
||||
import tempest.common.generator.base_generator as base
|
||||
import tempest.common.generator.valid_generator as valid
|
||||
from tempest.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NegativeTestGenerator(base.BasicGeneratorSet):
|
||||
@base.generator_type("string")
|
||||
@base.simple_generator
|
||||
def gen_int(self, _):
|
||||
return 4
|
||||
|
||||
@base.generator_type("integer")
|
||||
@base.simple_generator
|
||||
def gen_string(self, _):
|
||||
return "XXXXXX"
|
||||
|
||||
@base.generator_type("integer", "string")
|
||||
def gen_none(self, schema):
|
||||
# Note(mkoderer): it's not using the decorator otherwise it'd be
|
||||
# filtered
|
||||
expected_result = base._check_for_expected_result('gen_none', schema)
|
||||
return ('gen_none', None, expected_result)
|
||||
|
||||
@base.generator_type("string")
|
||||
@base.simple_generator
|
||||
def gen_str_min_length(self, schema):
|
||||
min_length = schema.get("minLength", 0)
|
||||
if min_length > 0:
|
||||
return "x" * (min_length - 1)
|
||||
|
||||
@base.generator_type("string")
|
||||
@base.simple_generator
|
||||
def gen_str_max_length(self, schema):
|
||||
max_length = schema.get("maxLength", -1)
|
||||
if max_length > -1:
|
||||
return "x" * (max_length + 1)
|
||||
|
||||
@base.generator_type("integer")
|
||||
@base.simple_generator
|
||||
def gen_int_min(self, schema):
|
||||
if "minimum" in schema:
|
||||
minimum = schema["minimum"]
|
||||
if "exclusiveMinimum" not in schema:
|
||||
minimum -= 1
|
||||
return minimum
|
||||
|
||||
@base.generator_type("integer")
|
||||
@base.simple_generator
|
||||
def gen_int_max(self, schema):
|
||||
if "maximum" in schema:
|
||||
maximum = schema["maximum"]
|
||||
if "exclusiveMaximum" not in schema:
|
||||
maximum += 1
|
||||
return maximum
|
||||
|
||||
@base.generator_type("object")
|
||||
def gen_obj_remove_attr(self, schema):
|
||||
invalids = []
|
||||
valid_schema = valid.ValidTestGenerator().generate_valid(schema)
|
||||
required = schema.get("required", [])
|
||||
for r in required:
|
||||
new_valid = copy.deepcopy(valid_schema)
|
||||
del new_valid[r]
|
||||
invalids.append(("gen_obj_remove_attr", new_valid, None))
|
||||
return invalids
|
||||
|
||||
@base.generator_type("object")
|
||||
@base.simple_generator
|
||||
def gen_obj_add_attr(self, schema):
|
||||
valid_schema = valid.ValidTestGenerator().generate_valid(schema)
|
||||
if not schema.get("additionalProperties", True):
|
||||
new_valid = copy.deepcopy(valid_schema)
|
||||
new_valid["$$$$$$$$$$"] = "xxx"
|
||||
return new_valid
|
||||
|
||||
@base.generator_type("object")
|
||||
def gen_inv_prop_obj(self, schema):
|
||||
LOG.debug("generate_invalid_object: %s" % schema)
|
||||
valid_schema = valid.ValidTestGenerator().generate_valid(schema)
|
||||
invalids = []
|
||||
properties = schema["properties"]
|
||||
|
||||
for k, v in properties.iteritems():
|
||||
for invalid in self.generate(v):
|
||||
LOG.debug(v)
|
||||
new_valid = copy.deepcopy(valid_schema)
|
||||
new_valid[k] = invalid[1]
|
||||
name = "prop_%s_%s" % (k, invalid[0])
|
||||
invalids.append((name, new_valid, invalid[2]))
|
||||
|
||||
LOG.debug("generate_invalid_object return: %s" % invalids)
|
||||
return invalids
|
58
tempest/common/generator/valid_generator.py
Normal file
58
tempest/common/generator/valid_generator.py
Normal file
@ -0,0 +1,58 @@
|
||||
# Copyright 2014 Deutsche Telekom AG
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 tempest.common.generator.base_generator as base
|
||||
from tempest.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ValidTestGenerator(base.BasicGeneratorSet):
|
||||
@base.generator_type("string")
|
||||
@base.simple_generator
|
||||
def generate_valid_string(self, schema):
|
||||
size = schema.get("minLength", 0)
|
||||
# TODO(dkr mko): handle format and pattern
|
||||
return "x" * size
|
||||
|
||||
@base.generator_type("integer")
|
||||
@base.simple_generator
|
||||
def generate_valid_integer(self, schema):
|
||||
# TODO(dkr mko): handle multipleOf
|
||||
if "minimum" in schema:
|
||||
minimum = schema["minimum"]
|
||||
if "exclusiveMinimum" not in schema:
|
||||
return minimum
|
||||
else:
|
||||
return minimum + 1
|
||||
if "maximum" in schema:
|
||||
maximum = schema["maximum"]
|
||||
if "exclusiveMaximum" not in schema:
|
||||
return maximum
|
||||
else:
|
||||
return maximum - 1
|
||||
return 0
|
||||
|
||||
@base.generator_type("object")
|
||||
@base.simple_generator
|
||||
def generate_valid_object(self, schema):
|
||||
obj = {}
|
||||
for k, v in schema["properties"].iteritems():
|
||||
obj[k] = self.generate_valid(v)
|
||||
return obj
|
||||
|
||||
def generate_valid(self, schema):
|
||||
return self.generate(schema)[0][1]
|
@ -820,6 +820,15 @@ CLIGroup = [
|
||||
help="Number of seconds to wait on a CLI timeout"),
|
||||
]
|
||||
|
||||
negative_group = cfg.OptGroup(name='negative', title="Negative Test Options")
|
||||
|
||||
NegativeGroup = [
|
||||
cfg.StrOpt('test_generator',
|
||||
default='tempest.common.' +
|
||||
'generator.negative_generator.NegativeTestGenerator',
|
||||
help="Test generator class for all negative tests"),
|
||||
]
|
||||
|
||||
|
||||
def register_opts():
|
||||
register_opt_group(cfg.CONF, compute_group, ComputeGroup)
|
||||
@ -855,6 +864,7 @@ def register_opts():
|
||||
register_opt_group(cfg.CONF, baremetal_group, BaremetalGroup)
|
||||
register_opt_group(cfg.CONF, input_scenario_group, InputScenarioGroup)
|
||||
register_opt_group(cfg.CONF, cli_group, CLIGroup)
|
||||
register_opt_group(cfg.CONF, negative_group, NegativeGroup)
|
||||
|
||||
|
||||
# this should never be called outside of this class
|
||||
@ -895,6 +905,7 @@ class TempestConfigPrivate(object):
|
||||
self.baremetal = cfg.CONF.baremetal
|
||||
self.input_scenario = cfg.CONF['input-scenario']
|
||||
self.cli = cfg.CONF.cli
|
||||
self.negative = cfg.CONF.negative
|
||||
if not self.compute_admin.username:
|
||||
self.compute_admin.username = self.identity.admin_username
|
||||
self.compute_admin.password = self.identity.admin_password
|
||||
|
@ -27,10 +27,11 @@ import testresources
|
||||
import testtools
|
||||
|
||||
from tempest import clients
|
||||
from tempest.common import generate_json
|
||||
import tempest.common.generator.valid_generator as valid
|
||||
from tempest.common import isolated_creds
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.openstack.common import importutils
|
||||
from tempest.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -400,7 +401,8 @@ class NegativeAutoTest(BaseTestCase):
|
||||
"""
|
||||
description = NegativeAutoTest.load_schema(description_file)
|
||||
LOG.debug(description)
|
||||
generate_json.validate_negative_test_schema(description)
|
||||
generator = importutils.import_class(CONF.negative.test_generator)()
|
||||
generator.validate_schema(description)
|
||||
schema = description.get("json-schema", None)
|
||||
resources = description.get("resources", [])
|
||||
scenario_list = []
|
||||
@ -416,7 +418,7 @@ class NegativeAutoTest(BaseTestCase):
|
||||
"expected_result": expected_result
|
||||
}))
|
||||
if schema is not None:
|
||||
for invalid in generate_json.generate_invalid(schema):
|
||||
for invalid in generator.generate(schema):
|
||||
scenario_list.append((invalid[0],
|
||||
{"schema": invalid[1],
|
||||
"expected_result": invalid[2]}))
|
||||
@ -459,11 +461,12 @@ class NegativeAutoTest(BaseTestCase):
|
||||
# Note(mkoderer): The resources list already contains an invalid
|
||||
# entry (see get_resource).
|
||||
# We just send a valid json-schema with it
|
||||
valid = None
|
||||
valid_schema = None
|
||||
schema = description.get("json-schema", None)
|
||||
if schema:
|
||||
valid = generate_json.generate_valid(schema)
|
||||
new_url, body = self._http_arguments(valid, url, method)
|
||||
valid_schema = \
|
||||
valid.ValidTestGenerator().generate_valid(schema)
|
||||
new_url, body = self._http_arguments(valid_schema, url, method)
|
||||
elif hasattr(self, "schema"):
|
||||
new_url, body = self._http_arguments(self.schema, url, method)
|
||||
|
||||
|
@ -43,6 +43,10 @@ class FakeConfig(object):
|
||||
swift = True
|
||||
horizon = True
|
||||
|
||||
class fake_negative(object):
|
||||
test_generator = 'tempest.common.' \
|
||||
'generator.negative_generator.NegativeTestGenerator'
|
||||
|
||||
compute_feature_enabled = fake_compute_feature_enabled()
|
||||
volume_feature_enabled = fake_default_feature_enabled()
|
||||
network_feature_enabled = fake_default_feature_enabled()
|
||||
@ -52,3 +56,5 @@ class FakeConfig(object):
|
||||
|
||||
compute = fake_compute()
|
||||
identity = fake_identity()
|
||||
|
||||
negative = fake_negative()
|
||||
|
@ -13,11 +13,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.common import generate_json as gen
|
||||
from tempest.common.generator import negative_generator
|
||||
import tempest.test
|
||||
|
||||
|
||||
class TestGenerateJson(tempest.test.BaseTestCase):
|
||||
class TestNegativeGenerator(tempest.test.BaseTestCase):
|
||||
|
||||
fake_input_str = {"type": "string",
|
||||
"minLength": 2,
|
||||
@ -35,19 +35,23 @@ class TestGenerateJson(tempest.test.BaseTestCase):
|
||||
}
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestNegativeGenerator, self).setUp()
|
||||
self.negative = negative_generator.NegativeTestGenerator()
|
||||
|
||||
def _validate_result(self, data):
|
||||
self.assertTrue(isinstance(data, list))
|
||||
for t in data:
|
||||
self.assertTrue(isinstance(t, tuple))
|
||||
|
||||
def test_generate_invalid_string(self):
|
||||
result = gen.generate_invalid(self.fake_input_str)
|
||||
result = self.negative.generate(self.fake_input_str)
|
||||
self._validate_result(result)
|
||||
|
||||
def test_generate_invalid_integer(self):
|
||||
result = gen.generate_invalid(self.fake_input_int)
|
||||
result = self.negative.generate(self.fake_input_int)
|
||||
self._validate_result(result)
|
||||
|
||||
def test_generate_invalid_obj(self):
|
||||
result = gen.generate_invalid(self.fake_input_obj)
|
||||
result = self.negative.generate(self.fake_input_obj)
|
||||
self._validate_result(result)
|
||||
|
@ -16,9 +16,11 @@
|
||||
import mock
|
||||
|
||||
import tempest.test as test
|
||||
from tempest.tests import base
|
||||
from tempest.tests import fake_config
|
||||
|
||||
|
||||
class TestNegativeAutoTest(test.BaseTestCase):
|
||||
class TestNegativeAutoTest(base.TestCase):
|
||||
# Fake entries
|
||||
_interface = 'json'
|
||||
_service = 'compute'
|
||||
@ -34,6 +36,10 @@ class TestNegativeAutoTest(test.BaseTestCase):
|
||||
"resources": ["flavor", "volume", "image"]
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestNegativeAutoTest, self).setUp()
|
||||
self.stubs.Set(test, 'CONF', fake_config.FakeConfig)
|
||||
|
||||
def _check_prop_entries(self, result, entry):
|
||||
entries = [a for a in result if entry in a[0]]
|
||||
self.assertIsNotNone(entries)
|
||||
|
Loading…
Reference in New Issue
Block a user