diff options
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py')
-rw-r--r-- | azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py b/azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py new file mode 100644 index 0000000..25b4080 --- /dev/null +++ b/azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py @@ -0,0 +1,872 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 datetime import datetime +from contextlib import contextmanager + +import pytest + +from aria import application_model_storage +from aria.storage import ( + sql_mapi, +) +from aria.storage.exceptions import StorageError +from aria.modeling.exceptions import ValueFormatException +from aria.modeling.models import ( + ServiceTemplate, + Service, + ServiceUpdate, + ServiceUpdateStep, + ServiceModification, + Execution, + Task, + Plugin, + Relationship, + NodeTemplate, + Node, + Input, + Output, + Property, + Attribute, + Configuration, + Argument, + Type +) + +from tests import mock +from tests.storage import release_sqlite_storage, init_inmemory_model_storage + + +@contextmanager +def sql_storage(storage_func): + storage = None + try: + storage = storage_func() + yield storage + finally: + if storage: + release_sqlite_storage(storage) + + +def _empty_storage(): + return application_model_storage(sql_mapi.SQLAlchemyModelAPI, + initiator=init_inmemory_model_storage) + + +def _service_template_storage(): + storage = _empty_storage() + service_template = mock.models.create_service_template() + storage.service_template.put(service_template) + return storage + + +def _service_storage(): + storage = _service_template_storage() + service = mock.models.create_service( + storage.service_template.get_by_name(mock.models.SERVICE_TEMPLATE_NAME)) + storage.service.put(service) + return storage + + +def _service_update_storage(): + storage = _service_storage() + service_update = ServiceUpdate( + service=storage.service.list()[0], + created_at=now, + service_plan={}, + ) + storage.service_update.put(service_update) + return storage + + +def _node_template_storage(): + storage = _service_storage() + service_template = storage.service_template.list()[0] + dependency_node_template = mock.models.create_dependency_node_template(service_template) + mock.models.create_dependent_node_template(service_template, dependency_node_template) + storage.service_template.update(service_template) + return storage + + +def _nodes_storage(): + storage = _node_template_storage() + service = storage.service.get_by_name(mock.models.SERVICE_NAME) + dependency_node_template = storage.node_template.get_by_name( + mock.models.DEPENDENCY_NODE_TEMPLATE_NAME) + mock.models.create_node(dependency_node_template, service, + name=mock.models.DEPENDENCY_NODE_NAME) + + dependent_node_template = mock.models.create_dependent_node_template(service.service_template, + dependency_node_template) + + mock.models.create_node(dependent_node_template, service, name=mock.models.DEPENDENT_NODE_NAME) + storage.service.update(service) + return storage + + +def _execution_storage(): + storage = _service_storage() + execution = mock.models.create_execution(storage.service.list()[0]) + plugin = mock.models.create_plugin() + storage.execution.put(execution) + storage.plugin.put(plugin) + return storage + + +@pytest.fixture +def empty_storage(): + with sql_storage(_empty_storage) as storage: + yield storage + + +@pytest.fixture +def service_template_storage(): + with sql_storage(_service_template_storage) as storage: + yield storage + + +@pytest.fixture +def service_storage(): + with sql_storage(_service_storage) as storage: + yield storage + + +@pytest.fixture +def service_update_storage(): + with sql_storage(_service_update_storage) as storage: + yield storage + + +@pytest.fixture +def node_template_storage(): + with sql_storage(_node_template_storage) as storage: + yield storage + + +@pytest.fixture +def nodes_storage(): + with sql_storage(_nodes_storage) as storage: + yield storage + + +@pytest.fixture +def execution_storage(): + with sql_storage(_execution_storage) as storage: + yield storage + + +m_cls = type('MockClass') +now = datetime.utcnow() + + +def _test_model(is_valid, storage, model_cls, model_kwargs): + if is_valid: + model = model_cls(**model_kwargs) + getattr(storage, model_cls.__modelname__).put(model) + return model + else: + with pytest.raises((ValueFormatException, StorageError, TypeError),): + getattr(storage, model_cls.__modelname__).put(model_cls(**model_kwargs)) + + +class TestServiceTemplate(object): + + @pytest.mark.parametrize( + 'is_valid, description, created_at, updated_at, main_file_name', + [ + (False, [], now, now, '/path'), + (False, 'description', 'error', now, '/path'), + (False, 'description', now, 'error', '/path'), + (False, 'description', now, now, {}), + + (True, 'description', now, now, '/path'), + ] + ) + + def test_service_template_model_creation(self, empty_storage, is_valid, description, created_at, + updated_at, main_file_name): + _test_model(is_valid=is_valid, + storage=empty_storage, + model_cls=ServiceTemplate, + model_kwargs=dict( + description=description, + created_at=created_at, + updated_at=updated_at, + main_file_name=main_file_name) + ) + + +class TestService(object): + + @pytest.mark.parametrize( + 'is_valid, name, created_at, description, inputs, ' + 'outputs, updated_at', + [ + (False, m_cls, now, 'desc', {}, {}, now), + (False, 'name', m_cls, 'desc', {}, {}, now), + (False, 'name', now, m_cls, {}, {}, now), + (False, 'name', now, 'desc', m_cls, {}, now), + (False, 'name', now, 'desc', {}, m_cls, now), + (False, 'name', now, 'desc', {}, {}, m_cls), + + (True, 'name', now, 'desc', {}, {}, now), + (True, None, now, 'desc', {}, {}, now), + (True, 'name', now, None, {}, {}, now), + (True, 'name', now, 'desc', {}, {}, None), + (True, 'name', now, 'desc', {}, {}, now), + ] + ) + def test_service_model_creation(self, service_storage, is_valid, name, created_at, description, + inputs, outputs, updated_at): + service = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=Service, + model_kwargs=dict( + name=name, + service_template=service_storage.service_template.list()[0], + created_at=created_at, + description=description, + inputs=inputs, + outputs=outputs, + updated_at=updated_at + )) + if is_valid: + assert service.service_template == \ + service_storage.service_template.list()[0] + + +class TestExecution(object): + + @pytest.mark.parametrize( + 'is_valid, created_at, started_at, ended_at, error, inputs, ' + 'status, workflow_name', + [ + (False, m_cls, now, now, 'error', {}, Execution.STARTED, 'wf_name'), + (False, now, m_cls, now, 'error', {}, Execution.STARTED, 'wf_name'), + (False, now, now, m_cls, 'error', {}, Execution.STARTED, 'wf_name'), + (False, now, now, now, m_cls, {}, Execution.STARTED, 'wf_name'), + (False, now, now, now, 'error', m_cls, Execution.STARTED, 'wf_name'), + (False, now, now, now, 'error', {}, m_cls, 'wf_name'), + (False, now, now, now, 'error', {}, Execution.STARTED, m_cls), + + (True, now, now, now, 'error', {}, Execution.STARTED, 'wf_name'), + (True, now, None, now, 'error', {}, Execution.STARTED, 'wf_name'), + (True, now, now, None, 'error', {}, Execution.STARTED, 'wf_name'), + (True, now, now, now, None, {}, Execution.STARTED, 'wf_name'), + ] + ) + def test_execution_model_creation(self, service_storage, is_valid, created_at, started_at, + ended_at, error, inputs, status, workflow_name): + execution = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=Execution, + model_kwargs=dict( + service=service_storage.service.list()[0], + created_at=created_at, + started_at=started_at, + ended_at=ended_at, + error=error, + inputs=inputs, + status=status, + workflow_name=workflow_name, + )) + if is_valid: + assert execution.service == service_storage.service.list()[0] + assert execution.service_template == service_storage.service_template.list()[0] + + def test_execution_status_transition(self): + def create_execution(status): + execution = Execution( + id='e_id', + workflow_name='w_name', + status=status, + inputs={}, + created_at=now, + ) + return execution + + valid_transitions = { + Execution.PENDING: [Execution.STARTED, + Execution.CANCELLED, + Execution.PENDING], + Execution.STARTED: [Execution.FAILED, + Execution.SUCCEEDED, + Execution.CANCELLED, + Execution.CANCELLING, + Execution.STARTED], + Execution.CANCELLING: [Execution.FAILED, + Execution.SUCCEEDED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.FAILED: [Execution.FAILED], + Execution.SUCCEEDED: [Execution.SUCCEEDED], + Execution.CANCELLED: [Execution.CANCELLED, Execution.PENDING] + } + + invalid_transitions = { + Execution.PENDING: [Execution.FAILED, + Execution.SUCCEEDED, + Execution.CANCELLING], + Execution.STARTED: [Execution.PENDING], + Execution.CANCELLING: [Execution.PENDING, + Execution.STARTED], + Execution.FAILED: [Execution.STARTED, + Execution.SUCCEEDED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.SUCCEEDED: [Execution.PENDING, + Execution.STARTED, + Execution.FAILED, + Execution.CANCELLED, + Execution.CANCELLING], + Execution.CANCELLED: [Execution.STARTED, + Execution.FAILED, + Execution.SUCCEEDED, + Execution.CANCELLING], + } + + for current_status, valid_transitioned_statues in valid_transitions.items(): + for transitioned_status in valid_transitioned_statues: + execution = create_execution(current_status) + execution.status = transitioned_status + + for current_status, invalid_transitioned_statues in invalid_transitions.items(): + for transitioned_status in invalid_transitioned_statues: + execution = create_execution(current_status) + with pytest.raises(ValueError): + execution.status = transitioned_status + + +class TestServiceUpdate(object): + @pytest.mark.parametrize( + 'is_valid, created_at, service_plan, service_update_nodes, ' + 'service_update_service, service_update_node_templates, ' + 'modified_entity_ids, state', + [ + (False, m_cls, {}, {}, {}, [], {}, 'state'), + (False, now, m_cls, {}, {}, [], {}, 'state'), + (False, now, {}, m_cls, {}, [], {}, 'state'), + (False, now, {}, {}, m_cls, [], {}, 'state'), + (False, now, {}, {}, {}, m_cls, {}, 'state'), + (False, now, {}, {}, {}, [], m_cls, 'state'), + (False, now, {}, {}, {}, [], {}, m_cls), + + (True, now, {}, {}, {}, [], {}, 'state'), + (True, now, {}, None, {}, [], {}, 'state'), + (True, now, {}, {}, None, [], {}, 'state'), + (True, now, {}, {}, {}, None, {}, 'state'), + (True, now, {}, {}, {}, [], None, 'state'), + (True, now, {}, {}, {}, [], {}, None), + ] + ) + def test_service_update_model_creation(self, service_storage, is_valid, created_at, + service_plan, service_update_nodes, + service_update_service, service_update_node_templates, + modified_entity_ids, state): + service_update = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=ServiceUpdate, + model_kwargs=dict( + service=service_storage.service.list()[0], + created_at=created_at, + service_plan=service_plan, + service_update_nodes=service_update_nodes, + service_update_service=service_update_service, + service_update_node_templates=service_update_node_templates, + modified_entity_ids=modified_entity_ids, + state=state + )) + if is_valid: + assert service_update.service == \ + service_storage.service.list()[0] + + +class TestServiceUpdateStep(object): + + @pytest.mark.parametrize( + 'is_valid, action, entity_id, entity_type', + [ + (False, m_cls, 'id', ServiceUpdateStep.ENTITY_TYPES.NODE), + (False, ServiceUpdateStep.ACTION_TYPES.ADD, m_cls, + ServiceUpdateStep.ENTITY_TYPES.NODE), + (False, ServiceUpdateStep.ACTION_TYPES.ADD, 'id', m_cls), + + (True, ServiceUpdateStep.ACTION_TYPES.ADD, 'id', + ServiceUpdateStep.ENTITY_TYPES.NODE) + ] + ) + def test_service_update_step_model_creation(self, service_update_storage, is_valid, action, + entity_id, entity_type): + service_update_step = _test_model( + is_valid=is_valid, + storage=service_update_storage, + model_cls=ServiceUpdateStep, + model_kwargs=dict( + service_update= + service_update_storage.service_update.list()[0], + action=action, + entity_id=entity_id, + entity_type=entity_type + )) + if is_valid: + assert service_update_step.service_update == \ + service_update_storage.service_update.list()[0] + + def test_service_update_step_order(self): + add_node = ServiceUpdateStep( + id='add_step', + action='add', + entity_type='node', + entity_id='node_id') + + modify_node = ServiceUpdateStep( + id='modify_step', + action='modify', + entity_type='node', + entity_id='node_id') + + remove_node = ServiceUpdateStep( + id='remove_step', + action='remove', + entity_type='node', + entity_id='node_id') + + for step in (add_node, modify_node, remove_node): + assert hash((step.id, step.entity_id)) == hash(step) + + assert remove_node < modify_node < add_node + assert not remove_node > modify_node > add_node + + add_rel = ServiceUpdateStep( + id='add_step', + action='add', + entity_type='relationship', + entity_id='relationship_id') + + remove_rel = ServiceUpdateStep( + id='remove_step', + action='remove', + entity_type='relationship', + entity_id='relationship_id') + + assert remove_rel < remove_node < add_node < add_rel + assert not add_node < None + + +class TestServiceModification(object): + @pytest.mark.parametrize( + 'is_valid, context, created_at, ended_at, modified_node_templates, nodes, status', + [ + (False, m_cls, now, now, {}, {}, ServiceModification.STARTED), + (False, {}, m_cls, now, {}, {}, ServiceModification.STARTED), + (False, {}, now, m_cls, {}, {}, ServiceModification.STARTED), + (False, {}, now, now, m_cls, {}, ServiceModification.STARTED), + (False, {}, now, now, {}, m_cls, ServiceModification.STARTED), + (False, {}, now, now, {}, {}, m_cls), + + (True, {}, now, now, {}, {}, ServiceModification.STARTED), + (True, {}, now, None, {}, {}, ServiceModification.STARTED), + (True, {}, now, now, None, {}, ServiceModification.STARTED), + (True, {}, now, now, {}, None, ServiceModification.STARTED), + ] + ) + def test_service_modification_model_creation(self, service_storage, is_valid, context, + created_at, ended_at, modified_node_templates, + nodes, status): + service_modification = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=ServiceModification, + model_kwargs=dict( + service=service_storage.service.list()[0], + context=context, + created_at=created_at, + ended_at=ended_at, + modified_node_templates=modified_node_templates, + nodes=nodes, + status=status, + )) + if is_valid: + assert service_modification.service == \ + service_storage.service.list()[0] + + +class TestNodeTemplate(object): + @pytest.mark.parametrize( + 'is_valid, name, properties', + [ + (False, m_cls, {}), + (False, 'name', m_cls), + + (True, 'name', {}), + ] + ) + def test_node_template_model_creation(self, service_storage, is_valid, name, properties): + node_template = _test_model( + is_valid=is_valid, + storage=service_storage, + model_cls=NodeTemplate, + model_kwargs=dict( + name=name, + type=service_storage.type.list()[0], + properties=properties, + service_template=service_storage.service_template.list()[0] + )) + if is_valid: + assert node_template.service_template == \ + service_storage.service_template.list()[0] + + +class TestNode(object): + @pytest.mark.parametrize( + 'is_valid, name, state, version', + [ + (False, m_cls, 'state', 1), + (False, 'name', 'state', 1), + (False, 'name', m_cls, 1), + (False, m_cls, 'state', m_cls), + + (True, 'name', 'initial', 1), + (True, None, 'initial', 1), + (True, 'name', 'initial', 1), + (True, 'name', 'initial', None), + ] + ) + def test_node_model_creation(self, node_template_storage, is_valid, name, state, version): + node = _test_model( + is_valid=is_valid, + storage=node_template_storage, + model_cls=Node, + model_kwargs=dict( + node_template=node_template_storage.node_template.list()[0], + type=node_template_storage.type.list()[0], + name=name, + state=state, + version=version, + service=node_template_storage.service.list()[0] + )) + if is_valid: + assert node.node_template == node_template_storage.node_template.list()[0] + assert node.service == \ + node_template_storage.service.list()[0] + + +class TestNodeHostAddress(object): + + host_address = '1.1.1.1' + + def test_host_address_on_none_hosted_node(self, service_storage): + node_template = self._node_template(service_storage, host_address='not considered') + node = self._node(service_storage, + node_template, + is_host=False, + host_address='not considered') + assert node.host_address is None + + def test_property_host_address_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, host_address=self.host_address) + node = self._node(service_storage, node_template, is_host=True, host_address=None) + assert node.host_address == self.host_address + + def test_runtime_property_host_address_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, host_address='not considered') + node = self._node(service_storage, node_template, is_host=True, + host_address=self.host_address) + assert node.host_address == self.host_address + + def test_no_host_address_configured_on_host_node(self, service_storage): + node_template = self._node_template(service_storage, host_address=None) + node = self._node(service_storage, node_template, is_host=True, host_address=None) + assert node.host_address is None + + def test_runtime_property_on_hosted_node(self, service_storage): + host_node_template = self._node_template(service_storage, host_address=None) + host_node = self._node(service_storage, + host_node_template, + is_host=True, + host_address=self.host_address) + node_template = self._node_template(service_storage, host_address=None) + node = self._node(service_storage, + node_template, + is_host=False, + host_address=None, + host_fk=host_node.id) + assert node.host_address == self.host_address + + def _node_template(self, storage, host_address): + kwargs = dict( + name='node_template', + type=storage.type.list()[0], + service_template=storage.service_template.list()[0] + ) + if host_address: + kwargs['properties'] = {'host_address': Property.wrap('host_address', host_address)} + node = NodeTemplate(**kwargs) + storage.node_template.put(node) + return node + + def _node(self, storage, node_template, is_host, host_address, host_fk=None): + kwargs = dict( + name='node', + node_template=node_template, + type=storage.type.list()[0], + state='initial', + service=storage.service.list()[0] + ) + if is_host and (host_address is None): + host_address = node_template.properties.get('host_address') + if host_address is not None: + host_address = host_address.value + if host_address: + kwargs.setdefault('attributes', {})['ip'] = Attribute.wrap('ip', host_address) + if is_host: + kwargs['host_fk'] = 1 + elif host_fk: + kwargs['host_fk'] = host_fk + node = Node(**kwargs) + storage.node.put(node) + return node + + +class TestRelationship(object): + @pytest.mark.parametrize( + 'is_valid, source_position, target_position', + [ + (False, m_cls, 0), + (False, 0, m_cls), + + (True, 0, 0), + (True, None, 0), + (True, 0, None), + ] + ) + def test_relationship_model_creation(self, nodes_storage, is_valid, source_position, + target_position): + nodes = nodes_storage.node + source_node = nodes.get_by_name(mock.models.DEPENDENT_NODE_NAME) + target_node = nodes.get_by_name(mock.models.DEPENDENCY_NODE_NAME) + _test_model(is_valid=is_valid, + storage=nodes_storage, + model_cls=Relationship, + model_kwargs=dict( + source_node=source_node, + target_node=target_node, + source_position=source_position, + target_position=target_position + )) + + +class TestPlugin(object): + @pytest.mark.parametrize( + 'is_valid, archive_name, distribution, distribution_release, ' + 'distribution_version, package_name, package_source, ' + 'package_version, supported_platform, supported_py_versions, uploaded_at, wheels', + [ + (False, m_cls, 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', m_cls, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', m_cls, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', m_cls, 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', m_cls, 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', m_cls, 'pak_ver', + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', m_cls, + 'sup_plat', [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', m_cls, [], now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', m_cls, now, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], m_cls, []), + (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, m_cls), + + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', None, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', None, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', None, 'pak_name', 'pak_src', 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', None, 'pak_ver', + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', None, + 'sup_plat', [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', None, [], now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', None, now, []), + (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', + 'pak_ver', 'sup_plat', [], now, []), + ] + ) + def test_plugin_model_creation(self, empty_storage, is_valid, archive_name, distribution, + distribution_release, distribution_version, package_name, + package_source, package_version, supported_platform, + supported_py_versions, uploaded_at, wheels): + _test_model(is_valid=is_valid, + storage=empty_storage, + model_cls=Plugin, + model_kwargs=dict( + archive_name=archive_name, + distribution=distribution, + distribution_release=distribution_release, + distribution_version=distribution_version, + package_name=package_name, + package_source=package_source, + package_version=package_version, + supported_platform=supported_platform, + supported_py_versions=supported_py_versions, + uploaded_at=uploaded_at, + wheels=wheels, + )) + + +class TestTask(object): + + @pytest.mark.parametrize( + 'is_valid, status, due_at, started_at, ended_at, max_attempts, attempts_count, ' + 'retry_interval, ignore_failure, name, operation_mapping, arguments, plugin_id', + [ + (False, m_cls, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, m_cls, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, m_cls, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, m_cls, 1, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, m_cls, 1, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, m_cls, 1, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, m_cls, True, 'name', 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, m_cls, 'map', {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', m_cls, {}, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', m_cls, '1'), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, m_cls), + (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', None, '1'), + + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, None, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, None, now, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, None, 1, 1, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, None, 1, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, None, True, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, None, 'name', 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, None, 'map', {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', None, {}, '1'), + (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, None), + ] + ) + def test_task_model_creation(self, execution_storage, is_valid, status, due_at, started_at, + ended_at, max_attempts, attempts_count, retry_interval, + ignore_failure, name, operation_mapping, arguments, plugin_id): + task = _test_model( + is_valid=is_valid, + storage=execution_storage, + model_cls=Task, + model_kwargs=dict( + status=status, + execution=execution_storage.execution.list()[0], + due_at=due_at, + started_at=started_at, + ended_at=ended_at, + max_attempts=max_attempts, + attempts_count=attempts_count, + retry_interval=retry_interval, + ignore_failure=ignore_failure, + name=name, + function=operation_mapping, + arguments=arguments, + plugin_fk=plugin_id, + )) + if is_valid: + assert task.execution == execution_storage.execution.list()[0] + if task.plugin: + assert task.plugin == execution_storage.plugin.list()[0] + + def test_task_max_attempts_validation(self): + def create_task(max_attempts): + Task(execution_fk='eid', + name='name', + function='', + arguments={}, + max_attempts=max_attempts) + create_task(max_attempts=1) + create_task(max_attempts=2) + create_task(max_attempts=Task.INFINITE_RETRIES) + with pytest.raises(ValueError): + create_task(max_attempts=0) + with pytest.raises(ValueError): + create_task(max_attempts=-2) + + +class TestType(object): + def test_type_hierarchy(self): + super_type = Type(variant='variant', name='super') + sub_type = Type(variant='variant', parent=super_type, name='sub') + additional_type = Type(variant='variant', name='non_related') + + assert super_type.hierarchy == [super_type] + assert sub_type.hierarchy == [sub_type, super_type] + assert additional_type.hierarchy == [additional_type] + + super_type.parent = additional_type + + assert super_type.hierarchy == [super_type, additional_type] + assert sub_type.hierarchy == [sub_type, super_type, additional_type] + + +class TestParameter(object): + + MODELS_DERIVED_FROM_PARAMETER = (Input, Output, Property, Attribute, Configuration, Argument) + + @pytest.mark.parametrize( + 'is_valid, name, type_name, description', + [ + (False, 'name', 'int', []), + (False, 'name', [], 'desc'), + (False, [], 'type_name', 'desc'), + (True, 'name', 'type_name', 'desc'), + ] + ) + def test_derived_from_parameter_model_creation(self, empty_storage, is_valid, name, type_name, + description): + + for model_cls in self.MODELS_DERIVED_FROM_PARAMETER: + _test_model(is_valid=is_valid, + storage=empty_storage, + model_cls=model_cls, + model_kwargs=dict( + name=name, + type_name=type_name, + description=description, + _value={}) + ) + + def test_as_argument(self): + + for model_cls in self.MODELS_DERIVED_FROM_PARAMETER: + model = model_cls(name='name', + type_name='type_name', + description='description', + _value={}) + argument = model.as_argument() + assert isinstance(argument, Argument) |