1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 from datetime import datetime
17 from contextlib import contextmanager
21 from aria import application_model_storage
22 from aria.storage import (
25 from aria.storage.exceptions import StorageError
26 from aria.modeling.exceptions import ValueFormatException
27 from aria.modeling.models import (
48 from tests import mock
49 from tests.storage import release_sqlite_storage, init_inmemory_model_storage
53 def sql_storage(storage_func):
56 storage = storage_func()
60 release_sqlite_storage(storage)
64 return application_model_storage(sql_mapi.SQLAlchemyModelAPI,
65 initiator=init_inmemory_model_storage)
68 def _service_template_storage():
69 storage = _empty_storage()
70 service_template = mock.models.create_service_template()
71 storage.service_template.put(service_template)
75 def _service_storage():
76 storage = _service_template_storage()
77 service = mock.models.create_service(
78 storage.service_template.get_by_name(mock.models.SERVICE_TEMPLATE_NAME))
79 storage.service.put(service)
83 def _service_update_storage():
84 storage = _service_storage()
85 service_update = ServiceUpdate(
86 service=storage.service.list()[0],
90 storage.service_update.put(service_update)
94 def _node_template_storage():
95 storage = _service_storage()
96 service_template = storage.service_template.list()[0]
97 dependency_node_template = mock.models.create_dependency_node_template(service_template)
98 mock.models.create_dependent_node_template(service_template, dependency_node_template)
99 storage.service_template.update(service_template)
103 def _nodes_storage():
104 storage = _node_template_storage()
105 service = storage.service.get_by_name(mock.models.SERVICE_NAME)
106 dependency_node_template = storage.node_template.get_by_name(
107 mock.models.DEPENDENCY_NODE_TEMPLATE_NAME)
108 mock.models.create_node(dependency_node_template, service,
109 name=mock.models.DEPENDENCY_NODE_NAME)
111 dependent_node_template = mock.models.create_dependent_node_template(service.service_template,
112 dependency_node_template)
114 mock.models.create_node(dependent_node_template, service, name=mock.models.DEPENDENT_NODE_NAME)
115 storage.service.update(service)
119 def _execution_storage():
120 storage = _service_storage()
121 execution = mock.models.create_execution(storage.service.list()[0])
122 plugin = mock.models.create_plugin()
123 storage.execution.put(execution)
124 storage.plugin.put(plugin)
130 with sql_storage(_empty_storage) as storage:
135 def service_template_storage():
136 with sql_storage(_service_template_storage) as storage:
141 def service_storage():
142 with sql_storage(_service_storage) as storage:
147 def service_update_storage():
148 with sql_storage(_service_update_storage) as storage:
153 def node_template_storage():
154 with sql_storage(_node_template_storage) as storage:
160 with sql_storage(_nodes_storage) as storage:
165 def execution_storage():
166 with sql_storage(_execution_storage) as storage:
170 m_cls = type('MockClass')
171 now = datetime.utcnow()
174 def _test_model(is_valid, storage, model_cls, model_kwargs):
176 model = model_cls(**model_kwargs)
177 getattr(storage, model_cls.__modelname__).put(model)
180 with pytest.raises((ValueFormatException, StorageError, TypeError),):
181 getattr(storage, model_cls.__modelname__).put(model_cls(**model_kwargs))
184 class TestServiceTemplate(object):
186 @pytest.mark.parametrize(
187 'is_valid, description, created_at, updated_at, main_file_name',
189 (False, [], now, now, '/path'),
190 (False, 'description', 'error', now, '/path'),
191 (False, 'description', now, 'error', '/path'),
192 (False, 'description', now, now, {}),
194 (True, 'description', now, now, '/path'),
198 def test_service_template_model_creation(self, empty_storage, is_valid, description, created_at,
199 updated_at, main_file_name):
200 _test_model(is_valid=is_valid,
201 storage=empty_storage,
202 model_cls=ServiceTemplate,
204 description=description,
205 created_at=created_at,
206 updated_at=updated_at,
207 main_file_name=main_file_name)
211 class TestService(object):
213 @pytest.mark.parametrize(
214 'is_valid, name, created_at, description, inputs, '
215 'outputs, updated_at',
217 (False, m_cls, now, 'desc', {}, {}, now),
218 (False, 'name', m_cls, 'desc', {}, {}, now),
219 (False, 'name', now, m_cls, {}, {}, now),
220 (False, 'name', now, 'desc', m_cls, {}, now),
221 (False, 'name', now, 'desc', {}, m_cls, now),
222 (False, 'name', now, 'desc', {}, {}, m_cls),
224 (True, 'name', now, 'desc', {}, {}, now),
225 (True, None, now, 'desc', {}, {}, now),
226 (True, 'name', now, None, {}, {}, now),
227 (True, 'name', now, 'desc', {}, {}, None),
228 (True, 'name', now, 'desc', {}, {}, now),
231 def test_service_model_creation(self, service_storage, is_valid, name, created_at, description,
232 inputs, outputs, updated_at):
233 service = _test_model(
235 storage=service_storage,
239 service_template=service_storage.service_template.list()[0],
240 created_at=created_at,
241 description=description,
244 updated_at=updated_at
247 assert service.service_template == \
248 service_storage.service_template.list()[0]
251 class TestExecution(object):
253 @pytest.mark.parametrize(
254 'is_valid, created_at, started_at, ended_at, error, inputs, '
255 'status, workflow_name',
257 (False, m_cls, now, now, 'error', {}, Execution.STARTED, 'wf_name'),
258 (False, now, m_cls, now, 'error', {}, Execution.STARTED, 'wf_name'),
259 (False, now, now, m_cls, 'error', {}, Execution.STARTED, 'wf_name'),
260 (False, now, now, now, m_cls, {}, Execution.STARTED, 'wf_name'),
261 (False, now, now, now, 'error', m_cls, Execution.STARTED, 'wf_name'),
262 (False, now, now, now, 'error', {}, m_cls, 'wf_name'),
263 (False, now, now, now, 'error', {}, Execution.STARTED, m_cls),
265 (True, now, now, now, 'error', {}, Execution.STARTED, 'wf_name'),
266 (True, now, None, now, 'error', {}, Execution.STARTED, 'wf_name'),
267 (True, now, now, None, 'error', {}, Execution.STARTED, 'wf_name'),
268 (True, now, now, now, None, {}, Execution.STARTED, 'wf_name'),
271 def test_execution_model_creation(self, service_storage, is_valid, created_at, started_at,
272 ended_at, error, inputs, status, workflow_name):
273 execution = _test_model(
275 storage=service_storage,
278 service=service_storage.service.list()[0],
279 created_at=created_at,
280 started_at=started_at,
285 workflow_name=workflow_name,
288 assert execution.service == service_storage.service.list()[0]
289 assert execution.service_template == service_storage.service_template.list()[0]
291 def test_execution_status_transition(self):
292 def create_execution(status):
293 execution = Execution(
295 workflow_name='w_name',
302 valid_transitions = {
303 Execution.PENDING: [Execution.STARTED,
306 Execution.STARTED: [Execution.FAILED,
309 Execution.CANCELLING,
311 Execution.CANCELLING: [Execution.FAILED,
314 Execution.CANCELLING],
315 Execution.FAILED: [Execution.FAILED],
316 Execution.SUCCEEDED: [Execution.SUCCEEDED],
317 Execution.CANCELLED: [Execution.CANCELLED, Execution.PENDING]
320 invalid_transitions = {
321 Execution.PENDING: [Execution.FAILED,
323 Execution.CANCELLING],
324 Execution.STARTED: [Execution.PENDING],
325 Execution.CANCELLING: [Execution.PENDING,
327 Execution.FAILED: [Execution.STARTED,
330 Execution.CANCELLING],
331 Execution.SUCCEEDED: [Execution.PENDING,
335 Execution.CANCELLING],
336 Execution.CANCELLED: [Execution.STARTED,
339 Execution.CANCELLING],
342 for current_status, valid_transitioned_statues in valid_transitions.items():
343 for transitioned_status in valid_transitioned_statues:
344 execution = create_execution(current_status)
345 execution.status = transitioned_status
347 for current_status, invalid_transitioned_statues in invalid_transitions.items():
348 for transitioned_status in invalid_transitioned_statues:
349 execution = create_execution(current_status)
350 with pytest.raises(ValueError):
351 execution.status = transitioned_status
354 class TestServiceUpdate(object):
355 @pytest.mark.parametrize(
356 'is_valid, created_at, service_plan, service_update_nodes, '
357 'service_update_service, service_update_node_templates, '
358 'modified_entity_ids, state',
360 (False, m_cls, {}, {}, {}, [], {}, 'state'),
361 (False, now, m_cls, {}, {}, [], {}, 'state'),
362 (False, now, {}, m_cls, {}, [], {}, 'state'),
363 (False, now, {}, {}, m_cls, [], {}, 'state'),
364 (False, now, {}, {}, {}, m_cls, {}, 'state'),
365 (False, now, {}, {}, {}, [], m_cls, 'state'),
366 (False, now, {}, {}, {}, [], {}, m_cls),
368 (True, now, {}, {}, {}, [], {}, 'state'),
369 (True, now, {}, None, {}, [], {}, 'state'),
370 (True, now, {}, {}, None, [], {}, 'state'),
371 (True, now, {}, {}, {}, None, {}, 'state'),
372 (True, now, {}, {}, {}, [], None, 'state'),
373 (True, now, {}, {}, {}, [], {}, None),
376 def test_service_update_model_creation(self, service_storage, is_valid, created_at,
377 service_plan, service_update_nodes,
378 service_update_service, service_update_node_templates,
379 modified_entity_ids, state):
380 service_update = _test_model(
382 storage=service_storage,
383 model_cls=ServiceUpdate,
385 service=service_storage.service.list()[0],
386 created_at=created_at,
387 service_plan=service_plan,
388 service_update_nodes=service_update_nodes,
389 service_update_service=service_update_service,
390 service_update_node_templates=service_update_node_templates,
391 modified_entity_ids=modified_entity_ids,
395 assert service_update.service == \
396 service_storage.service.list()[0]
399 class TestServiceUpdateStep(object):
401 @pytest.mark.parametrize(
402 'is_valid, action, entity_id, entity_type',
404 (False, m_cls, 'id', ServiceUpdateStep.ENTITY_TYPES.NODE),
405 (False, ServiceUpdateStep.ACTION_TYPES.ADD, m_cls,
406 ServiceUpdateStep.ENTITY_TYPES.NODE),
407 (False, ServiceUpdateStep.ACTION_TYPES.ADD, 'id', m_cls),
409 (True, ServiceUpdateStep.ACTION_TYPES.ADD, 'id',
410 ServiceUpdateStep.ENTITY_TYPES.NODE)
413 def test_service_update_step_model_creation(self, service_update_storage, is_valid, action,
414 entity_id, entity_type):
415 service_update_step = _test_model(
417 storage=service_update_storage,
418 model_cls=ServiceUpdateStep,
421 service_update_storage.service_update.list()[0],
424 entity_type=entity_type
427 assert service_update_step.service_update == \
428 service_update_storage.service_update.list()[0]
430 def test_service_update_step_order(self):
431 add_node = ServiceUpdateStep(
437 modify_node = ServiceUpdateStep(
443 remove_node = ServiceUpdateStep(
449 for step in (add_node, modify_node, remove_node):
450 assert hash((step.id, step.entity_id)) == hash(step)
452 assert remove_node < modify_node < add_node
453 assert not remove_node > modify_node > add_node
455 add_rel = ServiceUpdateStep(
458 entity_type='relationship',
459 entity_id='relationship_id')
461 remove_rel = ServiceUpdateStep(
464 entity_type='relationship',
465 entity_id='relationship_id')
467 assert remove_rel < remove_node < add_node < add_rel
468 assert not add_node < None
471 class TestServiceModification(object):
472 @pytest.mark.parametrize(
473 'is_valid, context, created_at, ended_at, modified_node_templates, nodes, status',
475 (False, m_cls, now, now, {}, {}, ServiceModification.STARTED),
476 (False, {}, m_cls, now, {}, {}, ServiceModification.STARTED),
477 (False, {}, now, m_cls, {}, {}, ServiceModification.STARTED),
478 (False, {}, now, now, m_cls, {}, ServiceModification.STARTED),
479 (False, {}, now, now, {}, m_cls, ServiceModification.STARTED),
480 (False, {}, now, now, {}, {}, m_cls),
482 (True, {}, now, now, {}, {}, ServiceModification.STARTED),
483 (True, {}, now, None, {}, {}, ServiceModification.STARTED),
484 (True, {}, now, now, None, {}, ServiceModification.STARTED),
485 (True, {}, now, now, {}, None, ServiceModification.STARTED),
488 def test_service_modification_model_creation(self, service_storage, is_valid, context,
489 created_at, ended_at, modified_node_templates,
491 service_modification = _test_model(
493 storage=service_storage,
494 model_cls=ServiceModification,
496 service=service_storage.service.list()[0],
498 created_at=created_at,
500 modified_node_templates=modified_node_templates,
505 assert service_modification.service == \
506 service_storage.service.list()[0]
509 class TestNodeTemplate(object):
510 @pytest.mark.parametrize(
511 'is_valid, name, properties',
514 (False, 'name', m_cls),
519 def test_node_template_model_creation(self, service_storage, is_valid, name, properties):
520 node_template = _test_model(
522 storage=service_storage,
523 model_cls=NodeTemplate,
526 type=service_storage.type.list()[0],
527 properties=properties,
528 service_template=service_storage.service_template.list()[0]
531 assert node_template.service_template == \
532 service_storage.service_template.list()[0]
535 class TestNode(object):
536 @pytest.mark.parametrize(
537 'is_valid, name, state, version',
539 (False, m_cls, 'state', 1),
540 (False, 'name', 'state', 1),
541 (False, 'name', m_cls, 1),
542 (False, m_cls, 'state', m_cls),
544 (True, 'name', 'initial', 1),
545 (True, None, 'initial', 1),
546 (True, 'name', 'initial', 1),
547 (True, 'name', 'initial', None),
550 def test_node_model_creation(self, node_template_storage, is_valid, name, state, version):
553 storage=node_template_storage,
556 node_template=node_template_storage.node_template.list()[0],
557 type=node_template_storage.type.list()[0],
561 service=node_template_storage.service.list()[0]
564 assert node.node_template == node_template_storage.node_template.list()[0]
565 assert node.service == \
566 node_template_storage.service.list()[0]
569 class TestNodeHostAddress(object):
571 host_address = '1.1.1.1'
573 def test_host_address_on_none_hosted_node(self, service_storage):
574 node_template = self._node_template(service_storage, host_address='not considered')
575 node = self._node(service_storage,
578 host_address='not considered')
579 assert node.host_address is None
581 def test_property_host_address_on_host_node(self, service_storage):
582 node_template = self._node_template(service_storage, host_address=self.host_address)
583 node = self._node(service_storage, node_template, is_host=True, host_address=None)
584 assert node.host_address == self.host_address
586 def test_runtime_property_host_address_on_host_node(self, service_storage):
587 node_template = self._node_template(service_storage, host_address='not considered')
588 node = self._node(service_storage, node_template, is_host=True,
589 host_address=self.host_address)
590 assert node.host_address == self.host_address
592 def test_no_host_address_configured_on_host_node(self, service_storage):
593 node_template = self._node_template(service_storage, host_address=None)
594 node = self._node(service_storage, node_template, is_host=True, host_address=None)
595 assert node.host_address is None
597 def test_runtime_property_on_hosted_node(self, service_storage):
598 host_node_template = self._node_template(service_storage, host_address=None)
599 host_node = self._node(service_storage,
602 host_address=self.host_address)
603 node_template = self._node_template(service_storage, host_address=None)
604 node = self._node(service_storage,
608 host_fk=host_node.id)
609 assert node.host_address == self.host_address
611 def _node_template(self, storage, host_address):
613 name='node_template',
614 type=storage.type.list()[0],
615 service_template=storage.service_template.list()[0]
618 kwargs['properties'] = {'host_address': Property.wrap('host_address', host_address)}
619 node = NodeTemplate(**kwargs)
620 storage.node_template.put(node)
623 def _node(self, storage, node_template, is_host, host_address, host_fk=None):
626 node_template=node_template,
627 type=storage.type.list()[0],
629 service=storage.service.list()[0]
631 if is_host and (host_address is None):
632 host_address = node_template.properties.get('host_address')
633 if host_address is not None:
634 host_address = host_address.value
636 kwargs.setdefault('attributes', {})['ip'] = Attribute.wrap('ip', host_address)
638 kwargs['host_fk'] = 1
640 kwargs['host_fk'] = host_fk
641 node = Node(**kwargs)
642 storage.node.put(node)
646 class TestRelationship(object):
647 @pytest.mark.parametrize(
648 'is_valid, source_position, target_position',
658 def test_relationship_model_creation(self, nodes_storage, is_valid, source_position,
660 nodes = nodes_storage.node
661 source_node = nodes.get_by_name(mock.models.DEPENDENT_NODE_NAME)
662 target_node = nodes.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
663 _test_model(is_valid=is_valid,
664 storage=nodes_storage,
665 model_cls=Relationship,
667 source_node=source_node,
668 target_node=target_node,
669 source_position=source_position,
670 target_position=target_position
674 class TestPlugin(object):
675 @pytest.mark.parametrize(
676 'is_valid, archive_name, distribution, distribution_release, '
677 'distribution_version, package_name, package_source, '
678 'package_version, supported_platform, supported_py_versions, uploaded_at, wheels',
680 (False, m_cls, 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
681 'sup_plat', [], now, []),
682 (False, 'arc_name', m_cls, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
683 'sup_plat', [], now, []),
684 (False, 'arc_name', 'dis_name', m_cls, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
685 'sup_plat', [], now, []),
686 (False, 'arc_name', 'dis_name', 'dis_rel', m_cls, 'pak_name', 'pak_src', 'pak_ver',
687 'sup_plat', [], now, []),
688 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', m_cls, 'pak_src', 'pak_ver',
689 'sup_plat', [], now, []),
690 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', m_cls, 'pak_ver',
691 'sup_plat', [], now, []),
692 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', m_cls,
693 'sup_plat', [], now, []),
694 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
695 'pak_ver', m_cls, [], now, []),
696 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
697 'pak_ver', 'sup_plat', m_cls, now, []),
698 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
699 'pak_ver', 'sup_plat', [], m_cls, []),
700 (False, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
701 'pak_ver', 'sup_plat', [], now, m_cls),
703 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
704 'sup_plat', [], now, []),
705 (True, 'arc_name', None, 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
706 'sup_plat', [], now, []),
707 (True, 'arc_name', 'dis_name', None, 'dis_ver', 'pak_name', 'pak_src', 'pak_ver',
708 'sup_plat', [], now, []),
709 (True, 'arc_name', 'dis_name', 'dis_rel', None, 'pak_name', 'pak_src', 'pak_ver',
710 'sup_plat', [], now, []),
711 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
712 'pak_ver', 'sup_plat', [], now, []),
713 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', None, 'pak_ver',
714 'sup_plat', [], now, []),
715 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src', None,
716 'sup_plat', [], now, []),
717 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
718 'pak_ver', None, [], now, []),
719 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
720 'pak_ver', 'sup_plat', None, now, []),
721 (True, 'arc_name', 'dis_name', 'dis_rel', 'dis_ver', 'pak_name', 'pak_src',
722 'pak_ver', 'sup_plat', [], now, []),
725 def test_plugin_model_creation(self, empty_storage, is_valid, archive_name, distribution,
726 distribution_release, distribution_version, package_name,
727 package_source, package_version, supported_platform,
728 supported_py_versions, uploaded_at, wheels):
729 _test_model(is_valid=is_valid,
730 storage=empty_storage,
733 archive_name=archive_name,
734 distribution=distribution,
735 distribution_release=distribution_release,
736 distribution_version=distribution_version,
737 package_name=package_name,
738 package_source=package_source,
739 package_version=package_version,
740 supported_platform=supported_platform,
741 supported_py_versions=supported_py_versions,
742 uploaded_at=uploaded_at,
747 class TestTask(object):
749 @pytest.mark.parametrize(
750 'is_valid, status, due_at, started_at, ended_at, max_attempts, attempts_count, '
751 'retry_interval, ignore_failure, name, operation_mapping, arguments, plugin_id',
753 (False, m_cls, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
754 (False, Task.STARTED, m_cls, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
755 (False, Task.STARTED, now, m_cls, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
756 (False, Task.STARTED, now, now, m_cls, 1, 1, 1, True, 'name', 'map', {}, '1'),
757 (False, Task.STARTED, now, now, now, m_cls, 1, 1, True, 'name', 'map', {}, '1'),
758 (False, Task.STARTED, now, now, now, 1, m_cls, 1, True, 'name', 'map', {}, '1'),
759 (False, Task.STARTED, now, now, now, 1, 1, m_cls, True, 'name', 'map', {}, '1'),
760 (False, Task.STARTED, now, now, now, 1, 1, 1, True, m_cls, 'map', {}, '1'),
761 (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', m_cls, {}, '1'),
762 (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', m_cls, '1'),
763 (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, m_cls),
764 (False, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', None, '1'),
766 (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
767 (True, Task.STARTED, None, now, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
768 (True, Task.STARTED, now, None, now, 1, 1, 1, True, 'name', 'map', {}, '1'),
769 (True, Task.STARTED, now, now, None, 1, 1, 1, True, 'name', 'map', {}, '1'),
770 (True, Task.STARTED, now, now, now, 1, None, 1, True, 'name', 'map', {}, '1'),
771 (True, Task.STARTED, now, now, now, 1, 1, None, True, 'name', 'map', {}, '1'),
772 (True, Task.STARTED, now, now, now, 1, 1, 1, None, 'name', 'map', {}, '1'),
773 (True, Task.STARTED, now, now, now, 1, 1, 1, True, None, 'map', {}, '1'),
774 (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', None, {}, '1'),
775 (True, Task.STARTED, now, now, now, 1, 1, 1, True, 'name', 'map', {}, None),
778 def test_task_model_creation(self, execution_storage, is_valid, status, due_at, started_at,
779 ended_at, max_attempts, attempts_count, retry_interval,
780 ignore_failure, name, operation_mapping, arguments, plugin_id):
783 storage=execution_storage,
787 execution=execution_storage.execution.list()[0],
789 started_at=started_at,
791 max_attempts=max_attempts,
792 attempts_count=attempts_count,
793 retry_interval=retry_interval,
794 ignore_failure=ignore_failure,
796 function=operation_mapping,
801 assert task.execution == execution_storage.execution.list()[0]
803 assert task.plugin == execution_storage.plugin.list()[0]
805 def test_task_max_attempts_validation(self):
806 def create_task(max_attempts):
807 Task(execution_fk='eid',
811 max_attempts=max_attempts)
812 create_task(max_attempts=1)
813 create_task(max_attempts=2)
814 create_task(max_attempts=Task.INFINITE_RETRIES)
815 with pytest.raises(ValueError):
816 create_task(max_attempts=0)
817 with pytest.raises(ValueError):
818 create_task(max_attempts=-2)
821 class TestType(object):
822 def test_type_hierarchy(self):
823 super_type = Type(variant='variant', name='super')
824 sub_type = Type(variant='variant', parent=super_type, name='sub')
825 additional_type = Type(variant='variant', name='non_related')
827 assert super_type.hierarchy == [super_type]
828 assert sub_type.hierarchy == [sub_type, super_type]
829 assert additional_type.hierarchy == [additional_type]
831 super_type.parent = additional_type
833 assert super_type.hierarchy == [super_type, additional_type]
834 assert sub_type.hierarchy == [sub_type, super_type, additional_type]
837 class TestParameter(object):
839 MODELS_DERIVED_FROM_PARAMETER = (Input, Output, Property, Attribute, Configuration, Argument)
841 @pytest.mark.parametrize(
842 'is_valid, name, type_name, description',
844 (False, 'name', 'int', []),
845 (False, 'name', [], 'desc'),
846 (False, [], 'type_name', 'desc'),
847 (True, 'name', 'type_name', 'desc'),
850 def test_derived_from_parameter_model_creation(self, empty_storage, is_valid, name, type_name,
853 for model_cls in self.MODELS_DERIVED_FROM_PARAMETER:
854 _test_model(is_valid=is_valid,
855 storage=empty_storage,
860 description=description,
864 def test_as_argument(self):
866 for model_cls in self.MODELS_DERIVED_FROM_PARAMETER:
867 model = model_cls(name='name',
868 type_name='type_name',
869 description='description',
871 argument = model.as_argument()
872 assert isinstance(argument, Argument)