summaryrefslogtreecommitdiffstats
path: root/azure/aria/aria-extension-cloudify/src/aria/tests/modeling/test_models.py
diff options
context:
space:
mode:
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.py872
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)