diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index 2527cd90d1..645141e549 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -15,10 +15,6 @@ import itertools import multiprocessing -import random -import re -import string -import uuid import mock @@ -29,143 +25,6 @@ from rally.task import context from rally.task import scenario -def generate_uuid(): - return str(uuid.uuid4()) - - -def generate_name(prefix="", length=12, choices=string.ascii_lowercase): - """Generate pseudo-random name. - - :param prefix: str, custom prefix for genertated name - :param length: int, length of autogenerated part of result name - :param choices: str, chars that accurs in generated name - :returns: str, pseudo-random name - """ - return prefix + "".join(random.choice(choices) for i in range(length)) - - -def generate_mac(): - """Generate pseudo-random MAC address. - - :returns: str, MAC address - """ - rand_str = generate_name(choices="0123456789abcdef", length=12) - return ":".join(re.findall("..", rand_str)) - - -def setup_dict(data, required=None, defaults=None): - """Setup and validate dict scenario_base. on mandatory keys and default data. - - This function reduces code that constructs dict objects - with specific schema (e.g. for API data). - - :param data: dict, input data - :param required: list, mandatory keys to check - :param defaults: dict, default data - :returns: dict, with all keys set - :raises IndexError, ValueError: If input data is incorrect - """ - required = required or [] - for i in set(required) - set(data): - raise IndexError("Missed: %s" % i) - - defaults = defaults or {} - for i in set(data) - set(required) - set(defaults): - raise ValueError("Unexpected: %s" % i) - - defaults.update(data) - return defaults - - -def fake_credential(**config): - m = mock.Mock() - m.to_dict.return_value = config - for key, value in config.items(): - setattr(m, key, value) - return m - - -class FakeResource(object): - - def __init__(self, manager=None, name=None, status="ACTIVE", items=None, - deployment_uuid=None, id=None): - self.name = name or generate_uuid() - self.status = status - self.manager = manager - self.uuid = generate_uuid() - self.id = id or self.uuid - self.items = items or {} - self.deployment_uuid = deployment_uuid or generate_uuid() - - def __getattr__(self, name): - # NOTE(msdubov): e.g. server.delete() -> manager.delete(server) - def manager_func(*args, **kwargs): - return getattr(self.manager, name)(self, *args, **kwargs) - return manager_func - - def __getitem__(self, key): - return self.items[key] - - -class FakeManager(object): - - def __init__(self): - super(FakeManager, self).__init__() - self.cache = {} - self.resources_order = [] - - def get(self, resource_uuid): - return self.cache.get(resource_uuid) - - def delete(self, resource_uuid): - cached = self.get(resource_uuid) - if cached is not None: - cached.status = "DELETED" - del self.cache[resource_uuid] - self.resources_order.remove(resource_uuid) - - def _cache(self, resource): - self.resources_order.append(resource.uuid) - self.cache[resource.uuid] = resource - return resource - - def list(self, **kwargs): - return [self.cache[key] for key in self.resources_order] - - def find(self, **kwargs): - for resource in self.cache.values(): - match = True - for key, value in kwargs.items(): - if getattr(resource, key, None) != value: - match = False - break - if match: - return resource - - -class FakeRunner(object): - - CONFIG_SCHEMA = { - "type": "object", - "$schema": consts.JSON_SCHEMA, - "properties": { - "type": { - "type": "string", - "enum": ["fake"] - }, - - "a": { - "type": "string" - }, - - "b": { - "type": "number" - } - }, - "required": ["type", "a"] - } - - class FakeScenario(scenario.Scenario): def idle_time(self): @@ -245,11 +104,6 @@ class FakeContext(context.Context): pass -@context.configure(name="fake_hidden_context", order=1, hidden=True) -class FakeHiddenContext(FakeContext): - pass - - class FakeDeployment(dict): def __init__(self, **kwargs): diff --git a/tests/unit/task/test_utils.py b/tests/unit/task/test_utils.py index 22671f2306..adf29e5188 100644 --- a/tests/unit/task/test_utils.py +++ b/tests/unit/task/test_utils.py @@ -15,6 +15,7 @@ import collections import datetime as dt +import uuid import ddt from jsonschema import exceptions as schema_exceptions @@ -22,10 +23,67 @@ import mock from rally import exceptions from rally.task import utils -from tests.unit import fakes from tests.unit import test +class FakeResource(object): + + def __init__(self, manager=None, name=None, status="ACTIVE", items=None, + deployment_uuid=None, id=None): + self.name = name or str(uuid.uuid4()) + self.status = status + self.manager = manager + self.uuid = str(uuid.uuid4()) + self.id = id or self.uuid + self.items = items or {} + self.deployment_uuid = deployment_uuid or str(uuid.uuid4()) + + def __getattr__(self, name): + # NOTE(msdubov): e.g. server.delete() -> manager.delete(server) + def manager_func(*args, **kwargs): + return getattr(self.manager, name)(self, *args, **kwargs) + return manager_func + + def __getitem__(self, key): + return self.items[key] + + +class FakeManager(object): + + def __init__(self): + super(FakeManager, self).__init__() + self.cache = {} + self.resources_order = [] + + def get(self, resource_uuid): + return self.cache.get(resource_uuid) + + def delete(self, resource_uuid): + cached = self.get(resource_uuid) + if cached is not None: + cached.status = "DELETED" + del self.cache[resource_uuid] + self.resources_order.remove(resource_uuid) + + def _cache(self, resource): + self.resources_order.append(resource.uuid) + self.cache[resource.uuid] = resource + return resource + + def list(self, **kwargs): + return [self.cache[key] for key in self.resources_order] + + def find(self, **kwargs): + for resource in self.cache.values(): + match = True + for key, value in kwargs.items(): + if getattr(resource, key, None) != value: + match = False + break + if match: + return resource + + class TaskUtilsTestCase(test.TestCase): def test_wait_for_delete(self): @@ -50,9 +108,9 @@ class TaskUtilsTestCase(test.TestCase): def test_resource_is(self): is_active = utils.resource_is("ACTIVE") self.assertEqual(is_active.status_getter, utils.get_status) - self.assertTrue(is_active(fakes.FakeResource(status="active"))) - self.assertTrue(is_active(fakes.FakeResource(status="aCtIvE"))) - self.assertFalse(is_active(fakes.FakeResource(status="ERROR"))) + self.assertTrue(is_active(FakeResource(status="active"))) + self.assertTrue(is_active(FakeResource(status="aCtIvE"))) + self.assertFalse(is_active(FakeResource(status="ERROR"))) def test_resource_is_with_fake_status_getter(self): fake_getter = mock.MagicMock(return_value="LGTM") @@ -69,7 +127,7 @@ class TaskUtilsTestCase(test.TestCase): break def test_manager_list_sizes(self): - manager = fakes.FakeManager() + manager = FakeManager() def lst(): return [1] * 10 @@ -83,38 +141,38 @@ class TaskUtilsTestCase(test.TestCase): def test_get_from_manager(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager) + manager = FakeManager() + resource = FakeResource(manager=manager) manager._cache(resource) self.assertEqual(resource, get_from_manager(resource)) def test_get_from_manager_with_uuid_field(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager) + manager = FakeManager() + resource = FakeResource(manager=manager) manager._cache(resource) self.assertEqual(resource, get_from_manager(resource, id_attr="uuid")) def test_get_from_manager_in_error_state(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager, status="ERROR") + manager = FakeManager() + resource = FakeResource(manager=manager, status="ERROR") manager._cache(resource) self.assertRaises(exceptions.GetResourceFailure, get_from_manager, resource) def test_get_from_manager_in_deleted_state(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager, status="DELETED") + manager = FakeManager() + resource = FakeResource(manager=manager, status="DELETED") manager._cache(resource) self.assertRaises(exceptions.GetResourceNotFound, get_from_manager, resource) def test_get_from_manager_in_deleted_state_for_heat_resource(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager) + manager = FakeManager() + resource = FakeResource(manager=manager) resource.stack_status = "DELETE_COMPLETE" manager._cache(resource) self.assertRaises(exceptions.GetResourceNotFound, @@ -122,8 +180,8 @@ class TaskUtilsTestCase(test.TestCase): def test_get_from_manager_in_deleted_state_for_ceilometer_resource(self): get_from_manager = utils.get_from_manager() - manager = fakes.FakeManager() - resource = fakes.FakeResource(manager=manager) + manager = FakeManager() + resource = FakeResource(manager=manager) resource.state = "DELETED" manager._cache(resource) self.assertRaises(exceptions.GetResourceNotFound, @@ -132,7 +190,7 @@ class TaskUtilsTestCase(test.TestCase): def test_get_from_manager_not_found(self): get_from_manager = utils.get_from_manager() manager = mock.MagicMock() - resource = fakes.FakeResource(manager=manager, status="ERROR") + resource = FakeResource(manager=manager, status="ERROR") class NotFoundException(Exception): http_status = 404 @@ -144,7 +202,7 @@ class TaskUtilsTestCase(test.TestCase): def test_get_from_manager_http_exception(self): get_from_manager = utils.get_from_manager() manager = mock.MagicMock() - resource = fakes.FakeResource(manager=manager, status="ERROR") + resource = FakeResource(manager=manager, status="ERROR") class HTTPException(Exception): pass @@ -159,7 +217,7 @@ class WaitForTestCase(test.TestCase): def setUp(self): super(WaitForTestCase, self).setUp() - self.resource = fakes.FakeResource() + self.resource = FakeResource() self.load_secs = 0.01 self.fake_checker_delayed = self.get_fake_checker_delayed( seconds=self.load_secs) diff --git a/tests/unit/test.py b/tests/unit/test.py index 62d5e5c0cc..ac2ae7318c 100644 --- a/tests/unit/test.py +++ b/tests/unit/test.py @@ -24,7 +24,6 @@ import testtools from rally.common import cfg from rally.common import db from rally import plugins -from tests.unit import fakes class TempHomeDir(TempDir): @@ -117,147 +116,6 @@ class DBTestCase(TestCase): self.useFixture(DatabaseFixture()) -# TODO(boris-42): This should be moved to test.plugins.test module -# or similar - -class ScenarioTestCase(TestCase): - """Base class for Scenario tests using mocked self.clients.""" - task_utils = "rally.task.utils" - patch_task_utils = True - - def client_factory(self, client_type, version=None, admin=False): - """Create a new client object.""" - return mock.MagicMock(client_type=client_type, - version=version, - admin=admin) - - def clients(self, client_type, version=None, admin=False): - """Get a mocked client.""" - key = (client_type, version, admin) - if key not in self._clients: - self._clients[key] = self.client_factory(client_type, - version=version, - admin=admin) - return self._clients[key] - - def admin_clients(self, client_type, version=None): - """Get a mocked admin client.""" - return self.clients(client_type, version=version, admin=True) - - def client_created(self, client_type, version=None, admin=False): - """Determine if a client has been created. - - This can be used to see if a scenario calls - 'self.clients("foo")', without checking to see what was done - with the client object returned by that call. - """ - key = (client_type, version, admin) - return key in self._clients - - def get_client_mocks(self): - base_path = "rally.plugins.openstack" - - return [ - mock.patch( - "%s.scenario.OpenStackScenario.clients" % base_path, - mock.Mock(side_effect=self.clients)), - mock.patch( - "%s.scenario.OpenStackScenario.admin_clients" % base_path, - mock.Mock(side_effect=self.admin_clients)) - ] - - def get_test_context(self): - return get_test_context() - - def setUp(self): - super(ScenarioTestCase, self).setUp() - if self.patch_task_utils: - self.mock_resource_is = fixtures.MockPatch( - self.task_utils + ".resource_is") - self.mock_get_from_manager = fixtures.MockPatch( - self.task_utils + ".get_from_manager") - self.mock_wait_for = fixtures.MockPatch( - self.task_utils + ".wait_for") - self.mock_wait_for_delete = fixtures.MockPatch( - self.task_utils + ".wait_for_delete") - self.mock_wait_for_status = fixtures.MockPatch( - self.task_utils + ".wait_for_status") - self.useFixture(self.mock_resource_is) - self.useFixture(self.mock_get_from_manager) - self.useFixture(self.mock_wait_for) - self.useFixture(self.mock_wait_for_delete) - self.useFixture(self.mock_wait_for_status) - - self.mock_sleep = fixtures.MockPatch("time.sleep") - self.useFixture(self.mock_sleep) - - self._clients = {} - self._client_mocks = self.get_client_mocks() - - for patcher in self._client_mocks: - patcher.start() - - self.context = self.get_test_context() - - def tearDown(self): - for patcher in self._client_mocks: - patcher.stop() - super(ScenarioTestCase, self).tearDown() - - -class ContextClientAdapter(object): - def __init__(self, endpoint, test_case): - self.endpoint = endpoint - self.test_case = test_case - - def mock_client(self, name, version=None): - admin = self.endpoint.startswith("admin") - client = self.test_case.clients(name, version=version, admin=admin) - if not isinstance(client.return_value, mock.Mock): - return client.return_value - if client.side_effect is not None: - # NOTE(pboldin): if a client has side_effects that means the - # user wants some of the returned values overrided (look at - # the test_existing_users for instance) - return client() - return client - - def __getattr__(self, name): - # NOTE(pboldin): __getattr__ magic is called last, after the value - # were looked up for in __dict__ - return lambda version=None: self.mock_client(name, version) - - -class ContextTestCase(ScenarioTestCase): - def setUp(self): - super(ContextTestCase, self).setUp() - - self._adapters = {} - - def context_client(self, endpoint, api_info=None): - if endpoint not in self._adapters: - self._adapters[endpoint] = ContextClientAdapter(endpoint, self) - return self._adapters[endpoint] - - def get_client_mocks(self): - return [ - mock.patch( - "rally.plugins.openstack.osclients.Clients", - mock.Mock(side_effect=self.context_client)) - ] - - -class FakeClientsScenarioTestCase(ScenarioTestCase): - """Base class for Scenario tests using fake (not mocked) self.clients.""" - - def client_factory(self, client_type, version=None, admin=False): - return getattr(self._fake_clients, client_type)() - - def setUp(self): - super(FakeClientsScenarioTestCase, self).setUp() - self._fake_clients = fakes.FakeClients() - - def get_test_context(**kwargs): kwargs["task"] = {"uuid": str(uuid.uuid4())} kwargs["owner_id"] = str(uuid.uuid4())