Remove old way to describe scenario plugin via method
Initally Rally scenario plugins were methods of speical class. However to unify scenarios with other plugins we moved to model where plugin is class. We have a bunch of code that was used for transition and backward compatiblity that we can finally remove. Change-Id: Ia6841068eb1d5a39a8f64f160160f1fcc1e05ac5
This commit is contained in:
parent
bae6b61bea
commit
9a225ac837
@ -24,6 +24,7 @@ from rally.task import scenario
|
||||
from test_relative_import import zzz
|
||||
|
||||
|
||||
@scenario.configure(name="FakePlugin.testplugin")
|
||||
class FakePlugin(scenario.Scenario):
|
||||
"""Fake plugin with a scenario."""
|
||||
|
||||
@ -35,8 +36,7 @@ class FakePlugin(scenario.Scenario):
|
||||
def _test2(self, factor):
|
||||
time.sleep(random.random() * factor)
|
||||
|
||||
@scenario.configure()
|
||||
def testplugin(self, factor=1):
|
||||
def run(self, factor=1):
|
||||
"""Fake scenario.
|
||||
|
||||
:param factor: influences the argument value for a time.sleep() call
|
||||
|
@ -91,13 +91,12 @@ class InfoMixin(object):
|
||||
|
||||
@classmethod
|
||||
def get_info(cls):
|
||||
plugin_ = getattr(cls, "func_ref", cls)
|
||||
doc = parse_docstring(cls._get_doc())
|
||||
|
||||
return {
|
||||
"name": plugin_.get_name(),
|
||||
"namespace": plugin_.get_namespace(),
|
||||
"module": plugin_.__module__,
|
||||
"name": cls.get_name(),
|
||||
"namespace": cls.get_namespace(),
|
||||
"module": cls.__module__,
|
||||
"title": doc["short_description"],
|
||||
"description": doc["long_description"],
|
||||
"parameters": doc["params"],
|
||||
|
@ -77,78 +77,6 @@ def configure(name, namespace="default", hidden=False):
|
||||
return decorator
|
||||
|
||||
|
||||
def from_func(plugin_baseclass=None):
|
||||
"""Add all plugin's methods to function object.
|
||||
|
||||
Rally benchmark scenarios are different from all other plugins in Rally.
|
||||
|
||||
Usually 1 plugin is 1 class and we can easily use Plugin() as base for
|
||||
all of them to avoid code duplication. In case of benchmark scenarios
|
||||
1 class can contain any amount of scenarios that are just methods
|
||||
of this class.
|
||||
|
||||
To make Rally code cleaner, these methods should look/work like other
|
||||
Plugins.
|
||||
|
||||
This decorator makes all dirty work for us, it creates dynamically new
|
||||
class, adds plugin instance and aliases for all non-private methods of
|
||||
Plugin instance to passed function.
|
||||
|
||||
|
||||
For example,
|
||||
|
||||
@plugin.from_func()
|
||||
def my_plugin_like_func(a, b):
|
||||
pass
|
||||
|
||||
|
||||
assert my_plugin_like_func.get_name() == "my_plugin_like_func"
|
||||
assert my_plugin_like_func.get_all() == []
|
||||
|
||||
|
||||
As a result, adding plugin behavior for benchmark scenarios fully unifies
|
||||
work with benchmark scenarios and other kinds of plugins.
|
||||
|
||||
:param plugin_baseclass: if specified, subclass of this class will be used
|
||||
to add behavior of plugin to function else,
|
||||
subclass of Plugin will be used.
|
||||
:returns: Function decorator that adds plugin behavior to function
|
||||
"""
|
||||
|
||||
if plugin_baseclass:
|
||||
if not issubclass(plugin_baseclass, Plugin):
|
||||
raise TypeError("plugin_baseclass should be subclass of %s "
|
||||
% Plugin)
|
||||
|
||||
class FuncPlugin(plugin_baseclass):
|
||||
|
||||
is_classbased = False
|
||||
|
||||
else:
|
||||
class FuncPlugin(Plugin):
|
||||
|
||||
is_classbased = False
|
||||
|
||||
def decorator(func):
|
||||
func._plugin = FuncPlugin
|
||||
|
||||
# NOTE(boris-42): This is required by Plugin.get_all method to
|
||||
# return func instead of FuncPlugin that will be
|
||||
# auto discovered.
|
||||
FuncPlugin.func_ref = func
|
||||
|
||||
# NOTE(boris-42): Make aliases from func to all public Plugin fields
|
||||
for field in dir(func._plugin):
|
||||
if not field.startswith("__"):
|
||||
obj = getattr(func._plugin, field)
|
||||
if callable(obj):
|
||||
setattr(func, field, obj)
|
||||
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class Plugin(meta.MetaMixin, info.InfoMixin):
|
||||
"""Base class for all Plugins in Rally."""
|
||||
|
||||
@ -278,8 +206,7 @@ class Plugin(meta.MetaMixin, info.InfoMixin):
|
||||
continue
|
||||
if not allow_hidden and p.is_hidden():
|
||||
continue
|
||||
|
||||
plugins.append(getattr(p, "func_ref", p))
|
||||
plugins.append(p)
|
||||
|
||||
return plugins
|
||||
|
||||
|
@ -60,9 +60,7 @@ class ArgsValidator(validation.Validator):
|
||||
scenario = plugin_cls
|
||||
name = scenario.get_name()
|
||||
namespace = scenario.get_namespace()
|
||||
if scenario.is_classbased:
|
||||
# We need initialize scenario class to access instancemethods
|
||||
scenario = scenario().run
|
||||
scenario = scenario().run
|
||||
args, _varargs, varkwargs, defaults = inspect.getargspec(scenario)
|
||||
|
||||
hint_msg = (" Use `rally plugin show --name %s --namespace %s` "
|
||||
|
@ -374,11 +374,8 @@ class TaskEngine(object):
|
||||
|
||||
# TODO(andreykurilin): Remove check for plugin namespace after
|
||||
# Rally 0.10.0
|
||||
if scenario_cls.is_classbased:
|
||||
cls = scenario_cls
|
||||
else:
|
||||
cls = scenario_cls._plugin
|
||||
if (issubclass(cls, os_scenario.OpenStackScenario)
|
||||
|
||||
if (issubclass(scenario_cls, os_scenario.OpenStackScenario)
|
||||
and namespace == "default"):
|
||||
LOG.warning(
|
||||
"Scenario '%(scen)s' is located in 'default' "
|
||||
|
@ -164,14 +164,9 @@ class ScenarioRunner(plugin.Plugin, validation.ValidatablePluginMixin):
|
||||
# NOTE(boris-42): processing @types decorators
|
||||
args = types.preprocess(name, context, args)
|
||||
|
||||
if scenario_plugin.is_classbased:
|
||||
cls, method_name = scenario_plugin, "run"
|
||||
else:
|
||||
cls, method_name = (scenario_plugin._meta_get("cls_ref"),
|
||||
name.split(".", 1).pop())
|
||||
|
||||
with rutils.Timer() as timer:
|
||||
self._run_scenario(cls, method_name, context, args)
|
||||
# TODO(boris-42): remove method_name argument, now it's always run
|
||||
self._run_scenario(scenario_plugin, "run", context, args)
|
||||
|
||||
self.run_duration = timer.duration()
|
||||
|
||||
|
@ -15,8 +15,6 @@
|
||||
|
||||
import random
|
||||
|
||||
import six
|
||||
|
||||
from rally.common.i18n import _
|
||||
from rally.common import logging
|
||||
from rally.common.objects import task # noqa
|
||||
@ -45,65 +43,22 @@ def configure(name=None, namespace="default", context=None):
|
||||
If there are custom user specified contexts this one
|
||||
will be updated by provided contexts.
|
||||
"""
|
||||
def wrapper(scen):
|
||||
scen.is_classbased = hasattr(scen, "run") and callable(scen.run)
|
||||
if not scen.is_classbased:
|
||||
plugin.from_func(Scenario)(scen)
|
||||
|
||||
scen._meta_init()
|
||||
def wrapper(cls):
|
||||
# TODO(boris-42): Drop this check as soon as we refactor rally report
|
||||
if name:
|
||||
if "." not in name.strip("."):
|
||||
msg = (_("Scenario name must include a dot: '%s'") % name)
|
||||
raise exceptions.RallyException(msg)
|
||||
scen._set_name_and_namespace(name, namespace)
|
||||
else:
|
||||
scen._meta_set("namespace", namespace)
|
||||
scen._meta_set("default_context", context or {})
|
||||
return scen
|
||||
|
||||
cls = plugin.configure(name=name, namespace=namespace)(cls)
|
||||
cls._meta_set("default_context", context or {})
|
||||
return cls
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class ConfigurePluginMeta(type):
|
||||
"""Finish Scenario plugin configuration.
|
||||
|
||||
After @scenario.configure() is performed to cls.method, method.im_class is
|
||||
pointing to FuncPlugin class instead of original cls. There is no way to
|
||||
fix this, mostly because im_class is add to method when it's called via
|
||||
cls, e.g. cls.method. Decorator is different case so there is no
|
||||
information about cls. method._plugin is pointing to FuncPlugin that has
|
||||
FuncPlugin pointer to method. What should be done is to set properly
|
||||
FuncPluing.func_ref to the cls.method
|
||||
|
||||
This metaclass iterates over all cls methods and fix func_ref of FuncPlugin
|
||||
class so func_ref will be cls.method instead of FuncPlugin.method.
|
||||
|
||||
Additionally this metaclass sets plugin names if they were not set explicit
|
||||
via configure(). Default name is <cls_name>.<method_name>
|
||||
|
||||
As well we need to keep cls_ref inside of _meta because Python3 loves us.
|
||||
|
||||
Viva black magic and dirty hacks.
|
||||
"""
|
||||
def __init__(cls, name, bases, namespaces):
|
||||
|
||||
super(ConfigurePluginMeta, cls).__init__(name, bases, namespaces)
|
||||
|
||||
for name, field in namespaces.items():
|
||||
if callable(field) and hasattr(field, "_plugin"):
|
||||
field._plugin._meta_set("cls_ref", cls)
|
||||
|
||||
if not field._meta_get("name", None):
|
||||
field._set_name_and_namespace(
|
||||
"%s.%s" % (cls.__name__, field.__name__),
|
||||
field.get_namespace())
|
||||
|
||||
field._plugin.func_ref = getattr(
|
||||
cls, field._plugin.func_ref.__name__)
|
||||
|
||||
|
||||
@validation.add_default("args-spec")
|
||||
@plugin.base()
|
||||
@six.add_metaclass(ConfigurePluginMeta)
|
||||
class Scenario(plugin.Plugin,
|
||||
atomic.ActionTimerMixin,
|
||||
functional.FunctionalMixin,
|
||||
@ -203,6 +158,4 @@ class Scenario(plugin.Plugin,
|
||||
|
||||
@classmethod
|
||||
def _get_doc(cls):
|
||||
if cls.is_classbased:
|
||||
return cls.run.__doc__
|
||||
return cls.__doc__
|
||||
return cls.run.__doc__
|
||||
|
@ -16,10 +16,9 @@
|
||||
from rally.task import scenario
|
||||
|
||||
|
||||
@scenario.configure(name="FakeScenarioPlugin1.list")
|
||||
class FakeScenarioPlugin1(scenario.Scenario):
|
||||
"""Sample fake plugin."""
|
||||
|
||||
@scenario.configure()
|
||||
def list(self):
|
||||
"""Fake scenario."""
|
||||
def run(self):
|
||||
"""Sample fake scenario."""
|
||||
pass
|
||||
|
@ -16,10 +16,9 @@
|
||||
from rally.task import scenario
|
||||
|
||||
|
||||
@scenario.configure(name="FakeScenarioPlugin2.list")
|
||||
class FakeScenarioPlugin2(scenario.Scenario):
|
||||
"""Sample fake plugin."""
|
||||
|
||||
@scenario.configure()
|
||||
def list(self):
|
||||
"""Fake scenario."""
|
||||
def run(self):
|
||||
"""Sample fake scenario."""
|
||||
pass
|
||||
|
@ -20,30 +20,6 @@ from tests.unit import test
|
||||
|
||||
class PluginModuleTestCase(test.TestCase):
|
||||
|
||||
def test_deprecated_func(self):
|
||||
|
||||
@plugin.deprecated("some", "0.0.1")
|
||||
@plugin.configure(name="deprecated_func_plugin_test")
|
||||
@plugin.from_func()
|
||||
def func():
|
||||
return 42
|
||||
|
||||
self.assertEqual("deprecated_func_plugin_test", func.get_name())
|
||||
self.assertEqual({"reason": "some", "rally_version": "0.0.1"},
|
||||
func.is_deprecated())
|
||||
self.assertEqual(42, func())
|
||||
|
||||
def test_configure(self):
|
||||
|
||||
@plugin.configure(name="configure_func_plugin_test")
|
||||
@plugin.from_func()
|
||||
def func(a):
|
||||
return a
|
||||
|
||||
self.assertEqual("configure_func_plugin_test", func.get_name())
|
||||
self.assertFalse(func.is_hidden())
|
||||
self.assertEqual(42, func(42))
|
||||
|
||||
def test_deprecated_cls(self):
|
||||
|
||||
@plugin.deprecated("God why?", "0.0.2")
|
||||
@ -106,38 +82,6 @@ class PluginModuleTestCase(test.TestCase):
|
||||
self.assertRaises(exceptions.MultipleMatchesFound, plugin.Plugin.get,
|
||||
name, name)
|
||||
|
||||
def test_from_func(self):
|
||||
|
||||
@plugin.from_func()
|
||||
def func():
|
||||
return 42
|
||||
|
||||
missing = [field for field in set(dir(plugin.Plugin)) - set(dir(func))
|
||||
if not field.startswith("__")]
|
||||
self.assertEqual([], missing)
|
||||
self.assertTrue(issubclass(func._plugin, plugin.Plugin))
|
||||
self.assertEqual(42, func())
|
||||
|
||||
def test_from_func_with_basecls(self):
|
||||
|
||||
class FakeFuncBasePlugin(plugin.Plugin):
|
||||
pass
|
||||
|
||||
@plugin.from_func(FakeFuncBasePlugin)
|
||||
def func():
|
||||
return 43
|
||||
|
||||
self.assertTrue(issubclass(func._plugin, FakeFuncBasePlugin))
|
||||
self.assertEqual(43, func())
|
||||
|
||||
def test_from_func_with_bad_basecls(self):
|
||||
|
||||
class FakeFuncBasePlugin(object):
|
||||
pass
|
||||
|
||||
self.assertRaises(TypeError,
|
||||
plugin.from_func, FakeFuncBasePlugin)
|
||||
|
||||
|
||||
@plugin.configure(name="test_base_plugin")
|
||||
class BasePlugin(plugin.Plugin):
|
||||
|
@ -22,7 +22,6 @@ import rally
|
||||
from rally.common.plugin import plugin
|
||||
from rally.common import validation
|
||||
from rally.plugins.common import validators
|
||||
from rally.task import scenario
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
@ -67,7 +66,7 @@ class ArgsValidatorTestCase(test.TestCase):
|
||||
@plugin.base()
|
||||
class DummyPluginBase(plugin.Plugin,
|
||||
validation.ValidatablePluginMixin):
|
||||
is_classbased = True
|
||||
pass
|
||||
|
||||
@validation.add(name="args-spec")
|
||||
@plugin.configure(name="dummy_plugin")
|
||||
@ -85,23 +84,6 @@ class ArgsValidatorTestCase(test.TestCase):
|
||||
|
||||
DummyPlugin.unregister()
|
||||
|
||||
class DummyPlugin2(DummyPluginBase):
|
||||
@scenario.configure(name="dummy_plugin.func_based")
|
||||
def func_based(self, a, b, c="spam"):
|
||||
pass
|
||||
|
||||
result = scenario.Scenario.validate(
|
||||
"dummy_plugin.func_based", None, config, None)
|
||||
|
||||
if err_msg is None:
|
||||
self.assertEqual(0, len(result))
|
||||
else:
|
||||
self.assertEqual(1, len(result))
|
||||
self.assertFalse(result[0].is_valid)
|
||||
self.assertIn(err_msg, result[0].msg)
|
||||
|
||||
DummyPlugin2.func_based.unregister()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class RequiredParameterValidatorTestCase(test.TestCase):
|
||||
|
@ -21,7 +21,6 @@ import mock
|
||||
|
||||
from rally.plugins.common.runners import serial
|
||||
from rally.task import runner
|
||||
from rally.task import scenario
|
||||
from tests.unit import fakes
|
||||
from tests.unit import test
|
||||
|
||||
@ -135,41 +134,6 @@ class ScenarioRunnerTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(BASE + "rutils.Timer.duration", return_value=10)
|
||||
def test_run(self, mock_timer_duration):
|
||||
runner_obj = serial.SerialScenarioRunner(
|
||||
mock.MagicMock(),
|
||||
mock.MagicMock())
|
||||
|
||||
runner_obj._run_scenario = mock.MagicMock()
|
||||
|
||||
scenario_name = "NovaServers.boot_server_from_volume_and_delete"
|
||||
config_kwargs = {"image": {"id": 1}, "flavor": {"id": 1}}
|
||||
|
||||
context_obj = {
|
||||
"task": runner_obj.task,
|
||||
"scenario_name": scenario_name,
|
||||
"admin": {"credential": mock.MagicMock()},
|
||||
"config": {
|
||||
"cleanup": ["nova", "cinder"], "some_ctx": 2, "users": {}
|
||||
}
|
||||
}
|
||||
|
||||
result = runner_obj.run(scenario_name, context_obj, config_kwargs)
|
||||
|
||||
self.assertIsNone(result)
|
||||
self.assertEqual(runner_obj.run_duration,
|
||||
mock_timer_duration.return_value)
|
||||
self.assertEqual(list(runner_obj.result_queue), [])
|
||||
|
||||
plugin_cls, method_name = scenario.Scenario.get(scenario_name), "run"
|
||||
|
||||
self.assertTrue(plugin_cls.is_classbased)
|
||||
|
||||
expected_config_kwargs = {"image": 1, "flavor": 1}
|
||||
runner_obj._run_scenario.assert_called_once_with(
|
||||
plugin_cls, method_name, context_obj, expected_config_kwargs)
|
||||
|
||||
@mock.patch(BASE + "rutils.Timer.duration", return_value=10)
|
||||
def test_run_classbased(self, mock_timer_duration):
|
||||
scenario_class = fakes.FakeClassBasedScenario
|
||||
runner_obj = serial.SerialScenarioRunner(
|
||||
mock.MagicMock(),
|
||||
|
@ -25,52 +25,13 @@ class ScenarioConfigureTestCase(test.TestCase):
|
||||
|
||||
def test_configure(self):
|
||||
|
||||
@scenario.configure("fooscenario.name", "testing")
|
||||
def some_func():
|
||||
pass
|
||||
|
||||
self.assertEqual("fooscenario.name", some_func.get_name())
|
||||
self.assertEqual("testing", some_func.get_namespace())
|
||||
self.assertFalse(some_func.is_classbased)
|
||||
some_func.unregister()
|
||||
|
||||
def test_configure_default_name(self):
|
||||
|
||||
@scenario.configure(namespace="testing", context={"any": 42})
|
||||
def some_func():
|
||||
pass
|
||||
|
||||
self.assertIsNone(some_func._meta_get("name"))
|
||||
self.assertEqual("testing", some_func.get_namespace())
|
||||
self.assertEqual({"any": 42}, some_func.get_default_context())
|
||||
self.assertFalse(some_func.is_classbased)
|
||||
some_func.unregister()
|
||||
|
||||
def test_configure_cls(self):
|
||||
|
||||
class ScenarioPluginCls(scenario.Scenario):
|
||||
|
||||
@scenario.configure(namespace="any", context={"any": 43})
|
||||
def some(self):
|
||||
pass
|
||||
|
||||
self.assertEqual("ScenarioPluginCls.some",
|
||||
ScenarioPluginCls.some.get_name())
|
||||
self.assertEqual("any", ScenarioPluginCls.some.get_namespace())
|
||||
self.assertEqual({"any": 43},
|
||||
ScenarioPluginCls.some.get_default_context())
|
||||
self.assertFalse(ScenarioPluginCls.some.is_classbased)
|
||||
ScenarioPluginCls.some.unregister()
|
||||
|
||||
def test_configure_classbased(self):
|
||||
|
||||
@scenario.configure(name="fooscenario.name", namespace="testing")
|
||||
class SomeScenario(scenario.Scenario):
|
||||
def run(self):
|
||||
pass
|
||||
|
||||
self.assertEqual("fooscenario.name", SomeScenario.get_name())
|
||||
self.assertTrue(SomeScenario.is_classbased)
|
||||
self.assertEqual("testing", SomeScenario.get_namespace())
|
||||
SomeScenario.unregister()
|
||||
|
||||
|
||||
|
@ -20,20 +20,23 @@ from rally.task import types
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
class TestConvertPlugin(scenario.Scenario):
|
||||
@types.convert(bar={"type": "test_bar"})
|
||||
@scenario.configure()
|
||||
def one_arg(self, bar):
|
||||
@types.convert(bar={"type": "test_bar"})
|
||||
@scenario.configure(name="TestConvertPlugin.one_arg")
|
||||
class TestConvertOneArgPlugin(scenario.Scenario):
|
||||
def run(self, bar):
|
||||
"""Dummy docstring.
|
||||
|
||||
:param bar: dummy parameter
|
||||
"""
|
||||
pass
|
||||
|
||||
@types.convert(bar={"type": "test_bar"},
|
||||
baz={"type": "test_baz"})
|
||||
@scenario.configure()
|
||||
def two_args(self, bar, baz):
|
||||
|
||||
@types.convert(bar={"type": "test_bar"},
|
||||
baz={"type": "test_baz"})
|
||||
@scenario.configure(name="TestConvertPlugin.two_args")
|
||||
class TestConvertTwoArgsPlugin(scenario.Scenario):
|
||||
|
||||
def run(self, bar, baz):
|
||||
"""Dummy docstring.
|
||||
|
||||
:param bar: dummy parameter
|
||||
|
@ -33,22 +33,27 @@ MODULE = "rally.task.validation."
|
||||
|
||||
class ValidationUtilsTestCase(test.TestCase):
|
||||
|
||||
def test_old_validator_admin(self):
|
||||
@plugin.from_func()
|
||||
def scenario():
|
||||
def setUp(self):
|
||||
super(ValidationUtilsTestCase, self).setUp()
|
||||
|
||||
class Plugin(plugin.Plugin):
|
||||
pass
|
||||
|
||||
scenario._meta_init()
|
||||
Plugin._meta_init()
|
||||
self.Plugin = Plugin
|
||||
|
||||
def test_old_validator_admin(self):
|
||||
|
||||
validator_func = mock.Mock()
|
||||
validator_func.return_value = None
|
||||
|
||||
validator = validation.validator(validator_func)
|
||||
|
||||
self.assertEqual(scenario, validator("a", "b", "c", d=1)(scenario))
|
||||
self.assertEqual(1, len(scenario._meta_get("validators")))
|
||||
self.assertEqual(self.Plugin,
|
||||
validator("a", "b", "c", d=1)(self.Plugin))
|
||||
self.assertEqual(1, len(self.Plugin._meta_get("validators")))
|
||||
|
||||
vname, args, kwargs = scenario._meta_get("validators")[0]
|
||||
vname, args, kwargs = self.Plugin._meta_get("validators")[0]
|
||||
validator_cls = common_validation.Validator.get(vname)
|
||||
validator_inst = validator_cls(*args, **kwargs)
|
||||
fake_admin = fakes.fake_credential()
|
||||
@ -64,21 +69,17 @@ class ValidationUtilsTestCase(test.TestCase):
|
||||
deployment.get_credentials_for("openstack"))
|
||||
|
||||
def test_old_validator_users(self):
|
||||
@plugin.from_func()
|
||||
def scenario():
|
||||
pass
|
||||
|
||||
scenario._meta_init()
|
||||
|
||||
validator_func = mock.Mock()
|
||||
validator_func.return_value = None
|
||||
|
||||
validator = validation.validator(validator_func)
|
||||
|
||||
self.assertEqual(scenario, validator("a", "b", "c", d=1)(scenario))
|
||||
self.assertEqual(1, len(scenario._meta_get("validators")))
|
||||
self.assertEqual(self.Plugin,
|
||||
validator("a", "b", "c", d=1)(self.Plugin))
|
||||
self.assertEqual(1, len(self.Plugin._meta_get("validators")))
|
||||
|
||||
vname, args, kwargs = scenario._meta_get("validators")[0]
|
||||
vname, args, kwargs = self.Plugin._meta_get("validators")[0]
|
||||
validator_cls = common_validation.Validator.get(vname)
|
||||
validator_inst = validator_cls(*args, **kwargs)
|
||||
fake_admin = fakes.fake_credential()
|
||||
@ -104,21 +105,17 @@ class ValidationUtilsTestCase(test.TestCase):
|
||||
deployment.get_credentials_for("openstack"))
|
||||
|
||||
def test_old_validator_users_error(self):
|
||||
@plugin.from_func()
|
||||
def scenario():
|
||||
pass
|
||||
|
||||
scenario._meta_init()
|
||||
|
||||
validator_func = mock.Mock()
|
||||
validator_func.return_value = common_validation.ValidationResult(False)
|
||||
|
||||
validator = validation.validator(validator_func)
|
||||
|
||||
self.assertEqual(scenario, validator("a", "b", "c", d=1)(scenario))
|
||||
self.assertEqual(1, len(scenario._meta_get("validators")))
|
||||
self.assertEqual(self.Plugin,
|
||||
validator("a", "b", "c", d=1)(self.Plugin))
|
||||
self.assertEqual(1, len(self.Plugin._meta_get("validators")))
|
||||
|
||||
vname, args, kwargs = scenario._meta_get("validators")[0]
|
||||
vname, args, kwargs = self.Plugin._meta_get("validators")[0]
|
||||
validator_cls = common_validation.Validator.get(vname)
|
||||
validator_inst = validator_cls(*args, **kwargs)
|
||||
fake_admin = fakes.fake_credential()
|
||||
@ -141,22 +138,18 @@ class ValidationUtilsTestCase(test.TestCase):
|
||||
|
||||
@mock.patch("rally.task.validation.LOG.warning")
|
||||
def test_deprecated_validator(self, mock_log_warning):
|
||||
@plugin.from_func()
|
||||
def my_plugin():
|
||||
pass
|
||||
my_plugin._meta_init()
|
||||
my_plugin._meta_set("name", "my_plugin")
|
||||
|
||||
my_deprecated_validator = validation.deprecated_validator(
|
||||
"new_validator", "deprecated_validator", "0.10.0")
|
||||
my_plugin = my_deprecated_validator("foo", bar="baz")(my_plugin)
|
||||
self.Plugin = my_deprecated_validator("foo", bar="baz")(self.Plugin)
|
||||
self.assertEqual([("new_validator", ("foo",), {"bar": "baz"})],
|
||||
my_plugin._meta_get("validators"))
|
||||
self.Plugin._meta_get("validators"))
|
||||
mock_log_warning.assert_called_once_with(
|
||||
"Plugin '%s' uses validator 'rally.task.validation.%s' which is "
|
||||
"deprecated in favor of '%s' (it should be used via new decorator "
|
||||
"'rally.common.validation.add') in Rally v%s.",
|
||||
"my_plugin", "deprecated_validator", "new_validator", "0.10.0")
|
||||
self.Plugin.get_name(), "deprecated_validator", "new_validator",
|
||||
"0.10.0")
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -164,14 +157,13 @@ class ValidatorsTestCase(test.TestCase):
|
||||
|
||||
def _unwrap_validator(self, validator, *args, **kwargs):
|
||||
|
||||
@plugin.from_func()
|
||||
def func():
|
||||
class Plugin(plugin.Plugin):
|
||||
pass
|
||||
|
||||
func._meta_init()
|
||||
validator(*args, **kwargs)(func)
|
||||
Plugin._meta_init()
|
||||
validator(*args, **kwargs)(Plugin)
|
||||
|
||||
fn = func._meta_get("validators")[0][1][0]
|
||||
fn = Plugin._meta_get("validators")[0][1][0]
|
||||
|
||||
def wrap_validator(config, admin_clients, clients):
|
||||
return (fn(config, admin_clients, clients, *args, **kwargs) or
|
||||
|
Loading…
Reference in New Issue
Block a user