From 7a60c13f90afe056e76514af76b31bf3184454de Mon Sep 17 00:00:00 2001 From: burnettk Date: Thu, 23 Feb 2023 10:42:56 -0500 Subject: [PATCH] Squashed 'SpiffWorkflow/' changes from 11e4b4f9..2ca6ebf8 2ca6ebf8 Data stores (#298) c2fc9d22 Merge pull request #297 from sartography/bugfix/copy-all-data-when-input-or-output-list-empty 07e3b582 add checks for len == 0 when copying based on io spec b439f69f Merge pull request #296 from sartography/bugfix/subprocess-access-to-data-objects 6d2a2031 update spiff subworkflow tasks too 992c3867 make data objects referenceable within subprocesses 6c8ff5cd allow subprocesses & call activities to have different data copy policies 2b14f3a4 initialize subprocesses in _update_hook instead of _on_ready_before 791f335d Merge pull request #295 from sartography/improvement/remove-camunda-from-base-and-misc-cleanup 28b579be remove a few unused, duplicative, and debugging methods 8f14d109 remove some other unused diagrams and tests 408bc673 rely on top level camunda parser for almost all namespace references 895b2cc9 remove camunda namespace from base bpmn parser 76ecbf7c Merge pull request #294 from sartography/bugfix/reactivate-boundary-event 82b6c8ad hack to ensure timers (and other events) are reset if returned to via loop reset 590903f4 Merge pull request #292 from sartography/feature/multiinstance-refactor 53749004 fix bug & typo f31726db raise error on attempting to migrate workflows with MI 44e6d08d create spiff multiinstance task 2168c022 create camunda MI that approximates what it used to do 9894cea5 some improvements and bugfixes f857ad5d remove some now unused functionality & tests, create a few more tests 6fead9d0 updated serializer & fixes for most tests ec662ecd add parallel multiinstance bd19b2a8 working sequential multiinstance 2f9c192b further cleanup around _update_hook 947792bf fix bug in exclusive gateway migration d3d87b28 add io spec to all tasks f1586e27 add support for standard loop tasks git-subtree-dir: SpiffWorkflow git-subtree-split: 2ca6ebf800d4ff1d54f3e1c48798a2cb879560f7 --- tests/SpiffWorkflow/TaskTest.py | 12 +- tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py | 42 - .../SpiffWorkflow/bpmn/BpmnLoaderForTests.py | 38 +- .../bpmn/BpmnWorkflowTestCase.py | 7 +- .../bpmn/DataObjectReferenceTest.py | 6 +- .../bpmn/DataStoreReferenceTest.py | 36 + .../ExclusiveGatewayIntoMultiInstanceTest.py | 38 - ...lsiveGatewayNonDefaultPathIntoMultiTest.py | 59 -- tests/SpiffWorkflow/bpmn/IOSpecTest.py | 49 +- tests/SpiffWorkflow/bpmn/LoopTaskTest.py | 60 -- .../bpmn/MultiInstanceParallelCondTest.py | 54 -- .../bpmn/MultiInstanceParallelTest.py | 51 -- tests/SpiffWorkflow/bpmn/MultiInstanceTest.py | 46 - .../bpmn/ParallelMultiInstanceTest.py | 233 +++++ tests/SpiffWorkflow/bpmn/ParallelOrderTest.py | 10 +- .../bpmn/ParallelWithScriptTest.py | 25 - tests/SpiffWorkflow/bpmn/ParserTest.py | 4 +- tests/SpiffWorkflow/bpmn/ResetTimerTest.py | 28 + .../bpmn/SequentialMultiInstanceTest.py | 213 +++++ tests/SpiffWorkflow/bpmn/StandardLoopTest.py | 62 ++ .../bpmn/SubWorkflowMultiTest.py | 51 -- .../bpmn/data/MultiInstanceParallelTask.bpmn | 59 -- .../data/MultiInstanceParallelTaskCond.bpmn | 145 --- .../bpmn/data/ParallelWithScript.bpmn | 117 --- .../bpmn/data/bpmnAntiLoopTask.bpmn | 47 - .../SpiffWorkflow/bpmn/data/bpmnLoopTask.bpmn | 45 - .../bpmn/data/bpmnMultiUserTask.bpmn | 49 -- .../SpiffWorkflow/bpmn/data/data_object.bpmn | 14 +- tests/SpiffWorkflow/bpmn/data/data_store.bpmn | 89 ++ .../bpmn/data/data_store_read.bpmn | 91 ++ .../bpmn/data/data_store_write.bpmn | 91 ++ .../bpmn/data/exclusive_into_multi.bpmn | 83 -- ...exclusive_non_default_path_into_multi.bpmn | 97 -- tests/SpiffWorkflow/bpmn/data/io_spec.bpmn | 6 +- .../bpmn/data/io_spec_on_task.bpmn | 66 ++ .../parallel_multiinstance_cardinality.bpmn | 44 + .../data/parallel_multiinstance_invalid.bpmn | 45 + .../parallel_multiinstance_loop_input.bpmn | 44 + .../SpiffWorkflow/bpmn/data/reset_timer.bpmn | 104 +++ .../sequential_multiinstance_cardinality.bpmn | 44 + .../sequential_multiinstance_loop_input.bpmn | 44 + .../bpmn/data/serialization/v1.1-data.json | 731 +++++++++++++++ .../data/serialization/v1.1-gateways.json | 830 ++++++++++++++++++ .../bpmn/data/serialization/v1.1-multi.json | 350 ++++++++ .../{v1-1.json => v1.1-timers.json} | 0 .../bpmn/data/standard_loop.bpmn | 41 + .../bpmn/data/standard_loop_invalid.bpmn | 39 + .../bpmn/data/sub_within_sub_multi.bpmn | 129 --- .../bpmn/data/sub_workflow_multi.bpmn | 93 -- .../bpmn/data/sub_workflow_multi1.bpmn | 59 -- .../data/sub_workflow_multi_parallel.bpmn | 93 -- .../bpmn/data/two_top_level_procs.bpmn | 79 -- .../bpmn/events/EventBasedGatewayTest.py | 2 +- .../bpmn/events/TransactionSubprocssTest.py | 26 +- .../bpmn/serializer/VersionMigrationTest.py | 37 +- .../camunda/DefaultGatewayPMITest.py | 60 -- .../camunda/ExclusiveGatewayPMITest.py | 68 -- .../camunda/MultiInstanceArrayTest.py | 222 ----- .../camunda/MultiInstanceDMNTest.py | 13 +- .../camunda/MultiInstanceDeepDictEdit.py | 113 --- .../camunda/MultiInstanceParallelArrayTest.py | 98 --- .../camunda/ParseMultiInstanceTest.py | 91 ++ .../camunda/ResetTokenMIParallelTest.py | 80 -- .../SpiffWorkflow/camunda/ResetTokenMITest.py | 81 -- .../camunda/data/DMNMultiInstance.bpmn | 62 +- .../camunda/data/common_workflow.bpmn | 89 -- .../camunda/data/default_gateway_pmi.bpmn | 89 -- .../camunda/data/multi_instance_array.bpmn | 99 --- .../data/multi_instance_array_parallel.bpmn | 99 --- ...ulti_instance_parallel_deep_data_edit.bpmn | 66 -- .../parallel_multiinstance_cardinality.bpmn | 41 + .../parallel_multiinstance_collection.bpmn | 39 + .../camunda/data/token_trial_MI.bpmn | 83 -- .../camunda/data/token_trial_MIParallel.bpmn | 83 -- tests/SpiffWorkflow/specs/ExecuteTest.py | 5 +- tests/SpiffWorkflow/specs/TaskSpecTest.py | 19 +- tests/SpiffWorkflow/specs/WorkflowSpecTest.py | 4 +- tests/SpiffWorkflow/spiff/BaseTestCase.py | 1 - tests/SpiffWorkflow/spiff/CorrelationTest.py | 7 - .../spiff/MultiInstanceTaskTest.py | 29 + .../spiff/data/spiff_multiinstance.bpmn | 49 ++ 81 files changed, 3649 insertions(+), 2998 deletions(-) delete mode 100644 tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py create mode 100644 tests/SpiffWorkflow/bpmn/DataStoreReferenceTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/ExclusiveGatewayIntoMultiInstanceTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/ExculsiveGatewayNonDefaultPathIntoMultiTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/LoopTaskTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/MultiInstanceParallelCondTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/MultiInstanceParallelTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/MultiInstanceTest.py create mode 100644 tests/SpiffWorkflow/bpmn/ParallelMultiInstanceTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/ParallelWithScriptTest.py create mode 100644 tests/SpiffWorkflow/bpmn/ResetTimerTest.py create mode 100644 tests/SpiffWorkflow/bpmn/SequentialMultiInstanceTest.py create mode 100644 tests/SpiffWorkflow/bpmn/StandardLoopTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/SubWorkflowMultiTest.py delete mode 100644 tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTask.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTaskCond.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/ParallelWithScript.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/bpmnAntiLoopTask.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/bpmnLoopTask.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/bpmnMultiUserTask.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/data_store.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/data_store_read.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/data_store_write.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/exclusive_into_multi.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/exclusive_non_default_path_into_multi.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/io_spec_on_task.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_cardinality.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_invalid.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_loop_input.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/reset_timer.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_cardinality.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_loop_input.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/serialization/v1.1-data.json create mode 100644 tests/SpiffWorkflow/bpmn/data/serialization/v1.1-gateways.json create mode 100644 tests/SpiffWorkflow/bpmn/data/serialization/v1.1-multi.json rename tests/SpiffWorkflow/bpmn/data/serialization/{v1-1.json => v1.1-timers.json} (100%) create mode 100644 tests/SpiffWorkflow/bpmn/data/standard_loop.bpmn create mode 100644 tests/SpiffWorkflow/bpmn/data/standard_loop_invalid.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/sub_within_sub_multi.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/sub_workflow_multi.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/sub_workflow_multi1.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/sub_workflow_multi_parallel.bpmn delete mode 100644 tests/SpiffWorkflow/bpmn/data/two_top_level_procs.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/DefaultGatewayPMITest.py delete mode 100644 tests/SpiffWorkflow/camunda/ExclusiveGatewayPMITest.py delete mode 100644 tests/SpiffWorkflow/camunda/MultiInstanceArrayTest.py delete mode 100644 tests/SpiffWorkflow/camunda/MultiInstanceDeepDictEdit.py delete mode 100644 tests/SpiffWorkflow/camunda/MultiInstanceParallelArrayTest.py create mode 100644 tests/SpiffWorkflow/camunda/ParseMultiInstanceTest.py delete mode 100644 tests/SpiffWorkflow/camunda/ResetTokenMIParallelTest.py delete mode 100644 tests/SpiffWorkflow/camunda/ResetTokenMITest.py delete mode 100644 tests/SpiffWorkflow/camunda/data/common_workflow.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/default_gateway_pmi.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/multi_instance_array.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/multi_instance_array_parallel.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/multi_instance_parallel_deep_data_edit.bpmn create mode 100644 tests/SpiffWorkflow/camunda/data/parallel_multiinstance_cardinality.bpmn create mode 100644 tests/SpiffWorkflow/camunda/data/parallel_multiinstance_collection.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/token_trial_MI.bpmn delete mode 100644 tests/SpiffWorkflow/camunda/data/token_trial_MIParallel.bpmn create mode 100644 tests/SpiffWorkflow/spiff/MultiInstanceTaskTest.py create mode 100644 tests/SpiffWorkflow/spiff/data/spiff_multiinstance.bpmn diff --git a/tests/SpiffWorkflow/TaskTest.py b/tests/SpiffWorkflow/TaskTest.py index e44f68e6f..77e28df61 100644 --- a/tests/SpiffWorkflow/TaskTest.py +++ b/tests/SpiffWorkflow/TaskTest.py @@ -1,12 +1,9 @@ # -*- coding: utf-8 -*- -import sys import unittest import re -import os.path -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..')) -from SpiffWorkflow.task import Task, TaskState, updateDotDict +from SpiffWorkflow.task import Task, TaskState from SpiffWorkflow.specs.WorkflowSpec import WorkflowSpec from SpiffWorkflow.specs.Simple import Simple @@ -15,10 +12,6 @@ class MockWorkflow(object): def __init__(self, spec): self.spec = spec -class UpdateDotDictTest(unittest.TestCase): - def test_update(self): - res = updateDotDict({}, 'some.thing.here', 'avalue') - self.assertEqual(res, {'some':{'thing': {'here': 'avalue'}}}) class TaskTest(unittest.TestCase): @@ -85,8 +78,7 @@ class TaskTest(unittest.TestCase): def suite(): taskSuite = unittest.TestLoader().loadTestsFromTestCase(TaskTest) - updateDotSuite = unittest.TestLoader().loadTestsFromTestCase(UpdateDotDictTest) - return unittest.TestSuite([taskSuite, updateDotSuite]) + return unittest.TestSuite([taskSuite]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py b/tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py deleted file mode 100644 index c398ca834..000000000 --- a/tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- - - - -import unittest -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.exceptions import WorkflowException -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'kellym' - - -class AntiLoopTaskTest(BpmnWorkflowTestCase): - """The example bpmn is actually a MultiInstance. It should not report that it is a looping task and - it should fail when we try to terminate the loop""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('bpmnAntiLoopTask.bpmn','LoopTaskTest') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - - self.workflow.do_engine_steps() - ready_tasks = self.workflow.get_ready_user_tasks() - self.assertTrue(len(ready_tasks) ==1) - self.assertFalse(ready_tasks[0].task_spec.is_loop_task()) - try: - ready_tasks[0].terminate_loop() - self.fail("Terminate Loop should throw and error when called on a non-loop MultiInstance") - except WorkflowException as ex: - self.assertTrue( - 'The method terminate_loop should only be called in the case of a BPMN Loop Task' in ( - '%r' % ex), - '\'The method terminate_loop should only be called in the case of a BPMN Loop Task\' should be a substring of error message: \'%r\'' % ex) - - - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(AntiLoopTaskTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/BpmnLoaderForTests.py b/tests/SpiffWorkflow/bpmn/BpmnLoaderForTests.py index 2623e6887..d8420daa8 100644 --- a/tests/SpiffWorkflow/bpmn/BpmnLoaderForTests.py +++ b/tests/SpiffWorkflow/bpmn/BpmnLoaderForTests.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +from SpiffWorkflow.bpmn.specs.data_spec import BpmnDataStoreSpecification from SpiffWorkflow.bpmn.specs.ExclusiveGateway import ExclusiveGateway from SpiffWorkflow.bpmn.specs.UserTask import UserTask from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser @@ -7,7 +8,7 @@ from SpiffWorkflow.bpmn.parser.TaskParser import TaskParser from SpiffWorkflow.bpmn.parser.task_parsers import ConditionalGatewayParser from SpiffWorkflow.bpmn.parser.util import full_tag -from SpiffWorkflow.bpmn.serializer.helpers.spec import TaskSpecConverter +from SpiffWorkflow.bpmn.serializer.helpers.spec import BpmnSpecConverter, TaskSpecConverter # Many of our tests relied on the Packager to set the calledElement attribute on # Call Activities. I've moved that code to a customized parser. @@ -57,6 +58,38 @@ class TestUserTaskConverter(TaskSpecConverter): def from_dict(self, dct): return self.task_spec_from_dict(dct) +class TestDataStore(BpmnDataStoreSpecification): + + _value = None + + def get(self, my_task): + """Copy a value from a data store into task data.""" + my_task.data[self.name] = TestDataStore._value + + def set(self, my_task): + """Copy a value from the task data to the data store""" + TestDataStore._value = my_task.data[self.name] + del my_task.data[self.name] + +class TestDataStoreConverter(BpmnSpecConverter): + + def __init__(self, registry): + super().__init__(TestDataStore, registry) + + def to_dict(self, spec): + return { + "name": spec.name, + "description": spec.description, + "capacity": spec.capacity, + "is_unlimited": spec.is_unlimited, + "_value": TestDataStore._value, + } + + def from_dict(self, dct): + _value = dct.pop("_value") + data_store = TestDataStore(**dct) + TestDataStore._value = _value + return data_store class TestBpmnParser(BpmnParser): OVERRIDE_PARSER_CLASSES = { @@ -65,3 +98,6 @@ class TestBpmnParser(BpmnParser): full_tag('callActivity'): (CallActivityParser, CallActivity) } + DATA_STORE_CLASSES = { + "TestDataStore": TestDataStore, + } diff --git a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py index ba564abc8..d16a87920 100644 --- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py +++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py @@ -8,13 +8,12 @@ from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnValidator from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer, DEFAULT_SPEC_CONFIG -from SpiffWorkflow.bpmn.serializer.task_spec import UserTaskConverter -from .BpmnLoaderForTests import TestUserTaskConverter, TestBpmnParser +from .BpmnLoaderForTests import TestUserTaskConverter, TestBpmnParser, TestDataStoreConverter __author__ = 'matth' DEFAULT_SPEC_CONFIG['task_specs'].append(TestUserTaskConverter) - +DEFAULT_SPEC_CONFIG['task_specs'].append(TestDataStoreConverter) wf_spec_converter = BpmnWorkflowSerializer.configure_workflow_spec_converter(spec_config=DEFAULT_SPEC_CONFIG) @@ -121,6 +120,7 @@ class BpmnWorkflowTestCase(unittest.TestCase): def save_restore(self): + script_engine = self.workflow.script_engine before_state = self._get_workflow_state(do_steps=False) before_dump = self.workflow.get_dump() # Check that we can actully convert this to JSON @@ -133,6 +133,7 @@ class BpmnWorkflowTestCase(unittest.TestCase): self.assertEqual(before_dump, after_dump) self.assertEqual(before_state, after_state) self.workflow = after + self.workflow.script_engine = script_engine def restore(self, state): self.workflow = self.serializer.workflow_from_dict(state) diff --git a/tests/SpiffWorkflow/bpmn/DataObjectReferenceTest.py b/tests/SpiffWorkflow/bpmn/DataObjectReferenceTest.py index 0254c5df4..fab8db77b 100644 --- a/tests/SpiffWorkflow/bpmn/DataObjectReferenceTest.py +++ b/tests/SpiffWorkflow/bpmn/DataObjectReferenceTest.py @@ -72,11 +72,15 @@ class DataObjectReferenceTest(BpmnWorkflowTestCase): self.assertNotIn('obj_1', ready_tasks[0].data) self.assertEqual(self.workflow.data['obj_1'], 'hello') - # Make sure data objects can be copied in and out of a subprocess + # Make sure data objects are accessible inside a subprocess self.workflow.do_engine_steps() ready_tasks = self.workflow.get_ready_user_tasks() self.assertEqual(ready_tasks[0].data['obj_1'], 'hello') + ready_tasks[0].data['obj_1'] = 'hello again' ready_tasks[0].complete() self.workflow.do_engine_steps() sp = self.workflow.get_tasks_from_spec_name('subprocess')[0] + # It was copied out self.assertNotIn('obj_1', sp.data) + # The update should persist in the main process + self.assertEqual(self.workflow.data['obj_1'], 'hello again') diff --git a/tests/SpiffWorkflow/bpmn/DataStoreReferenceTest.py b/tests/SpiffWorkflow/bpmn/DataStoreReferenceTest.py new file mode 100644 index 000000000..a9e3d7358 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/DataStoreReferenceTest.py @@ -0,0 +1,36 @@ +from tests.SpiffWorkflow.bpmn.BpmnLoaderForTests import TestDataStore +from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase +from SpiffWorkflow.bpmn.exceptions import WorkflowDataException +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow + +class DataStoreReferenceTest(BpmnWorkflowTestCase): + def _do_engine_steps(self, file, processid, save_restore): + spec, subprocesses = self.load_workflow_spec('data_store.bpmn', 'JustDataStoreRef') + self.workflow = BpmnWorkflow(spec, subprocesses) + if save_restore: + self.save_restore() + self.workflow.do_engine_steps() + + def _check_last_script_task_data(self): + last_script_task_data = self.workflow.get_tasks_from_spec_name("Activity_1skgyn9")[0].data + self.assertEqual(len(last_script_task_data), 1) + self.assertEqual(last_script_task_data["x"], "Sue") + + def testCanInterpretDataStoreReferenceWithInputsAndOutputs(self): + self._do_engine_steps('data_store.bpmn', 'JustDataStoreRef', False) + self._check_last_script_task_data() + + def testCanSaveRestoreDataStoreReferenceWithInputsAndOutputs(self): + self._do_engine_steps('data_store.bpmn', 'JustDataStoreRef', True) + self._check_last_script_task_data() + + def testSeparateWorkflowInstancesCanShareDataUsingDataStores(self): + self._do_engine_steps('data_store_write.bpmn', 'JustDataStoreRef', False) + self._do_engine_steps('data_store_read.bpmn', 'JustDataStoreRef', False) + self._check_last_script_task_data() + + def testSeparateRestoredWorkflowInstancesCanShareDataUsingDataStores(self): + self._do_engine_steps('data_store_write.bpmn', 'JustDataStoreRef', True) + self._do_engine_steps('data_store_read.bpmn', 'JustDataStoreRef', True) + self._check_last_script_task_data() + diff --git a/tests/SpiffWorkflow/bpmn/ExclusiveGatewayIntoMultiInstanceTest.py b/tests/SpiffWorkflow/bpmn/ExclusiveGatewayIntoMultiInstanceTest.py deleted file mode 100644 index 8eaaff418..000000000 --- a/tests/SpiffWorkflow/bpmn/ExclusiveGatewayIntoMultiInstanceTest.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- - - - -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class ExclusiveGatewayIntoMultiInstanceTest(BpmnWorkflowTestCase): - """In the example BPMN Diagram we set x = 0, then we have an - exclusive gateway that should skip over a parallel multi-instance - class, so it should run straight through and complete without issue.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('exclusive_into_multi.bpmn','ExclusiveToMulti') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - - - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - - def testSaveRestore(self): - - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ExclusiveGatewayIntoMultiInstanceTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/ExculsiveGatewayNonDefaultPathIntoMultiTest.py b/tests/SpiffWorkflow/bpmn/ExculsiveGatewayNonDefaultPathIntoMultiTest.py deleted file mode 100644 index 424f72e9b..000000000 --- a/tests/SpiffWorkflow/bpmn/ExculsiveGatewayNonDefaultPathIntoMultiTest.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- - - - -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class ExclusiveGatewayNonDefaultPathIntoMultiTest(BpmnWorkflowTestCase): - """In the example BPMN Diagram we require that "Yes" or "No" be specified - in a user task and check that a multiinstance can follow a non-default - path. - """ - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('exclusive_non_default_path_into_multi.bpmn','ExclusiveNonDefaultMulti') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def load_workflow1_spec(self): - return - - def testRunThroughHappy(self): - - - self.workflow.do_engine_steps() - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("DoStuff", task.task_spec.name) - task.update_data({"morestuff": 'Yes'}) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i == 0: - self.assertEqual("GetMoreStuff", task.task_spec.name) - else: - self.assertEqual("GetMoreStuff_%d"%(i-1), task.task_spec.name) - - - task.update_data({"stuff.addstuff": "Stuff %d"%i}) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - - self.assertTrue(self.workflow.is_completed()) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ExclusiveGatewayNonDefaultPathIntoMultiTest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/IOSpecTest.py b/tests/SpiffWorkflow/bpmn/IOSpecTest.py index 6b27fc059..b3f70fe67 100644 --- a/tests/SpiffWorkflow/bpmn/IOSpecTest.py +++ b/tests/SpiffWorkflow/bpmn/IOSpecTest.py @@ -25,9 +25,6 @@ class CallActivityDataTest(BpmnWorkflowTestCase): with self.assertRaises(WorkflowDataException) as exc: self.advance_to_subprocess() - self.assertEqual("'in_2' was not found in the task data. " - "You are missing a required Data Input for a call activity.", - str(exc.exception)) self.assertEqual(exc.exception.data_input.name,'in_2') def testCallActivityMissingOutput(self): @@ -43,10 +40,7 @@ class CallActivityDataTest(BpmnWorkflowTestCase): with self.assertRaises(WorkflowDataException) as exc: self.complete_subprocess() - - self.assertEqual("'out_2' was not found in the task data. A Data Output was not provided as promised.", - str(exc.exception)) - self.assertEqual(exc.exception.data_output.name,'out_2') + self.assertEqual(exc.exception.data_output.name, 'out_2') def actual_test(self, save_restore=False): @@ -92,3 +86,44 @@ class CallActivityDataTest(BpmnWorkflowTestCase): next_task = self.workflow.get_tasks(TaskState.READY)[0] next_task.complete() waiting = self.workflow.get_tasks(TaskState.WAITING) + + +class IOSpecOnTaskTest(BpmnWorkflowTestCase): + + def setUp(self): + self.spec, self.subprocesses = self.load_workflow_spec('io_spec_on_task.bpmn', 'main') + + def testIOSpecOnTask(self): + self.actual_test() + + def testIOSpecOnTaskSaveRestore(self): + self.actual_test(True) + + def testIOSpecOnTaskMissingInput(self): + self.workflow = BpmnWorkflow(self.spec, self.subprocesses) + set_data = self.workflow.spec.task_specs['set_data'] + set_data.script = """in_1, unused = 1, True""" + with self.assertRaises(WorkflowDataException) as exc: + self.workflow.do_engine_steps() + self.assertEqual(exc.exception.data_input.name, 'in_2') + + def testIOSpecOnTaskMissingOutput(self): + self.workflow = BpmnWorkflow(self.spec, self.subprocesses) + self.workflow.do_engine_steps() + task = self.workflow.get_tasks_from_spec_name('any_task')[0] + task.data.update({'out_1': 1}) + with self.assertRaises(WorkflowDataException) as exc: + task.complete() + self.assertEqual(exc.exception.data_output.name, 'out_2') + + def actual_test(self, save_restore=False): + self.workflow = BpmnWorkflow(self.spec, self.subprocesses) + self.workflow.do_engine_steps() + if save_restore: + self.save_restore() + task = self.workflow.get_tasks_from_spec_name('any_task')[0] + self.assertDictEqual(task.data, {'in_1': 1, 'in_2': 'hello world'}) + task.data.update({'out_1': 1, 'out_2': 'bye', 'extra': True}) + task.complete() + self.workflow.do_engine_steps() + self.assertDictEqual(self.workflow.last_task.data, {'out_1': 1, 'out_2': 'bye'}) diff --git a/tests/SpiffWorkflow/bpmn/LoopTaskTest.py b/tests/SpiffWorkflow/bpmn/LoopTaskTest.py deleted file mode 100644 index 709750c64..000000000 --- a/tests/SpiffWorkflow/bpmn/LoopTaskTest.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'kellym' - - -class LoopTaskTest(BpmnWorkflowTestCase): - """The example bpmn diagram has a single task with a loop cardinality of 5. - It should repeat 5 times before termination.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('bpmnLoopTask.bpmn','LoopTaskTest') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - - for i in range(5): - self.workflow.do_engine_steps() - ready_tasks = self.workflow.get_ready_user_tasks() - self.assertTrue(len(ready_tasks) ==1) - self.assertTrue(ready_tasks[0].task_spec.is_loop_task()) - self.assertFalse(self.workflow.is_completed()) - last_task = self.workflow.last_task - - self.do_next_exclusive_step('Activity_TestLoop') - - ready_tasks = self.workflow.get_ready_user_tasks() - self.assertTrue(len(ready_tasks) ==1) - ready_tasks[0].terminate_loop() - self.do_next_exclusive_step('Activity_TestLoop') - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - - - def testSaveRestore(self): - - for i in range(5): - self.save_restore() - self.workflow.do_engine_steps() - ready_tasks = self.workflow.get_ready_user_tasks() - self.assertTrue(len(ready_tasks) ==1) - self.assertTrue(ready_tasks[0].task_spec.is_loop_task()) - self.assertFalse(self.workflow.is_completed()) - self.do_next_exclusive_step('Activity_TestLoop') - - ready_tasks = self.workflow.get_ready_user_tasks() - self.assertTrue(len(ready_tasks) ==1) - ready_tasks[0].terminate_loop() - self.do_next_exclusive_step('Activity_TestLoop') - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(LoopTaskTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/MultiInstanceParallelCondTest.py b/tests/SpiffWorkflow/bpmn/MultiInstanceParallelCondTest.py deleted file mode 100644 index 305cb3df9..000000000 --- a/tests/SpiffWorkflow/bpmn/MultiInstanceParallelCondTest.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class MultiInstanceCondTest(BpmnWorkflowTestCase): - """The example bpmn diagram has a single task set to be a parallel - multi-instance with a loop cardinality of 5. - It should repeat 5 times before termination, and it should - have a navigation list with 7 items in it - one for start, one for end, - and five items for the repeating section. """ - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('MultiInstanceParallelTaskCond.bpmn', 'MultiInstance') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def load_workflow1_spec(self): - return - - def testRunThroughHappy(self): - self.actualTest() - - def testSaveRestore(self): - self.actualTest(True) - - def actualTest(self, save_restore=False): - - self.workflow.do_engine_steps() - self.assertEqual(1, len(self.workflow.get_ready_user_tasks())) - task = self.workflow.get_ready_user_tasks()[0] - task.data['collection'] = {'a':{'a':'test'}, - 'b':{'b':'test'}} - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - - for task in self.workflow.get_ready_user_tasks(): - self.assertFalse(self.workflow.is_completed()) - self.workflow.complete_task_from_id(task.id) - if save_restore: - self.save_restore() - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceCondTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/MultiInstanceParallelTest.py b/tests/SpiffWorkflow/bpmn/MultiInstanceParallelTest.py deleted file mode 100644 index e13b943a2..000000000 --- a/tests/SpiffWorkflow/bpmn/MultiInstanceParallelTest.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class MultiInstanceTest(BpmnWorkflowTestCase): - """The example bpmn diagram has a single task set to be a parallel - multi-instance with a loop cardinality of 5. - It should repeat 5 times before termination, and it should - have a navigation list with 7 items in it - one for start, one for end, - and five items for the repeating section. """ - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('MultiInstanceParallelTask.bpmn', 'MultiInstance') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def load_workflow1_spec(self): - return - - def testRunThroughHappy(self): - self.actualTest() - - def testSaveRestore(self): - self.actualTest(True) - - def actualTest(self, save_restore=False): - self.workflow.do_engine_steps() - self.assertEqual(1, len(self.workflow.get_ready_user_tasks())) - task = self.workflow.get_ready_user_tasks()[0] - task.data['collection'] = [1,2,3,4,5] - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - for task in self.workflow.get_ready_user_tasks(): - self.assertFalse(self.workflow.is_completed()) - self.workflow.complete_task_from_id(task.id) - if save_restore: - self.save_restore() - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/MultiInstanceTest.py b/tests/SpiffWorkflow/bpmn/MultiInstanceTest.py deleted file mode 100644 index 6054f99a4..000000000 --- a/tests/SpiffWorkflow/bpmn/MultiInstanceTest.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class MultiInstanceTest(BpmnWorkflowTestCase): - """The example bpmn diagram has a single task with a loop cardinality of 5. - It should repeat 5 times before termination.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('bpmnMultiUserTask.bpmn','MultiInstance') - self.workflow = BpmnWorkflow(spec, subprocesses) - - - def testRunThroughHappy(self): - - for i in range(5): - self.workflow.do_engine_steps() - self.assertFalse(self.workflow.is_completed()) - self.do_next_exclusive_step('Activity_Loop') - - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - - def testSaveRestore(self): - - for i in range(5): - self.save_restore() - self.workflow.do_engine_steps() - self.assertFalse(self.workflow.is_completed()) - self.do_next_exclusive_step('Activity_Loop') - - self.workflow.do_engine_steps() - self.assertTrue(self.workflow.is_completed()) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/ParallelMultiInstanceTest.py b/tests/SpiffWorkflow/bpmn/ParallelMultiInstanceTest.py new file mode 100644 index 000000000..c72948b42 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/ParallelMultiInstanceTest.py @@ -0,0 +1,233 @@ +from SpiffWorkflow.task import TaskState +from SpiffWorkflow.bpmn.exceptions import WorkflowDataException +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.bpmn.specs.data_spec import TaskDataReference +from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException + +from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase + + +class BaseTestCase(BpmnWorkflowTestCase): + + def set_io_and_run_workflow(self, data, data_input=None, data_output=None, save_restore=False): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = data + + any_task = self.workflow.get_tasks_from_spec_name('any_task')[0] + any_task.task_spec.data_input = TaskDataReference(data_input) if data_input is not None else None + any_task.task_spec.data_output = TaskDataReference(data_output) if data_output is not None else None + + self.workflow.do_engine_steps() + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + while len(ready_tasks) > 0: + task = ready_tasks[0] + self.assertEqual(task.task_spec.name, 'any_task [child]') + self.assertIn('input_item', task.data) + task.data['output_item'] = task.data['input_item'] * 2 + task.complete() + if save_restore: + self.save_restore() + ready_tasks = self.workflow.get_ready_user_tasks() + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + + def run_workflow_with_condition(self, data): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = data + + task = self.workflow.get_tasks_from_spec_name('any_task')[0] + task.task_spec.condition = "input_item == 2" + + self.workflow.do_engine_steps() + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + task = [t for t in ready_tasks if t.data['input_item'] == 2][0] + task.data['output_item'] = task.data['input_item'] * 2 + task.complete() + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + + self.assertTrue(self.workflow.is_completed()) + self.assertEqual(len([ t for t in ready_tasks if t.state == TaskState.CANCELLED]), 2) + + +class ParallellMultiInstanceExistingOutputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('parallel_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testListWithDictOutput(self): + data = { + 'input_data': [1, 2, 3], + 'output_data': {}, + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': {0: 2, 1: 4, 2: 6}, + }) + + def testDictWithListOutput(self): + data = { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': [], + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': [2, 4, 6], + }) + + def testNonEmptyOutput(self): + with self.assertRaises(WorkflowDataException) as exc: + data = { + 'input_data': [1, 2, 3], + 'output_data': [1, 2, 3], + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertEqual(exc.exception.message, + "If the input is not being updated in place, the output must be empty or it must be a map (dict)") + + def testInvalidOutputType(self): + with self.assertRaises(WorkflowDataException) as exc: + data = { + 'input_data': set([1, 2, 3]), + 'output_data': set(), + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertEqual(exc.exception.message, "Only a mutable map (dict) or sequence (list) can be used for output") + + +class ParallelMultiInstanceNewOutputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('parallel_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testList(self): + data = {'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [2, 4, 6] + }) + + def testListSaveRestore(self): + data = {'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [2, 4, 6] + }) + + def testDict(self): + data = {'input_data': {'a': 1, 'b': 2, 'c': 3} } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': {'a': 2, 'b': 4, 'c': 6} + }) + + def testDictSaveRestore(self): + data = {'input_data': {'a': 1, 'b': 2, 'c': 3} } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': {'a': 2, 'b': 4, 'c': 6} + }) + + def testSet(self): + data = {'input_data': set([1, 2, 3])} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': set([1, 2, 3]), + 'output_data': [2, 4, 6] + }) + + def testEmptyCollection(self): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': []} + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, {'input_data': [], 'output_data': []}) + + def testCondition(self): + self.run_workflow_with_condition({'input_data': [1, 2, 3]}) + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [4] + }) + + +class ParallelMultiInstanceUpdateInputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('parallel_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testList(self): + data = { 'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='input_data') + self.assertDictEqual(self.workflow.data, {'input_data': [2, 4, 6]}) + + def testDict(self): + data = { 'input_data': {'a': 1, 'b': 2, 'c': 3}} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='input_data') + self.assertDictEqual(self.workflow.data, {'input_data': {'a': 2, 'b': 4, 'c': 6}}) + + +class ParallelMultiInstanceWithCardinality(BaseTestCase): + + def setUp(self) -> None: + self.spec, subprocess = self.load_workflow_spec('parallel_multiinstance_cardinality.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testCardinality(self): + self.set_io_and_run_workflow({}, data_output='output_data') + self.assertDictEqual(self.workflow.data, {'output_data': [0, 2, 4]}) + + def testCardinalitySaveRestore(self): + self.set_io_and_run_workflow({}, data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, {'output_data': [0, 2, 4]}) + + def testCondition(self): + self.run_workflow_with_condition({}) + self.assertDictEqual(self.workflow.data, { + 'output_data': [4] + }) + + +class ParallelMultiInstanceTaskTest(BpmnWorkflowTestCase): + + def check_reference(self, reference, name): + self.assertIsInstance(reference, TaskDataReference) + self.assertEqual(reference.name, name) + + def testParseInputOutput(self): + spec, subprocess = self.load_workflow_spec('parallel_multiinstance_loop_input.bpmn', 'main') + workflow = BpmnWorkflow(spec) + task_spec = workflow.get_tasks_from_spec_name('any_task')[0].task_spec + self.check_reference(task_spec.data_input, 'input_data') + self.check_reference(task_spec.data_output, 'output_data') + self.check_reference(task_spec.input_item, 'input_item') + self.check_reference(task_spec.output_item, 'output_item') + self.assertIsNone(task_spec.cardinality) + + def testParseCardinality(self): + spec, subprocess = self.load_workflow_spec('parallel_multiinstance_cardinality.bpmn', 'main') + workflow = BpmnWorkflow(spec) + task_spec = workflow.get_tasks_from_spec_name('any_task')[0].task_spec + self.assertIsNone(task_spec.data_input) + self.assertEqual(task_spec.cardinality, '3') + + def testInvalidBpmn(self): + with self.assertRaises(ValidationException) as exc: + spec, subprocess = self.load_workflow_spec('parallel_multiinstance_invalid.bpmn', 'main') + self.assertEqual(exc.exception.message, + 'A multiinstance task must specify exactly one of cardinality or loop input data reference.') diff --git a/tests/SpiffWorkflow/bpmn/ParallelOrderTest.py b/tests/SpiffWorkflow/bpmn/ParallelOrderTest.py index 67d3c90bd..39797448b 100644 --- a/tests/SpiffWorkflow/bpmn/ParallelOrderTest.py +++ b/tests/SpiffWorkflow/bpmn/ParallelOrderTest.py @@ -1,16 +1,12 @@ # -*- coding: utf-8 -*- -import sys -import os import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) + from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase -__author__ = 'matth' - -class MultiInstanceTest(BpmnWorkflowTestCase): +class ParallelOrderTest(BpmnWorkflowTestCase): """The example bpmn diagram has a 4 parallel workflows, this verifies that the parallel tasks have a natural order that follows the visual layout of the diagram, rather than just the order in which @@ -33,6 +29,6 @@ class MultiInstanceTest(BpmnWorkflowTestCase): def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceTest) + return unittest.TestLoader().loadTestsFromTestCase(ParallelOrderTest) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/ParallelWithScriptTest.py b/tests/SpiffWorkflow/bpmn/ParallelWithScriptTest.py deleted file mode 100644 index 933d8a91d..000000000 --- a/tests/SpiffWorkflow/bpmn/ParallelWithScriptTest.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - - - -import unittest -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'leashys' - - -class ParallelWithScriptTest(BpmnWorkflowTestCase): - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('ParallelWithScript.bpmn', 'ParallelWithScript') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughParallel(self): - self.workflow.do_engine_steps() - # TODO: what to assert here? - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ParallelWithScriptTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/ParserTest.py b/tests/SpiffWorkflow/bpmn/ParserTest.py index 59a327758..25d26fdb6 100644 --- a/tests/SpiffWorkflow/bpmn/ParserTest.py +++ b/tests/SpiffWorkflow/bpmn/ParserTest.py @@ -13,8 +13,8 @@ class ParserTest(unittest.TestCase): bpmn_file = os.path.join(os.path.dirname(__file__), 'data', 'io_spec.bpmn') parser.add_bpmn_file(bpmn_file) spec = parser.get_spec('subprocess') - self.assertEqual(len(spec.data_inputs), 2) - self.assertEqual(len(spec.data_outputs), 2) + self.assertEqual(len(spec.io_specification.data_inputs), 2) + self.assertEqual(len(spec.io_specification.data_outputs), 2) def testDataReferences(self): diff --git a/tests/SpiffWorkflow/bpmn/ResetTimerTest.py b/tests/SpiffWorkflow/bpmn/ResetTimerTest.py new file mode 100644 index 000000000..8a94dabab --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/ResetTimerTest.py @@ -0,0 +1,28 @@ + +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.task import TaskState + +from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase + +class ResetTimerTest(BpmnWorkflowTestCase): + + def test_timer(self): + spec, subprocess = self.load_workflow_spec('reset_timer.bpmn', 'main') + self.workflow = BpmnWorkflow(spec, subprocess) + self.workflow.do_engine_steps() + task_1 = self.workflow.get_tasks_from_spec_name('task_1')[0] + timer = self.workflow.get_tasks_from_spec_name('timer')[0] + original_timer = timer.internal_data.get('event_value') + # This returns us to the task + task_1.data['modify'] = True + task_1.complete() + self.workflow.do_engine_steps() + # The timer should be waiting and the time should have been updated + self.assertEqual(task_1.state, TaskState.READY) + self.assertEqual(timer.state, TaskState.WAITING) + self.assertGreater(timer.internal_data.get('event_value'), original_timer) + task_1.data['modify'] = False + task_1.complete() + self.workflow.do_engine_steps() + self.assertEqual(timer.state, TaskState.CANCELLED) + self.assertTrue(self.workflow.is_completed()) \ No newline at end of file diff --git a/tests/SpiffWorkflow/bpmn/SequentialMultiInstanceTest.py b/tests/SpiffWorkflow/bpmn/SequentialMultiInstanceTest.py new file mode 100644 index 000000000..ba93fdbe1 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/SequentialMultiInstanceTest.py @@ -0,0 +1,213 @@ +from SpiffWorkflow.task import TaskState +from SpiffWorkflow.bpmn.exceptions import WorkflowDataException +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.bpmn.specs.data_spec import TaskDataReference + +from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase + + +class BaseTestCase(BpmnWorkflowTestCase): + + def set_io_and_run_workflow(self, data, data_input=None, data_output=None, save_restore=False): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = data + + any_task = self.workflow.get_tasks_from_spec_name('any_task')[0] + any_task.task_spec.data_input = TaskDataReference(data_input) if data_input is not None else None + any_task.task_spec.data_output = TaskDataReference(data_output) if data_output is not None else None + + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + ready_tasks = self.workflow.get_ready_user_tasks() + + while len(ready_tasks) > 0: + self.assertEqual(len(ready_tasks), 1) + task = ready_tasks[0] + self.assertEqual(task.task_spec.name, 'any_task [child]') + self.assertIn('input_item', task.data) + task.data['output_item'] = task.data['input_item'] * 2 + task.complete() + if save_restore: + self.save_restore() + ready_tasks = self.workflow.get_ready_user_tasks() + + self.workflow.do_engine_steps() + children = self.workflow.get_tasks_from_spec_name('any_task [child]') + self.assertEqual(len(children), 3) + self.assertTrue(self.workflow.is_completed()) + + def run_workflow_with_condition(self, data, condition): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = data + + task = self.workflow.get_tasks_from_spec_name('any_task')[0] + task.task_spec.condition = condition + + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + ready_tasks = self.workflow.get_ready_user_tasks() + + while len(ready_tasks) > 0: + ready = ready_tasks[0] + self.assertEqual(ready.task_spec.name, 'any_task [child]') + self.assertIn('input_item', ready.data) + ready.data['output_item'] = ready.data['input_item'] * 2 + ready.complete() + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + ready_tasks = self.workflow.get_ready_user_tasks() + + self.workflow.do_engine_steps() + children = self.workflow.get_tasks_from_spec_name('any_task [child]') + self.assertEqual(len(children), 2) + self.assertTrue(self.workflow.is_completed()) + + +class SequentialMultiInstanceExistingOutputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('sequential_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testListWithDictOutput(self): + data = { + 'input_data': [1, 2, 3], + 'output_data': {}, + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': {0: 2, 1: 4, 2: 6}, + }) + + def testDictWithListOutput(self): + data = { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': [], + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': [2, 4, 6], + }) + + def testNonEmptyOutput(self): + with self.assertRaises(WorkflowDataException) as exc: + data = { + 'input_data': [1, 2, 3], + 'output_data': [1, 2, 3], + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertEqual(exc.exception.message, + "If the input is not being updated in place, the output must be empty or it must be a map (dict)") + + def testInvalidOutputType(self): + with self.assertRaises(WorkflowDataException) as exc: + data = { + 'input_data': set([1, 2, 3]), + 'output_data': set(), + } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertEqual(exc.exception.message, "Only a mutable map (dict) or sequence (list) can be used for output") + + +class SequentialMultiInstanceNewOutputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('sequential_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testList(self): + data = {'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [2, 4, 6] + }) + + def testListSaveRestore(self): + data = {'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [2, 4, 6] + }) + + def testDict(self): + data = {'input_data': {'a': 1, 'b': 2, 'c': 3} } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': {'a': 2, 'b': 4, 'c': 6} + }) + + def testDictSaveRestore(self): + data = {'input_data': {'a': 1, 'b': 2, 'c': 3} } + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, { + 'input_data': {'a': 1, 'b': 2, 'c': 3}, + 'output_data': {'a': 2, 'b': 4, 'c': 6} + }) + + def testSet(self): + data = {'input_data': set([1, 2, 3])} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='output_data') + self.assertDictEqual(self.workflow.data, { + 'input_data': set([1, 2, 3]), + 'output_data': [2, 4, 6] + }) + + def testEmptyCollection(self): + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': []} + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, {'input_data': [], 'output_data': []}) + + def testCondition(self): + self.run_workflow_with_condition({'input_data': [1, 2, 3]}, "input_item == 2") + self.assertDictEqual(self.workflow.data, { + 'input_data': [1, 2, 3], + 'output_data': [2, 4] + }) + + +class SequentialMultiInstanceUpdateInputTest(BaseTestCase): + + def setUp(self): + self.spec, subprocess = self.load_workflow_spec('sequential_multiinstance_loop_input.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testList(self): + data = { 'input_data': [1, 2, 3]} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='input_data') + self.assertDictEqual(self.workflow.data, {'input_data': [2, 4, 6]}) + + def testDict(self): + data = { 'input_data': {'a': 1, 'b': 2, 'c': 3}} + self.set_io_and_run_workflow(data, data_input='input_data', data_output='input_data') + self.assertDictEqual(self.workflow.data, {'input_data': {'a': 2, 'b': 4, 'c': 6}}) + + +class SequentialMultiInstanceWithCardinality(BaseTestCase): + + def setUp(self) -> None: + self.spec, subprocess = self.load_workflow_spec('sequential_multiinstance_cardinality.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testCardinality(self): + self.set_io_and_run_workflow({}, data_output='output_data') + self.assertDictEqual(self.workflow.data, {'output_data': [0, 2, 4]}) + + def testCardinalitySaveRestore(self): + self.set_io_and_run_workflow({}, data_output='output_data', save_restore=True) + self.assertDictEqual(self.workflow.data, {'output_data': [0, 2, 4]}) + + def testCondition(self): + self.run_workflow_with_condition({}, "input_item == 1") + self.assertDictEqual(self.workflow.data, { + 'output_data': [0, 2] + }) diff --git a/tests/SpiffWorkflow/bpmn/StandardLoopTest.py b/tests/SpiffWorkflow/bpmn/StandardLoopTest.py new file mode 100644 index 000000000..e9d6534c4 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/StandardLoopTest.py @@ -0,0 +1,62 @@ +import os + +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser, ValidationException +from .BpmnWorkflowTestCase import BpmnWorkflowTestCase + +class StandardLoopTest(BpmnWorkflowTestCase): + + def setUp(self): + spec, subprocesses = self.load_workflow_spec('standard_loop.bpmn','main', validate=False) + # This spec has a loop task with loopMaximum = 3 and loopCondition = 'done' + self.workflow = BpmnWorkflow(spec, subprocesses) + + def testLoopMaximum(self): + + start = self.workflow.get_tasks_from_spec_name('StartEvent_1') + start[0].data['done'] = False + for idx in range(3): + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 1) + ready_tasks[0].data[str(idx)] = True + ready_tasks[0].complete() + + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + + def testLoopCondition(self): + + start = self.workflow.get_tasks_from_spec_name('StartEvent_1') + start[0].data['done'] = False + + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 1) + ready_tasks[0].data['done'] = True + ready_tasks[0].complete() + + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + + def testSkipLoop(self): + + # This is called "skip loop" because I thought "testTestBefore" was a terrible name + start = self.workflow.get_tasks_from_spec_name('StartEvent_1') + start[0].data['done'] = True + self.workflow.do_engine_steps() + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + + +class ParseStandardLoop(BpmnWorkflowTestCase): + + def testParseStandardLoop(self): + parser = BpmnParser() + # This process has neither a loop condition nor a loop maximum + bpmn_file = os.path.join(os.path.dirname(__file__), 'data', 'standard_loop_invalid.bpmn') + parser.add_bpmn_file(bpmn_file) + self.assertRaises(ValidationException, parser.get_spec, 'main') diff --git a/tests/SpiffWorkflow/bpmn/SubWorkflowMultiTest.py b/tests/SpiffWorkflow/bpmn/SubWorkflowMultiTest.py deleted file mode 100644 index 83dfcef26..000000000 --- a/tests/SpiffWorkflow/bpmn/SubWorkflowMultiTest.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase - -__author__ = 'matth' - - -class SubWorkflowMultiTest(BpmnWorkflowTestCase): - - expected_data = { - 'a': {'name': 'Apple_edit', - 'new_info': 'Adding this!'}, - 'b': {'name': 'Bubble_edit', - 'new_info': 'Adding this!'}, - 'c': {'name': 'Crap, I should write better code_edit', - 'new_info': 'Adding this!'} - } - - def testSequential(self): - spec, subprocesses = self.load_workflow_spec('sub_workflow_multi.bpmn', 'ScriptTest') - self.workflow = BpmnWorkflow(spec, subprocesses) - self.workflow.do_engine_steps() - - data = self.workflow.last_task.data - self.assertEqual(data['my_collection'], self.expected_data) - - def testParallel(self): - spec, subprocesses= self.load_workflow_spec('sub_workflow_multi_parallel.bpmn', 'ScriptTest') - self.workflow = BpmnWorkflow(spec, subprocesses) - self.workflow.do_engine_steps() - - data = self.workflow.last_task.data - self.assertEqual(data['my_collection'], self.expected_data) - - def testWrapped(self): - spec, subprocesses = self.load_workflow_spec('sub_within_sub_multi.bpmn', 'ScriptTest') - self.workflow = BpmnWorkflow(spec, subprocesses) - self.workflow.do_engine_steps() - - data = self.workflow.last_task.data - self.assertEqual(self.expected_data, data['my_collection']) - - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(SubWorkflowMultiTest) -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTask.bpmn b/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTask.bpmn deleted file mode 100644 index 6b02f0961..000000000 --- a/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTask.bpmn +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Flow_0t6p1sb - - - - Flow_0ugjw69 - - - - Flow_0ds4mp0 - Flow_0ugjw69 - - collection - - - - Flow_0t6p1sb - Flow_0ds4mp0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTaskCond.bpmn b/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTaskCond.bpmn deleted file mode 100644 index 53ecfd4e2..000000000 --- a/tests/SpiffWorkflow/bpmn/data/MultiInstanceParallelTaskCond.bpmn +++ /dev/null @@ -1,145 +0,0 @@ - - - - - Flow_0t6p1sb - - - - Flow_0ugjw69 - Flow_1oo4mpj - - - - Flow_0u92n7b - Flow_0ugjw69 - - - - Flow_0t6p1sb - Flow_0ds4mp0 - - - - Flow_1sx7n9u - Flow_1oo4mpj - Flow_0u92n7b - - - len(collection.keys())==0 - - - - - Flow_0ds4mp0 - Flow_1dah8xt - Flow_0i1bv5g - - - - Flow_1dah8xt - Flow_0io0g18 - - - Flow_0io0g18 - Flow_0i1bv5g - Flow_1sx7n9u - - - - 1==1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/ParallelWithScript.bpmn b/tests/SpiffWorkflow/bpmn/data/ParallelWithScript.bpmn deleted file mode 100644 index a92df4add..000000000 --- a/tests/SpiffWorkflow/bpmn/data/ParallelWithScript.bpmn +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Flow_1swtnkk - - - - - - - - - - - Flow_1empxbr - Flow_1m1yz1x - # do nothing - - - Flow_04k0ue9 - - - - Flow_1swtnkk - Flow_1ukvcj0 - Flow_188f01l - Flow_1empxbr - - - Flow_0ykkbts - Flow_0lmf2gd - Flow_0954wrk - Flow_04k0ue9 - - - Flow_1ukvcj0 - Flow_0lmf2gd - - - Flow_188f01l - Flow_0ykkbts - - - Flow_1m1yz1x - Flow_0954wrk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/bpmnAntiLoopTask.bpmn b/tests/SpiffWorkflow/bpmn/data/bpmnAntiLoopTask.bpmn deleted file mode 100644 index 4893f713a..000000000 --- a/tests/SpiffWorkflow/bpmn/data/bpmnAntiLoopTask.bpmn +++ /dev/null @@ -1,47 +0,0 @@ - - - - - Flow_0q33jmj - - - Enter Name for member {{ Activity_TestLoop_CurrentVar }} - - - - - - Flow_0q33jmj - Flow_13213ce - - 5 - - - - - Flow_13213ce - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/bpmnLoopTask.bpmn b/tests/SpiffWorkflow/bpmn/data/bpmnLoopTask.bpmn deleted file mode 100644 index c35b237e2..000000000 --- a/tests/SpiffWorkflow/bpmn/data/bpmnLoopTask.bpmn +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Flow_0q33jmj - - - Enter Name for member {{ Activity_TestLoop_CurrentVar }} - - - - - - Flow_0q33jmj - Flow_13213ce - - - - - Flow_13213ce - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/bpmnMultiUserTask.bpmn b/tests/SpiffWorkflow/bpmn/data/bpmnMultiUserTask.bpmn deleted file mode 100644 index d9a723161..000000000 --- a/tests/SpiffWorkflow/bpmn/data/bpmnMultiUserTask.bpmn +++ /dev/null @@ -1,49 +0,0 @@ - - - - - Flow_0t6p1sb - - - - Flow_0ugjw69 - - - - Flow_0t6p1sb - Flow_0ugjw69 - - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/data_object.bpmn b/tests/SpiffWorkflow/bpmn/data/data_object.bpmn index 298c5fa2f..c558cf59d 100644 --- a/tests/SpiffWorkflow/bpmn/data/data_object.bpmn +++ b/tests/SpiffWorkflow/bpmn/data/data_object.bpmn @@ -11,6 +11,7 @@ + Flow_19pyf8s @@ -38,17 +39,20 @@ Flow_1tnu3ej Flow_19pyf8s - - - DataObjectReference_0cm8dnh - Property_1q5wp77 - Flow_0yx8lkz Flow_0yx8lkz Flow_0rk4i35 + + + DataObjectReference_0cm8dnh + Property_1q5wp77 + + + DataObjectReference_1dn9eoi + diff --git a/tests/SpiffWorkflow/bpmn/data/data_store.bpmn b/tests/SpiffWorkflow/bpmn/data/data_store.bpmn new file mode 100644 index 000000000..1bc17744d --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/data_store.bpmn @@ -0,0 +1,89 @@ + + + + + + Flow_0oekyeq + + + + Flow_0mc5gib + + + + + + Flow_0oekyeq + Flow_0ah5fbf + + referenceToDataStore + + variableTiedToDataStore = "Sue" + + + Flow_0ah5fbf + Flow_0mtq2q5 + True + + + Flow_0mtq2q5 + Flow_0mc5gib + + + referenceToDataStore + Property_1k6jy2l + + x=variableTiedToDataStore + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/data_store_read.bpmn b/tests/SpiffWorkflow/bpmn/data/data_store_read.bpmn new file mode 100644 index 000000000..2ebed2652 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/data_store_read.bpmn @@ -0,0 +1,91 @@ + + + + + + Flow_0oekyeq + + + + Flow_0mc5gib + + + + + + Flow_0oekyeq + Flow_0ah5fbf + + True + + + Flow_0ah5fbf + Flow_0mtq2q5 + True + + + Flow_0mtq2q5 + Flow_0mc5gib + + + referenceToDataStore + Property_1k6jy2l + + x=variableTiedToDataStore + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/data_store_write.bpmn b/tests/SpiffWorkflow/bpmn/data/data_store_write.bpmn new file mode 100644 index 000000000..2453a21e8 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/data_store_write.bpmn @@ -0,0 +1,91 @@ + + + + + + Flow_0oekyeq + + + + Flow_0mc5gib + + + + + + Flow_0oekyeq + Flow_0ah5fbf + + referenceToDataStore + + variableTiedToDataStore = "Sue" + + + Flow_0ah5fbf + Flow_0mtq2q5 + True + + + Flow_0mtq2q5 + Flow_0mc5gib + + + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/exclusive_into_multi.bpmn b/tests/SpiffWorkflow/bpmn/data/exclusive_into_multi.bpmn deleted file mode 100644 index 0fb12a411..000000000 --- a/tests/SpiffWorkflow/bpmn/data/exclusive_into_multi.bpmn +++ /dev/null @@ -1,83 +0,0 @@ - - - - - Flow_163toj3 - - - Flow_163toj3 - Flow_1rakb4c - x = 0 - - - - Flow_1rakb4c - Flow_04bjhw6 - Flow_0340se7 - - - - x != 0 - - - - - Flow_04bjhw6 - Flow_073oado - - 1 - - - - Flow_073oado - Flow_0340se7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/exclusive_non_default_path_into_multi.bpmn b/tests/SpiffWorkflow/bpmn/data/exclusive_non_default_path_into_multi.bpmn deleted file mode 100644 index bb4bbab0d..000000000 --- a/tests/SpiffWorkflow/bpmn/data/exclusive_non_default_path_into_multi.bpmn +++ /dev/null @@ -1,97 +0,0 @@ - - - - - Flow_0rqubl2 - - - - - - - - Flow_0rqubl2 - Flow_02orejl - - - Flow_02orejl - Flow_Yes - Flow_No - - - Flow_No - Flow_0pud9db - - - - - - - - Flow_Yes - Flow_0pud9db - - 3 - - - - - - morestuff == 'Yes' - - - morestuff == 'No' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/io_spec.bpmn b/tests/SpiffWorkflow/bpmn/data/io_spec.bpmn index dc10332f0..773f11bca 100644 --- a/tests/SpiffWorkflow/bpmn/data/io_spec.bpmn +++ b/tests/SpiffWorkflow/bpmn/data/io_spec.bpmn @@ -13,8 +13,8 @@ as a required set of inputs or outputs that must all appear together --> - id_1 - id_2 + in_1 + in_2 out_1 @@ -85,4 +85,4 @@ - + \ No newline at end of file diff --git a/tests/SpiffWorkflow/bpmn/data/io_spec_on_task.bpmn b/tests/SpiffWorkflow/bpmn/data/io_spec_on_task.bpmn new file mode 100644 index 000000000..af89b3538 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/io_spec_on_task.bpmn @@ -0,0 +1,66 @@ + + + + + Flow_0zbeoq1 + + + + Flow_0zbeoq1 + Flow_16rr3p3 + in_1, in_2, unused = 1, "hello world", True + + + + + Flow_16rr3p3 + Flow_1woo38x + + + + + + + in_1 + in_2 + + + out_1 + out_2 + + + + + Flow_1woo38x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_cardinality.bpmn b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_cardinality.bpmn new file mode 100644 index 000000000..1f0e75b51 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_cardinality.bpmn @@ -0,0 +1,44 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + 3 + output_data + + + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_invalid.bpmn b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_invalid.bpmn new file mode 100644 index 000000000..1113dd90d --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_invalid.bpmn @@ -0,0 +1,45 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + 3 + input_data + output_data + + + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_loop_input.bpmn b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_loop_input.bpmn new file mode 100644 index 000000000..e9cce84e5 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/parallel_multiinstance_loop_input.bpmn @@ -0,0 +1,44 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + input_data + output_data + + + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/reset_timer.bpmn b/tests/SpiffWorkflow/bpmn/data/reset_timer.bpmn new file mode 100644 index 000000000..7750e4bb2 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/reset_timer.bpmn @@ -0,0 +1,104 @@ + + + + + Flow_0j648np + + + Flow_0j648np + modify + Flow_13cp5nc + + + + Flow_13cp5nc + Flow_1r81vou + + + + Flow_0m5s7t9 + Flow_0p7c88x + + + Flow_1gm7381 + Flow_0p7c88x + + + Flow_0m5s7t9 + + "PT60S" + + + + + Flow_1r81vou + modify + Flow_1gm7381 + + + + modify + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_cardinality.bpmn b/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_cardinality.bpmn new file mode 100644 index 000000000..0271b3aef --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_cardinality.bpmn @@ -0,0 +1,44 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + 3 + output_data + + + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_loop_input.bpmn b/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_loop_input.bpmn new file mode 100644 index 000000000..a77f86b5f --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/sequential_multiinstance_loop_input.bpmn @@ -0,0 +1,44 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + input_data + output_data + + + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-data.json b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-data.json new file mode 100644 index 000000000..796f58471 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-data.json @@ -0,0 +1,731 @@ +{ + "serializer_version": "1.1", + "data": { + "obj_1": "object 1" + }, + "last_task": "9a4925a1-a152-428e-a764-b24d81b3cfdd", + "success": true, + "tasks": { + "4a2e2ad3-ad4b-4168-800d-71e31f33e225": { + "id": "4a2e2ad3-ad4b-4168-800d-71e31f33e225", + "parent": null, + "children": [ + "b666abf3-1e97-49c0-94b3-6e0f1a5573ec" + ], + "last_state_change": 1675380199.2266004, + "state": 32, + "task_spec": "Root", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": {} + }, + "b666abf3-1e97-49c0-94b3-6e0f1a5573ec": { + "id": "b666abf3-1e97-49c0-94b3-6e0f1a5573ec", + "parent": "4a2e2ad3-ad4b-4168-800d-71e31f33e225", + "children": [ + "c066bd8f-894d-4b24-b724-8c63fb15bdbf" + ], + "last_state_change": 1675380199.2330534, + "state": 32, + "task_spec": "Start", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": {} + }, + "c066bd8f-894d-4b24-b724-8c63fb15bdbf": { + "id": "c066bd8f-894d-4b24-b724-8c63fb15bdbf", + "parent": "b666abf3-1e97-49c0-94b3-6e0f1a5573ec", + "children": [ + "9a4925a1-a152-428e-a764-b24d81b3cfdd" + ], + "last_state_change": 1675380199.2362425, + "state": 32, + "task_spec": "Event_0xiw3t6", + "triggered": false, + "workflow_name": "parent", + "internal_data": { + "event_fired": true + }, + "data": {} + }, + "9a4925a1-a152-428e-a764-b24d81b3cfdd": { + "id": "9a4925a1-a152-428e-a764-b24d81b3cfdd", + "parent": "c066bd8f-894d-4b24-b724-8c63fb15bdbf", + "children": [ + "dcd54745-3143-4b4d-b557-f9c8ce9c7e71" + ], + "last_state_change": 1675380199.238688, + "state": 32, + "task_spec": "Activity_0haob58", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": { + "in_1": 1, + "in_2": "hello world", + "unused": true + } + }, + "dcd54745-3143-4b4d-b557-f9c8ce9c7e71": { + "id": "dcd54745-3143-4b4d-b557-f9c8ce9c7e71", + "parent": "9a4925a1-a152-428e-a764-b24d81b3cfdd", + "children": [ + "3a537753-2578-4f33-914c-5e840d2f9612" + ], + "last_state_change": 1675380199.243926, + "state": 8, + "task_spec": "Activity_1wdjypm", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": { + "in_1": 1, + "in_2": "hello world", + "unused": true + } + }, + "3a537753-2578-4f33-914c-5e840d2f9612": { + "id": "3a537753-2578-4f33-914c-5e840d2f9612", + "parent": "dcd54745-3143-4b4d-b557-f9c8ce9c7e71", + "children": [ + "f4e68050-fdc7-48e6-b0e0-7c71aa7ff3df" + ], + "last_state_change": 1675380199.2281342, + "state": 4, + "task_spec": "Event_1q277cc", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": {} + }, + "f4e68050-fdc7-48e6-b0e0-7c71aa7ff3df": { + "id": "f4e68050-fdc7-48e6-b0e0-7c71aa7ff3df", + "parent": "3a537753-2578-4f33-914c-5e840d2f9612", + "children": [ + "04c50af7-cf65-4cd7-a25e-af506581de7c" + ], + "last_state_change": 1675380199.2283747, + "state": 4, + "task_spec": "parent.EndJoin", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": {} + }, + "04c50af7-cf65-4cd7-a25e-af506581de7c": { + "id": "04c50af7-cf65-4cd7-a25e-af506581de7c", + "parent": "f4e68050-fdc7-48e6-b0e0-7c71aa7ff3df", + "children": [], + "last_state_change": 1675380199.2286203, + "state": 4, + "task_spec": "End", + "triggered": false, + "workflow_name": "parent", + "internal_data": {}, + "data": {} + } + }, + "root": "4a2e2ad3-ad4b-4168-800d-71e31f33e225", + "spec": { + "name": "parent", + "description": "Parent Process", + "file": "/home/essweine/work/sartography/code/SpiffWorkflow/tests/SpiffWorkflow/bpmn/data/io_spec_parent_data_obj.bpmn", + "task_specs": { + "Start": { + "id": "parent_1", + "name": "Start", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [ + "Event_0xiw3t6" + ], + "typename": "StartTask" + }, + "parent.EndJoin": { + "id": "parent_2", + "name": "parent.EndJoin", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_1q277cc" + ], + "outputs": [ + "End" + ], + "typename": "_EndJoin" + }, + "End": { + "id": "parent_3", + "name": "End", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "parent.EndJoin" + ], + "outputs": [], + "typename": "Simple" + }, + "Event_0xiw3t6": { + "id": "parent_4", + "name": "Event_0xiw3t6", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Start" + ], + "outputs": [ + "Activity_0haob58" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 152.0, + "y": 102.0 + }, + "outgoing_sequence_flows": { + "Activity_0haob58": { + "id": "Flow_00qjfvu", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0haob58", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_00qjfvu": { + "id": "Flow_00qjfvu", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0haob58", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "StartEvent", + "extensions": {} + }, + "Activity_0haob58": { + "id": "parent_5", + "name": "Activity_0haob58", + "description": "Set Data", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_0xiw3t6" + ], + "outputs": [ + "Activity_1wdjypm" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 240.0, + "y": 80.0 + }, + "outgoing_sequence_flows": { + "Activity_1wdjypm": { + "id": "Flow_0aj70uj", + "name": null, + "documentation": null, + "target_task_spec": "Activity_1wdjypm", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0aj70uj": { + "id": "Flow_0aj70uj", + "name": null, + "documentation": null, + "target_task_spec": "Activity_1wdjypm", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [ + { + "name": "obj_1", + "description": "obj_1", + "typename": "BpmnDataSpecification" + } + ], + "script": "in_1, in_2, unused = 1, \"hello world\", True\nobj_1='object 1'", + "typename": "ScriptTask", + "extensions": {} + }, + "Activity_1wdjypm": { + "id": "parent_6", + "name": "Activity_1wdjypm", + "description": "Update Data", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_0haob58" + ], + "outputs": [ + "Event_1q277cc" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 400.0, + "y": 80.0 + }, + "outgoing_sequence_flows": { + "Event_1q277cc": { + "id": "Flow_1uel76w", + "name": null, + "documentation": null, + "target_task_spec": "Event_1q277cc", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_1uel76w": { + "id": "Flow_1uel76w", + "name": null, + "documentation": null, + "target_task_spec": "Event_1q277cc", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "spec": "subprocess", + "typename": "CallActivity", + "extensions": {} + }, + "Event_1q277cc": { + "id": "parent_7", + "name": "Event_1q277cc", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_1wdjypm" + ], + "outputs": [ + "parent.EndJoin" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 562.0, + "y": 102.0 + }, + "outgoing_sequence_flows": { + "parent.EndJoin": { + "id": "Event_1q277cc.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "parent.EndJoin", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Event_1q277cc.ToEndJoin": { + "id": "Event_1q277cc.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "parent.EndJoin", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "EndEvent", + "extensions": {} + }, + "Root": { + "id": "parent_8", + "name": "Root", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [], + "typename": "Simple" + } + }, + "data_inputs": [], + "data_outputs": [], + "data_objects": { + "obj_1": { + "name": "obj_1", + "description": "obj_1", + "typename": "BpmnDataSpecification" + } + }, + "correlation_keys": {}, + "typename": "BpmnProcessSpec" + }, + "subprocess_specs": { + "subprocess": { + "name": "subprocess", + "description": "subprocess", + "file": "/home/essweine/work/sartography/code/SpiffWorkflow/tests/SpiffWorkflow/bpmn/data/io_spec.bpmn", + "task_specs": { + "Start": { + "id": "subprocess_1", + "name": "Start", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [ + "Event_1rtivo5" + ], + "typename": "StartTask" + }, + "subprocess.EndJoin": { + "id": "subprocess_2", + "name": "subprocess.EndJoin", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_0pgucu1" + ], + "outputs": [ + "End" + ], + "typename": "_EndJoin" + }, + "End": { + "id": "subprocess_3", + "name": "End", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "subprocess.EndJoin" + ], + "outputs": [], + "typename": "Simple" + }, + "Event_1rtivo5": { + "id": "subprocess_4", + "name": "Event_1rtivo5", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Start" + ], + "outputs": [ + "Activity_04d94ee" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 232.0, + "y": 252.0 + }, + "outgoing_sequence_flows": { + "Activity_04d94ee": { + "id": "Flow_0n038fc", + "name": null, + "documentation": null, + "target_task_spec": "Activity_04d94ee", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0n038fc": { + "id": "Flow_0n038fc", + "name": null, + "documentation": null, + "target_task_spec": "Activity_04d94ee", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "StartEvent", + "extensions": {} + }, + "Activity_04d94ee": { + "id": "subprocess_5", + "name": "Activity_04d94ee", + "description": "Task 1", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_1rtivo5" + ], + "outputs": [ + "Event_0pgucu1" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 320.0, + "y": 230.0 + }, + "outgoing_sequence_flows": { + "Event_0pgucu1": { + "id": "Flow_1d3l0mt", + "name": null, + "documentation": null, + "target_task_spec": "Event_0pgucu1", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_1d3l0mt": { + "id": "Flow_1d3l0mt", + "name": null, + "documentation": null, + "target_task_spec": "Event_0pgucu1", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "script": "out_1, out_2, unused = in_1 * 2, in_2.upper(), False\n ", + "typename": "ScriptTask", + "extensions": {} + }, + "Event_0pgucu1": { + "id": "subprocess_6", + "name": "Event_0pgucu1", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_04d94ee" + ], + "outputs": [ + "subprocess.EndJoin" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 472.0, + "y": 252.0 + }, + "outgoing_sequence_flows": { + "subprocess.EndJoin": { + "id": "Event_0pgucu1.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "subprocess.EndJoin", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Event_0pgucu1.ToEndJoin": { + "id": "Event_0pgucu1.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "subprocess.EndJoin", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "EndEvent", + "extensions": {} + }, + "Root": { + "id": "subprocess_7", + "name": "Root", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [], + "typename": "Simple" + } + }, + "data_inputs": [ + { + "name": "in_1", + "description": "input 1", + "typename": "BpmnDataSpecification" + }, + { + "name": "in_2", + "description": "input 2", + "typename": "BpmnDataSpecification" + } + ], + "data_outputs": [ + { + "name": "out_1", + "description": "output 1", + "typename": "BpmnDataSpecification" + }, + { + "name": "out_2", + "description": "output 2", + "typename": "BpmnDataSpecification" + } + ], + "data_objects": {}, + "correlation_keys": {}, + "typename": "BpmnProcessSpec" + } + }, + "subprocesses": { + "dcd54745-3143-4b4d-b557-f9c8ce9c7e71": { + "data": { + "obj_1": "object 1" + }, + "last_task": null, + "success": true, + "tasks": { + "658250f5-54df-4300-9e0a-6e122ed17e08": { + "id": "658250f5-54df-4300-9e0a-6e122ed17e08", + "parent": null, + "children": [ + "cce657f0-4534-4923-b073-0213caf8d500" + ], + "last_state_change": 1675380199.240486, + "state": 32, + "task_spec": "Root", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + }, + "cce657f0-4534-4923-b073-0213caf8d500": { + "id": "cce657f0-4534-4923-b073-0213caf8d500", + "parent": "658250f5-54df-4300-9e0a-6e122ed17e08", + "children": [ + "d0fd83e5-e4fb-49fb-9055-27993fa09430" + ], + "last_state_change": 1675380199.24384, + "state": 16, + "task_spec": "Start", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": { + "in_1": 1, + "in_2": "hello world" + } + }, + "d0fd83e5-e4fb-49fb-9055-27993fa09430": { + "id": "d0fd83e5-e4fb-49fb-9055-27993fa09430", + "parent": "cce657f0-4534-4923-b073-0213caf8d500", + "children": [ + "48649a1e-9fe5-48ef-8bd9-57b60ff4e98b" + ], + "last_state_change": 1675380199.2407098, + "state": 4, + "task_spec": "Event_1rtivo5", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + }, + "48649a1e-9fe5-48ef-8bd9-57b60ff4e98b": { + "id": "48649a1e-9fe5-48ef-8bd9-57b60ff4e98b", + "parent": "d0fd83e5-e4fb-49fb-9055-27993fa09430", + "children": [ + "984b7e3e-b037-4120-a544-792d5ee91fe5" + ], + "last_state_change": 1675380199.240903, + "state": 4, + "task_spec": "Activity_04d94ee", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + }, + "984b7e3e-b037-4120-a544-792d5ee91fe5": { + "id": "984b7e3e-b037-4120-a544-792d5ee91fe5", + "parent": "48649a1e-9fe5-48ef-8bd9-57b60ff4e98b", + "children": [ + "8b4d7999-b35b-480f-8e3d-08ad24883bce" + ], + "last_state_change": 1675380199.2411075, + "state": 4, + "task_spec": "Event_0pgucu1", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + }, + "8b4d7999-b35b-480f-8e3d-08ad24883bce": { + "id": "8b4d7999-b35b-480f-8e3d-08ad24883bce", + "parent": "984b7e3e-b037-4120-a544-792d5ee91fe5", + "children": [ + "0ad22900-dac5-4ce8-8fcf-644849cf8827" + ], + "last_state_change": 1675380199.2413251, + "state": 4, + "task_spec": "subprocess.EndJoin", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + }, + "0ad22900-dac5-4ce8-8fcf-644849cf8827": { + "id": "0ad22900-dac5-4ce8-8fcf-644849cf8827", + "parent": "8b4d7999-b35b-480f-8e3d-08ad24883bce", + "children": [], + "last_state_change": 1675380199.2415493, + "state": 4, + "task_spec": "End", + "triggered": false, + "workflow_name": "Activity_1wdjypm", + "internal_data": {}, + "data": {} + } + }, + "root": "658250f5-54df-4300-9e0a-6e122ed17e08" + } + }, + "bpmn_messages": [] +} diff --git a/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-gateways.json b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-gateways.json new file mode 100644 index 000000000..b79872556 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-gateways.json @@ -0,0 +1,830 @@ +{ + "serializer_version": "1.1", + "data": {}, + "last_task": "215867bf-41a3-42b3-8403-b836aabcfe6c", + "success": true, + "tasks": { + "01bdb086-35cc-4897-805f-d059d1cfe682": { + "id": "01bdb086-35cc-4897-805f-d059d1cfe682", + "parent": null, + "children": [ + "3846b631-5ed5-4913-9f53-f358886547cd" + ], + "last_state_change": 1675380654.3327675, + "state": 32, + "task_spec": "Root", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "3846b631-5ed5-4913-9f53-f358886547cd": { + "id": "3846b631-5ed5-4913-9f53-f358886547cd", + "parent": "01bdb086-35cc-4897-805f-d059d1cfe682", + "children": [ + "7f261ef4-047b-4941-a508-c24790f0a8c0" + ], + "last_state_change": 1675380654.338419, + "state": 32, + "task_spec": "Start", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "7f261ef4-047b-4941-a508-c24790f0a8c0": { + "id": "7f261ef4-047b-4941-a508-c24790f0a8c0", + "parent": "3846b631-5ed5-4913-9f53-f358886547cd", + "children": [ + "215867bf-41a3-42b3-8403-b836aabcfe6c" + ], + "last_state_change": 1675380654.3411734, + "state": 32, + "task_spec": "StartEvent_1", + "triggered": false, + "workflow_name": "lanes", + "internal_data": { + "event_fired": true + }, + "data": {} + }, + "215867bf-41a3-42b3-8403-b836aabcfe6c": { + "id": "215867bf-41a3-42b3-8403-b836aabcfe6c", + "parent": "7f261ef4-047b-4941-a508-c24790f0a8c0", + "children": [ + "5b0dc44b-0901-4989-8733-2dfcb82344c7" + ], + "last_state_change": 1675380654.3452208, + "state": 32, + "task_spec": "Activity_A1", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "5b0dc44b-0901-4989-8733-2dfcb82344c7": { + "id": "5b0dc44b-0901-4989-8733-2dfcb82344c7", + "parent": "215867bf-41a3-42b3-8403-b836aabcfe6c", + "children": [ + "bf645868-c2fc-4dfb-90c9-210f23b7f503" + ], + "last_state_change": 1675380654.3462226, + "state": 16, + "task_spec": "Activity_B1", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "bf645868-c2fc-4dfb-90c9-210f23b7f503": { + "id": "bf645868-c2fc-4dfb-90c9-210f23b7f503", + "parent": "5b0dc44b-0901-4989-8733-2dfcb82344c7", + "children": [ + "3825a6af-4ea6-4242-9570-411a7d080f96", + "90b2d2bc-d222-4c96-95e5-9becd7260ef6" + ], + "last_state_change": 1675380654.3340564, + "state": 4, + "task_spec": "Gateway_askQuestion", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "3825a6af-4ea6-4242-9570-411a7d080f96": { + "id": "3825a6af-4ea6-4242-9570-411a7d080f96", + "parent": "bf645868-c2fc-4dfb-90c9-210f23b7f503", + "children": [ + "a00fc3d7-c0ab-46ec-a3b1-892ff78f4809" + ], + "last_state_change": 1675380654.3344204, + "state": 1, + "task_spec": "Activity_A2", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "a00fc3d7-c0ab-46ec-a3b1-892ff78f4809": { + "id": "a00fc3d7-c0ab-46ec-a3b1-892ff78f4809", + "parent": "3825a6af-4ea6-4242-9570-411a7d080f96", + "children": [], + "last_state_change": 1675380654.3349297, + "state": 1, + "task_spec": "Implement_Feature", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "90b2d2bc-d222-4c96-95e5-9becd7260ef6": { + "id": "90b2d2bc-d222-4c96-95e5-9becd7260ef6", + "parent": "bf645868-c2fc-4dfb-90c9-210f23b7f503", + "children": [ + "3eeb1f48-6bde-4921-b2b0-ae4557c09d1f" + ], + "last_state_change": 1675380654.3346882, + "state": 2, + "task_spec": "Implement_Feature", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + }, + "3eeb1f48-6bde-4921-b2b0-ae4557c09d1f": { + "id": "3eeb1f48-6bde-4921-b2b0-ae4557c09d1f", + "parent": "90b2d2bc-d222-4c96-95e5-9becd7260ef6", + "children": [], + "last_state_change": 1675380654.3352633, + "state": 2, + "task_spec": "Activity_1uksrqx", + "triggered": false, + "workflow_name": "lanes", + "internal_data": {}, + "data": {} + } + }, + "root": "01bdb086-35cc-4897-805f-d059d1cfe682", + "spec": { + "name": "lanes", + "description": "lanes", + "file": "/home/essweine/work/sartography/code/SpiffWorkflow/tests/SpiffWorkflow/bpmn/data/lanes.bpmn", + "task_specs": { + "Start": { + "id": "lanes_1", + "name": "Start", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [ + "StartEvent_1" + ], + "typename": "StartTask" + }, + "lanes.EndJoin": { + "id": "lanes_2", + "name": "lanes.EndJoin", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_07pakcl" + ], + "outputs": [ + "End" + ], + "typename": "_EndJoin" + }, + "End": { + "id": "lanes_3", + "name": "End", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "lanes.EndJoin" + ], + "outputs": [], + "typename": "Simple" + }, + "StartEvent_1": { + "id": "lanes_4", + "name": "StartEvent_1", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Start" + ], + "outputs": [ + "Activity_A1" + ], + "lane": "A", + "documentation": null, + "loopTask": false, + "position": { + "x": 219.0, + "y": 92.0 + }, + "outgoing_sequence_flows": { + "Activity_A1": { + "id": "Flow_0jwejm5", + "name": null, + "documentation": null, + "target_task_spec": "Activity_A1", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0jwejm5": { + "id": "Flow_0jwejm5", + "name": null, + "documentation": null, + "target_task_spec": "Activity_A1", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "StartEvent", + "extensions": {} + }, + "Activity_A1": { + "id": "lanes_5", + "name": "Activity_A1", + "description": "Request Feature", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "StartEvent_1" + ], + "outputs": [ + "Activity_B1" + ], + "lane": "A", + "documentation": null, + "loopTask": false, + "position": { + "x": 300.0, + "y": 70.0 + }, + "outgoing_sequence_flows": { + "Activity_B1": { + "id": "Flow_140vffb", + "name": null, + "documentation": null, + "target_task_spec": "Activity_B1", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_140vffb": { + "id": "Flow_140vffb", + "name": null, + "documentation": null, + "target_task_spec": "Activity_B1", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "UserTask", + "extensions": {} + }, + "Activity_B1": { + "id": "lanes_6", + "name": "Activity_B1", + "description": "Clarifying Questions?", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_A1" + ], + "outputs": [ + "Gateway_askQuestion" + ], + "lane": "B", + "documentation": null, + "loopTask": false, + "position": { + "x": 300.0, + "y": 210.0 + }, + "outgoing_sequence_flows": { + "Gateway_askQuestion": { + "id": "Flow_1k9gsm1", + "name": null, + "documentation": null, + "target_task_spec": "Gateway_askQuestion", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_1k9gsm1": { + "id": "Flow_1k9gsm1", + "name": null, + "documentation": null, + "target_task_spec": "Gateway_askQuestion", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "UserTask", + "extensions": {} + }, + "Gateway_askQuestion": { + "id": "lanes_7", + "name": "Gateway_askQuestion", + "description": "Do we need Clarifcation?", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_B1" + ], + "outputs": [ + "Activity_A2", + "Implement_Feature" + ], + "lane": "B", + "documentation": null, + "loopTask": false, + "position": { + "x": 465.0, + "y": 225.0 + }, + "outgoing_sequence_flows": { + "Activity_A2": { + "id": "Flow_0okhwy0", + "name": "Yes", + "documentation": null, + "target_task_spec": "Activity_A2", + "typename": "SequenceFlow" + }, + "Implement_Feature": { + "id": "Flow_182bqvo", + "name": "No", + "documentation": null, + "target_task_spec": "Implement_Feature", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0okhwy0": { + "id": "Flow_0okhwy0", + "name": "Yes", + "documentation": null, + "target_task_spec": "Activity_A2", + "typename": "SequenceFlow" + }, + "Flow_182bqvo": { + "id": "Flow_182bqvo", + "name": "No", + "documentation": null, + "target_task_spec": "Implement_Feature", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "default_task_spec": "Implement_Feature", + "cond_task_specs": [ + { + "condition": "NeedClarification == 'Yes'", + "task_spec": "Activity_A2" + } + ], + "choice": null, + "typename": "ExclusiveGateway", + "extensions": {} + }, + "Implement_Feature": { + "id": "lanes_8", + "name": "Implement_Feature", + "description": "Implement Feature", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_A2", + "Gateway_askQuestion" + ], + "outputs": [ + "Activity_1uksrqx" + ], + "lane": "B", + "documentation": null, + "loopTask": false, + "position": { + "x": 620.0, + "y": 200.0 + }, + "outgoing_sequence_flows": { + "Activity_1uksrqx": { + "id": "Flow_0xz2oco", + "name": null, + "documentation": null, + "target_task_spec": "Activity_1uksrqx", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0xz2oco": { + "id": "Flow_0xz2oco", + "name": null, + "documentation": null, + "target_task_spec": "Activity_1uksrqx", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "ManualTask", + "extensions": {} + }, + "Activity_1uksrqx": { + "id": "lanes_9", + "name": "Activity_1uksrqx", + "description": "Send to testing", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Implement_Feature" + ], + "outputs": [ + "Activity_0i0rxuw" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 620.0, + "y": 340.0 + }, + "outgoing_sequence_flows": { + "Activity_0i0rxuw": { + "id": "Flow_1cybznq", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0i0rxuw", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_1cybznq": { + "id": "Flow_1cybznq", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0i0rxuw", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "ManualTask", + "extensions": {} + }, + "Activity_0i0rxuw": { + "id": "lanes_10", + "name": "Activity_0i0rxuw", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_1uksrqx" + ], + "outputs": [ + "Event_07pakcl" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 760.0, + "y": 320.0 + }, + "outgoing_sequence_flows": { + "Event_07pakcl": { + "id": "Flow_0e1uyol", + "name": null, + "documentation": null, + "target_task_spec": "Event_07pakcl", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_0e1uyol": { + "id": "Flow_0e1uyol", + "name": null, + "documentation": null, + "target_task_spec": "Event_07pakcl", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "spec": "Activity_0i0rxuw", + "typename": "CallActivity", + "extensions": {} + }, + "Event_07pakcl": { + "id": "lanes_11", + "name": "Event_07pakcl", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_0i0rxuw" + ], + "outputs": [ + "lanes.EndJoin" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 1092.0, + "y": 362.0 + }, + "outgoing_sequence_flows": { + "lanes.EndJoin": { + "id": "Event_07pakcl.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "lanes.EndJoin", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Event_07pakcl.ToEndJoin": { + "id": "Event_07pakcl.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "lanes.EndJoin", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "EndEvent", + "extensions": {} + }, + "Activity_A2": { + "id": "lanes_12", + "name": "Activity_A2", + "description": "Clarify Request", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Gateway_askQuestion" + ], + "outputs": [ + "Implement_Feature" + ], + "lane": "A", + "documentation": null, + "loopTask": false, + "position": { + "x": 530.0, + "y": 70.0 + }, + "outgoing_sequence_flows": { + "Implement_Feature": { + "id": "Flow_17rng3c", + "name": null, + "documentation": null, + "target_task_spec": "Implement_Feature", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_17rng3c": { + "id": "Flow_17rng3c", + "name": null, + "documentation": null, + "target_task_spec": "Implement_Feature", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "UserTask", + "extensions": {} + }, + "Root": { + "id": "lanes_13", + "name": "Root", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [], + "typename": "Simple" + } + }, + "data_inputs": [], + "data_outputs": [], + "data_objects": {}, + "correlation_keys": {}, + "typename": "BpmnProcessSpec" + }, + "subprocess_specs": { + "Activity_0i0rxuw": { + "name": "Activity_0i0rxuw", + "description": "Activity_0i0rxuw", + "file": "/home/essweine/work/sartography/code/SpiffWorkflow/tests/SpiffWorkflow/bpmn/data/lanes.bpmn", + "task_specs": { + "Start": { + "id": "Activity_0i0rxuw_1", + "name": "Start", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [ + "Event_0lbloj7" + ], + "typename": "StartTask" + }, + "Activity_0i0rxuw.EndJoin": { + "id": "Activity_0i0rxuw_2", + "name": "Activity_0i0rxuw.EndJoin", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_1vz21ww" + ], + "outputs": [ + "End" + ], + "typename": "_EndJoin" + }, + "End": { + "id": "Activity_0i0rxuw_3", + "name": "End", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Activity_0i0rxuw.EndJoin" + ], + "outputs": [], + "typename": "Simple" + }, + "Event_0lbloj7": { + "id": "Activity_0i0rxuw_4", + "name": "Event_0lbloj7", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Start" + ], + "outputs": [ + "SubProcessTask" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 782.0, + "y": 362.0 + }, + "outgoing_sequence_flows": { + "SubProcessTask": { + "id": "Flow_086ghyu", + "name": null, + "documentation": null, + "target_task_spec": "SubProcessTask", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_086ghyu": { + "id": "Flow_086ghyu", + "name": null, + "documentation": null, + "target_task_spec": "SubProcessTask", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "StartEvent", + "extensions": {} + }, + "SubProcessTask": { + "id": "Activity_0i0rxuw_5", + "name": "SubProcessTask", + "description": "SubProcessTask", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_0lbloj7" + ], + "outputs": [ + "Event_1vz21ww" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 850.0, + "y": 340.0 + }, + "outgoing_sequence_flows": { + "Event_1vz21ww": { + "id": "Flow_1jw6qrj", + "name": null, + "documentation": null, + "target_task_spec": "Event_1vz21ww", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Flow_1jw6qrj": { + "id": "Flow_1jw6qrj", + "name": null, + "documentation": null, + "target_task_spec": "Event_1vz21ww", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "ManualTask", + "extensions": {} + }, + "Event_1vz21ww": { + "id": "Activity_0i0rxuw_6", + "name": "Event_1vz21ww", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "SubProcessTask" + ], + "outputs": [ + "Activity_0i0rxuw.EndJoin" + ], + "lane": "C", + "documentation": null, + "loopTask": false, + "position": { + "x": 982.0, + "y": 362.0 + }, + "outgoing_sequence_flows": { + "Activity_0i0rxuw.EndJoin": { + "id": "Event_1vz21ww.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0i0rxuw.EndJoin", + "typename": "SequenceFlow" + } + }, + "outgoing_sequence_flows_by_id": { + "Event_1vz21ww.ToEndJoin": { + "id": "Event_1vz21ww.ToEndJoin", + "name": null, + "documentation": null, + "target_task_spec": "Activity_0i0rxuw.EndJoin", + "typename": "SequenceFlow" + } + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "EndEvent", + "extensions": {} + } + }, + "data_inputs": [], + "data_outputs": [], + "data_objects": {}, + "correlation_keys": {}, + "typename": "BpmnProcessSpec" + } + }, + "subprocesses": {}, + "bpmn_messages": [] +} diff --git a/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-multi.json b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-multi.json new file mode 100644 index 000000000..122d5a21f --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-multi.json @@ -0,0 +1,350 @@ +{ + "serializer_version": "1.1", + "data": {}, + "last_task": "ca089728-9745-4d50-8fbc-f2f7234dec8f", + "success": true, + "tasks": { + "fa4b8656-22a2-467e-8fb0-9b1d8f1f6da6": { + "id": "fa4b8656-22a2-467e-8fb0-9b1d8f1f6da6", + "parent": null, + "children": [ + "ccf50f31-880b-406a-9e61-2f3d42f39d70" + ], + "last_state_change": 1676389310.7311432, + "state": 32, + "task_spec": "Root", + "triggered": false, + "workflow_name": "main", + "internal_data": {}, + "data": {} + }, + "ccf50f31-880b-406a-9e61-2f3d42f39d70": { + "id": "ccf50f31-880b-406a-9e61-2f3d42f39d70", + "parent": "fa4b8656-22a2-467e-8fb0-9b1d8f1f6da6", + "children": [ + "ca089728-9745-4d50-8fbc-f2f7234dec8f" + ], + "last_state_change": 1676389310.735502, + "state": 32, + "task_spec": "Start", + "triggered": false, + "workflow_name": "main", + "internal_data": {}, + "data": { + "input_data": [ + 1, + 2, + 3 + ] + } + }, + "ca089728-9745-4d50-8fbc-f2f7234dec8f": { + "id": "ca089728-9745-4d50-8fbc-f2f7234dec8f", + "parent": "ccf50f31-880b-406a-9e61-2f3d42f39d70", + "children": [ + "513dba6b-7017-48df-a1e0-7a2c57a1042c" + ], + "last_state_change": 1676389310.739117, + "state": 32, + "task_spec": "StartEvent_1", + "triggered": false, + "workflow_name": "main", + "internal_data": { + "event_fired": true + }, + "data": { + "input_data": [ + 1, + 2, + 3 + ] + } + }, + "513dba6b-7017-48df-a1e0-7a2c57a1042c": { + "id": "513dba6b-7017-48df-a1e0-7a2c57a1042c", + "parent": "ca089728-9745-4d50-8fbc-f2f7234dec8f", + "children": [ + "638ea876-beb2-4fd6-9dc3-5fd528d7cfb9" + ], + "last_state_change": 1676389310.7412922, + "state": 16, + "task_spec": "Gateway_for_any_task_start", + "triggered": false, + "workflow_name": "main", + "internal_data": {}, + "data": { + "input_data": [ + 1, + 2, + 3 + ] + } + }, + "638ea876-beb2-4fd6-9dc3-5fd528d7cfb9": { + "id": "638ea876-beb2-4fd6-9dc3-5fd528d7cfb9", + "parent": "513dba6b-7017-48df-a1e0-7a2c57a1042c", + "children": [ + "ec145fea-d068-4401-9f6c-6903cf153b23" + ], + "last_state_change": 1676389310.7315657, + "state": 4, + "task_spec": "any_task", + "triggered": false, + "workflow_name": "main", + "internal_data": { + "splits": 1, + "runtimes": 1 + }, + "data": { + "item": 1 + } + }, + "ec145fea-d068-4401-9f6c-6903cf153b23": { + "id": "ec145fea-d068-4401-9f6c-6903cf153b23", + "parent": "638ea876-beb2-4fd6-9dc3-5fd528d7cfb9", + "children": [ + "eccb7e2f-4b23-4b75-b9fb-e3b3a335574f" + ], + "last_state_change": 1676389310.7325432, + "state": 1, + "task_spec": "Gateway_for_any_task_end", + "triggered": false, + "workflow_name": "main", + "internal_data": {}, + "data": {} + }, + "eccb7e2f-4b23-4b75-b9fb-e3b3a335574f": { + "id": "eccb7e2f-4b23-4b75-b9fb-e3b3a335574f", + "parent": "ec145fea-d068-4401-9f6c-6903cf153b23", + "children": [], + "last_state_change": 1676389310.732967, + "state": 1, + "task_spec": "Event_0a6d9t5", + "triggered": false, + "workflow_name": "main", + "internal_data": {}, + "data": {} + } + }, + "root": "fa4b8656-22a2-467e-8fb0-9b1d8f1f6da6", + "spec": { + "name": "main", + "description": "main", + "file": "/home/essweine/work/sartography/code/SpiffWorkflow/tests/SpiffWorkflow/bpmn/data/diagram_1.bpmn", + "task_specs": { + "Start": { + "id": "main_1", + "name": "Start", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [ + "StartEvent_1" + ], + "typename": "StartTask" + }, + "main.EndJoin": { + "id": "main_2", + "name": "main.EndJoin", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Event_0a6d9t5" + ], + "outputs": [ + "End" + ], + "typename": "_EndJoin" + }, + "End": { + "id": "main_3", + "name": "End", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "main.EndJoin" + ], + "outputs": [], + "typename": "Simple" + }, + "StartEvent_1": { + "id": "main_4", + "name": "StartEvent_1", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "Start" + ], + "outputs": [ + "Gateway_for_any_task_start" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 179.0, + "y": 99.0 + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "StartEvent", + "extensions": {} + }, + "any_task": { + "id": "main_5", + "name": "any_task", + "description": "Any Task", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "StartEvent_1", + "Gateway_for_any_task_start" + ], + "outputs": [ + "Gateway_for_any_task_end" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 270.0, + "y": 77.0 + }, + "data_input_associations": [], + "data_output_associations": [], + "typename": "NoneTask", + "times": { + "name": "input_data", + "typename": "Attrib" + }, + "elementVar": "item", + "collection": { + "name": "output_data", + "typename": "Attrib" + }, + "completioncondition": null, + "prevtaskclass": "SpiffWorkflow.bpmn.specs.NoneTask.NoneTask", + "isSequential": false, + "expanded": 1, + "extensions": {} + }, + "Event_0a6d9t5": { + "id": "main_6", + "name": "Event_0a6d9t5", + "description": null, + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "any_task" + ], + "outputs": [ + "main.EndJoin" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 432.0, + "y": 99.0 + }, + "data_input_associations": [], + "data_output_associations": [], + "event_definition": { + "internal": false, + "external": false, + "typename": "NoneEventDefinition" + }, + "typename": "EndEvent", + "extensions": {} + }, + "Root": { + "id": "main_7", + "name": "Root", + "description": "", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [], + "outputs": [], + "typename": "Simple" + }, + "Gateway_for_any_task_start": { + "id": "main_8", + "name": "Gateway_for_any_task_start", + "description": "Begin Gateway", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "StartEvent_1" + ], + "outputs": [ + "any_task" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 0, + "y": 0 + }, + "data_input_associations": [], + "data_output_associations": [], + "split_task": null, + "threshold": null, + "cancel": false, + "typename": "ParallelGateway" + }, + "Gateway_for_any_task_end": { + "id": "main_9", + "name": "Gateway_for_any_task_end", + "description": "End Gateway", + "manual": false, + "internal": false, + "lookahead": 2, + "inputs": [ + "any_task" + ], + "outputs": [ + "Event_0a6d9t5" + ], + "lane": null, + "documentation": null, + "loopTask": false, + "position": { + "x": 0, + "y": 0 + }, + "data_input_associations": [], + "data_output_associations": [], + "split_task": null, + "threshold": null, + "cancel": false, + "typename": "ParallelGateway" + } + }, + "data_inputs": [], + "data_outputs": [], + "data_objects": {}, + "correlation_keys": {}, + "typename": "BpmnProcessSpec" + }, + "subprocess_specs": {}, + "subprocesses": {}, + "bpmn_messages": [] +} diff --git a/tests/SpiffWorkflow/bpmn/data/serialization/v1-1.json b/tests/SpiffWorkflow/bpmn/data/serialization/v1.1-timers.json similarity index 100% rename from tests/SpiffWorkflow/bpmn/data/serialization/v1-1.json rename to tests/SpiffWorkflow/bpmn/data/serialization/v1.1-timers.json diff --git a/tests/SpiffWorkflow/bpmn/data/standard_loop.bpmn b/tests/SpiffWorkflow/bpmn/data/standard_loop.bpmn new file mode 100644 index 000000000..1e08e3e27 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/standard_loop.bpmn @@ -0,0 +1,41 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + done + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/standard_loop_invalid.bpmn b/tests/SpiffWorkflow/bpmn/data/standard_loop_invalid.bpmn new file mode 100644 index 000000000..3696e100e --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/standard_loop_invalid.bpmn @@ -0,0 +1,39 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/sub_within_sub_multi.bpmn b/tests/SpiffWorkflow/bpmn/data/sub_within_sub_multi.bpmn deleted file mode 100644 index 95e29da0d..000000000 --- a/tests/SpiffWorkflow/bpmn/data/sub_within_sub_multi.bpmn +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Flow_0dsbqk4 - - - - Flow_18e9qgr - - - Flow_1ona7kk - Flow_18e9qgr - - - Flow_05tjul5 - - - Flow_1pc1vib - - - Flow_1pc1vib - Flow_05tjul5 - - Flow_0hikak1 - - - Flow_0hikak1 - Flow_0oby5rd - my_var['new_info'] = "Adding this!" -my_var['name'] = my_var['name'] + "_edit" - - - - - Flow_0oby5rd - - - - - - - - - - Flow_0dsbqk4 - Flow_1ona7kk - my_collection = { - 'a':{'name':'Apple'}, - 'b':{'name':'Bubble'}, - 'c':{'name':'Crap, I should write better code'} -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi.bpmn b/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi.bpmn deleted file mode 100644 index 1fb69933c..000000000 --- a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi.bpmn +++ /dev/null @@ -1,93 +0,0 @@ - - - - - Flow_0dsbqk4 - - - - Flow_18e9qgr - - - Flow_1ona7kk - Flow_18e9qgr - - - Flow_14l2ton - Flow_06gypww - my_var['new_info'] = "Adding this!" -my_var['name'] = my_var['name'] + "_edit" - - - Flow_06gypww - - - Flow_14l2ton - - - - - - - - Flow_0dsbqk4 - Flow_1ona7kk - my_collection = { - 'a':{'name':'Apple'}, - 'b':{'name':'Bubble'}, - 'c':{'name':'Crap, I should write better code'} -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi1.bpmn b/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi1.bpmn deleted file mode 100644 index 478e18ffa..000000000 --- a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi1.bpmn +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Flow_0dsbqk4 - - - - Flow_1lbqsop - - - Flow_0n1o8w6 - Flow_1lbqsop - - 5 - done==True - - x = {'a':a} -if a==3: - done=True -a=x - - - - - Flow_0dsbqk4 - Flow_0n1o8w6 - done=False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi_parallel.bpmn b/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi_parallel.bpmn deleted file mode 100644 index b89d98f66..000000000 --- a/tests/SpiffWorkflow/bpmn/data/sub_workflow_multi_parallel.bpmn +++ /dev/null @@ -1,93 +0,0 @@ - - - - - Flow_0dsbqk4 - - - - Flow_18e9qgr - - - Flow_1ona7kk - Flow_18e9qgr - - - Flow_14l2ton - Flow_06gypww - my_var['new_info'] = "Adding this!" -my_var['name'] = my_var['name'] + "_edit" - - - Flow_06gypww - - - Flow_14l2ton - - - - - - - - Flow_0dsbqk4 - Flow_1ona7kk - my_collection = { - 'a':{'name':'Apple'}, - 'b':{'name':'Bubble'}, - 'c':{'name':'Crap, I should write better code'} -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/data/two_top_level_procs.bpmn b/tests/SpiffWorkflow/bpmn/data/two_top_level_procs.bpmn deleted file mode 100644 index 363ccc120..000000000 --- a/tests/SpiffWorkflow/bpmn/data/two_top_level_procs.bpmn +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - Flow_1fumg40 - - - - Flow_1sfcxwo - - - - Flow_1fumg40 - Flow_1sfcxwo - - - - - Flow_0ptjvq1 - - - - Flow_12xe6lg - - - - Flow_0ptjvq1 - Flow_12xe6lg - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py b/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py index 29febd248..529852ee2 100644 --- a/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py +++ b/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py @@ -8,7 +8,7 @@ from SpiffWorkflow.task import TaskState from ..BpmnWorkflowTestCase import BpmnWorkflowTestCase -class EventBsedGatewayTest(BpmnWorkflowTestCase): +class EventBasedGatewayTest(BpmnWorkflowTestCase): def setUp(self): self.spec, self.subprocesses = self.load_workflow_spec('event-gateway.bpmn', 'Process_0pvx19v') diff --git a/tests/SpiffWorkflow/bpmn/events/TransactionSubprocssTest.py b/tests/SpiffWorkflow/bpmn/events/TransactionSubprocssTest.py index 1212d776c..02a8389fb 100644 --- a/tests/SpiffWorkflow/bpmn/events/TransactionSubprocssTest.py +++ b/tests/SpiffWorkflow/bpmn/events/TransactionSubprocssTest.py @@ -29,17 +29,17 @@ class TransactionSubprocessTest(BpmnWorkflowTestCase): # Check that workflow and next task completed subprocess = self.workflow.get_tasks_from_spec_name('Subprocess')[0] - self.assertEqual(subprocess.get_state(), TaskState.COMPLETED) + self.assertEqual(subprocess.state, TaskState.COMPLETED) print_task = self.workflow.get_tasks_from_spec_name("Activity_Print_Data")[0] - self.assertEqual(print_task.get_state(), TaskState.COMPLETED) + self.assertEqual(print_task.state, TaskState.COMPLETED) # Check that the boundary events were cancelled cancel_task = self.workflow.get_tasks_from_spec_name("Catch_Cancel_Event")[0] - self.assertEqual(cancel_task.get_state(), TaskState.CANCELLED) + self.assertEqual(cancel_task.state, TaskState.CANCELLED) error_1_task = self.workflow.get_tasks_from_spec_name("Catch_Error_1")[0] - self.assertEqual(error_1_task.get_state(), TaskState.CANCELLED) + self.assertEqual(error_1_task.state, TaskState.CANCELLED) error_none_task = self.workflow.get_tasks_from_spec_name("Catch_Error_None")[0] - self.assertEqual(error_none_task.get_state(), TaskState.CANCELLED) + self.assertEqual(error_none_task.state, TaskState.CANCELLED) def testSubworkflowCancelEvent(self): @@ -56,13 +56,13 @@ class TransactionSubprocessTest(BpmnWorkflowTestCase): # Check that we completed the Cancel Task cancel_task = self.workflow.get_tasks_from_spec_name("Cancel_Action")[0] - self.assertEqual(cancel_task.get_state(), TaskState.COMPLETED) + self.assertEqual(cancel_task.state, TaskState.COMPLETED) # And cancelled the remaining tasks error_1_task = self.workflow.get_tasks_from_spec_name("Catch_Error_1")[0] - self.assertEqual(error_1_task.get_state(), TaskState.CANCELLED) + self.assertEqual(error_1_task.state, TaskState.CANCELLED) error_none_task = self.workflow.get_tasks_from_spec_name("Catch_Error_None")[0] - self.assertEqual(error_none_task.get_state(), TaskState.CANCELLED) + self.assertEqual(error_none_task.state, TaskState.CANCELLED) # We should not have this task, as we followed the 'cancel branch' print_task = self.workflow.get_tasks_from_spec_name("Activity_Print_Data") @@ -87,13 +87,13 @@ class TransactionSubprocessTest(BpmnWorkflowTestCase): # The cancel boundary event should be cancelled cancel_task = self.workflow.get_tasks_from_spec_name("Catch_Cancel_Event")[0] - self.assertEqual(cancel_task.get_state(), TaskState.CANCELLED) + self.assertEqual(cancel_task.state, TaskState.CANCELLED) # We should catch the None Error, but not Error 1 error_none_task = self.workflow.get_tasks_from_spec_name("Catch_Error_None")[0] - self.assertEqual(error_none_task.get_state(), TaskState.COMPLETED) + self.assertEqual(error_none_task.state, TaskState.COMPLETED) error_1_task = self.workflow.get_tasks_from_spec_name("Catch_Error_1")[0] - self.assertEqual(error_1_task.get_state(), TaskState.CANCELLED) + self.assertEqual(error_1_task.state, TaskState.CANCELLED) # Make sure this branch didn't getfollowed print_task = self.workflow.get_tasks_from_spec_name("Activity_Print_Data") @@ -117,9 +117,9 @@ class TransactionSubprocessTest(BpmnWorkflowTestCase): # Both boundary events should complete error_none_task = self.workflow.get_tasks_from_spec_name("Catch_Error_None")[0] - self.assertEqual(error_none_task.get_state(), TaskState.COMPLETED) + self.assertEqual(error_none_task.state, TaskState.COMPLETED) error_1_task = self.workflow.get_tasks_from_spec_name("Catch_Error_1")[0] - self.assertEqual(error_1_task.get_state(), TaskState.COMPLETED) + self.assertEqual(error_1_task.state, TaskState.COMPLETED) print_task = self.workflow.get_tasks_from_spec_name("Activity_Print_Data") self.assertEqual(len(print_task), 0) diff --git a/tests/SpiffWorkflow/bpmn/serializer/VersionMigrationTest.py b/tests/SpiffWorkflow/bpmn/serializer/VersionMigrationTest.py index cae051baf..2b169f149 100644 --- a/tests/SpiffWorkflow/bpmn/serializer/VersionMigrationTest.py +++ b/tests/SpiffWorkflow/bpmn/serializer/VersionMigrationTest.py @@ -4,15 +4,16 @@ import time from SpiffWorkflow.task import TaskState from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.PythonScriptEngineEnvironment import TaskDataEnvironment +from SpiffWorkflow.bpmn.serializer.migration.exceptions import VersionMigrationError from .BaseTestCase import BaseTestCase -class VersionMigrationTest(BaseTestCase): +class Version_1_0_Test(BaseTestCase): SERIALIZER_VERSION = "1.2" - def test_convert_1_0_to_1_1(self): + def test_convert_subprocess(self): # The serialization used here comes from NestedSubprocessTest saved at line 25 with version 1.0 fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.0.json') wf = self.serializer.deserialize_json(open(fn).read()) @@ -23,10 +24,38 @@ class VersionMigrationTest(BaseTestCase): wf.do_engine_steps() self.assertEqual(True, wf.is_completed()) - def test_convert_1_1_to_1_2(self): - fn = os.path.join(self.DATA_DIR, 'serialization', 'v1-1.json') + +class Version_1_1_Test(BaseTestCase): + + def test_timers(self): + fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-timers.json') wf = self.serializer.deserialize_json(open(fn).read()) wf.script_engine = PythonScriptEngine(environment=TaskDataEnvironment({"time": time})) wf.refresh_waiting_tasks() wf.do_engine_steps() self.assertTrue(wf.is_completed()) + + def test_convert_data_specs(self): + fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-data.json') + wf = self.serializer.deserialize_json(open(fn).read()) + wf.do_engine_steps() + self.assertTrue(wf.is_completed()) + + def test_convert_exclusive_gateway(self): + fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-gateways.json') + wf = self.serializer.deserialize_json(open(fn).read()) + wf.do_engine_steps() + task = wf.get_tasks_from_spec_name('Gateway_askQuestion')[0] + self.assertEqual(len(task.task_spec.cond_task_specs), 2) + ready_task = wf.get_ready_user_tasks()[0] + ready_task.data['NeedClarification'] = 'Yes' + ready_task.complete() + wf.do_engine_steps() + ready_task = wf.get_ready_user_tasks()[0] + self.assertEqual(ready_task.task_spec.name, 'Activity_A2') + + def test_check_multiinstance(self): + fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-multi.json') + with self.assertRaises(VersionMigrationError) as ctx: + wf = self.serializer.deserialize_json(open(fn).read()) + self.assertEqual(ctx.exception.message, "This workflow cannot be migrated because it contains MultiInstance Tasks") \ No newline at end of file diff --git a/tests/SpiffWorkflow/camunda/DefaultGatewayPMITest.py b/tests/SpiffWorkflow/camunda/DefaultGatewayPMITest.py deleted file mode 100644 index 96852cc2c..000000000 --- a/tests/SpiffWorkflow/camunda/DefaultGatewayPMITest.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - - -import unittest - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow - -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - -__author__ = 'matth' - -class DefaultGatewayPMITest(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('default_gateway_pmi.bpmn', 'DefaultGateway') - self.workflow = BpmnWorkflow(spec, subprocesses) - self.workflow.do_engine_steps() - - def testRunThroughHappy(self): - self.actual_test(False) - - def testRunThroughSaveRestore(self): - self.actual_test(True) - - def actual_test(self, save_restore=False): - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("DoStuff", task.task_spec.name) - task.update_data({"morestuff": 'Yep'}) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - # Set the names of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i == 0: - self.assertEqual("GetMoreStuff", task.task_spec.name) - else: - self.assertEqual("GetMoreStuff_%d"%(i-1), task.task_spec.name) - - - task.update_data({"stuff.addstuff": "Stuff %d"%i}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - self.workflow.do_engine_steps() - - if save_restore: self.save_restore() - self.assertTrue(self.workflow.is_completed()) - - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(DefaultGatewayPMITest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/ExclusiveGatewayPMITest.py b/tests/SpiffWorkflow/camunda/ExclusiveGatewayPMITest.py deleted file mode 100644 index 1b65ba575..000000000 --- a/tests/SpiffWorkflow/camunda/ExclusiveGatewayPMITest.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow - -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - -__author__ = 'matth' - - -class ExclusiveGatewayPMITest(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('default_gateway_pmi.bpmn', 'DefaultGateway') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - self.actual_test(False) - - def testRunThroughSaveRestore(self): - self.actual_test(True) - - def testRunThroughHappyNo(self): - self.actual_test(False,'No') - - def testRunThroughSaveRestoreNo(self): - self.actual_test(True,'No') - - def actual_test(self, save_restore=False,response='Yes'): - - self.workflow.do_engine_steps() - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("DoStuff", task.task_spec.name) - task.update_data({"morestuff": response}) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - # Set the names of the 3 family members. - if response == 'Yes': - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i == 0: - self.assertEqual("GetMoreStuff", task.task_spec.name) - else: - self.assertEqual("GetMoreStuff_%d"%(i-1), task.task_spec.name) - - - task.update_data({"stuff.addstuff": "Stuff %d"%i}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - self.workflow.do_engine_steps() - - if save_restore: self.save_restore() - self.assertTrue(self.workflow.is_completed()) - - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ExclusiveGatewayPMITest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/MultiInstanceArrayTest.py b/tests/SpiffWorkflow/camunda/MultiInstanceArrayTest.py deleted file mode 100644 index 3244f16d3..000000000 --- a/tests/SpiffWorkflow/camunda/MultiInstanceArrayTest.py +++ /dev/null @@ -1,222 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from SpiffWorkflow.exceptions import WorkflowException - -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - -__author__ = 'matth' - - -class MultiInstanceArrayTest(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('multi_instance_array.bpmn', 'MultiInstanceArray') - self.workflow = BpmnWorkflow(spec, subprocesses) - self.workflow.do_engine_steps() - - def testRunThroughHappy(self): - self.actual_test(False) - - def testRunThroughSaveRestore(self): - self.actual_test(True) - - - def testRunThroughHappyList(self): - self.actual_test2(False) - - def testRunThroughSaveRestoreList(self): - self.actual_test2(True) - - def testRunThroughHappyDict(self): - self.actual_test_with_dict(False) - - def testRunThroughSaveRestoreDict(self): - self.actual_test_with_dict(True) - - def testGetTaskExtensions(self): - self.actual_test_for_extensions(False) - - - def actual_test(self, save_restore=False): - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - taskinfo = task.task_info() - self.assertEqual(taskinfo,{'is_looping':False, - 'is_sequential_mi':False, - 'is_parallel_mi':False, - 'mi_count':0, - 'mi_index':0}) - self.assertEqual("Activity_FamSize", task.task_spec.name) - task.update_data({"Family": {"Size": 3}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - # Set the names of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - taskinfo = task.task_info() - self.assertEqual(taskinfo, {'is_looping': False, - 'is_sequential_mi': True, - 'is_parallel_mi': False, - 'mi_count': 3, - 'mi_index': i+1}) - if i > 0: - self.assertEqual("FamilyMemberTask"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberTask", task.task_spec.name) - - - task.update_data({"FamilyMember": {"FirstName": "The Funk #%i" % i}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - self.workflow.do_engine_steps() - - self.assertEqual({'1': {'FirstName': 'The Funk #0'}, - '2': {'FirstName': 'The Funk #1'}, - '3': {'FirstName': 'The Funk #2'}}, - task.data["Family"]["Members"]) - #### NB - start here - ### Data is not correctly getting to the next task upon complete of the last task - ### after do_engine_steps, the next task in the list should be the same as task.data - ### but it is not. - - ### invalid copy of data?? ## appears that parent is not hooked up correctly - - # Set the birthdays of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i > 0: - self.assertEqual("FamilyMemberBday"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberBday", task.task_spec.name) - task.update_data({"CurrentFamilyMember": {"Birthdate": "10/0%i/1985" % i}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - self.workflow.do_engine_steps() - - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - self.assertTrue(self.workflow.is_completed()) - - self.assertEqual({'1': {'FirstName': 'The Funk #0', "Birthdate": "10/00/1985"}, - '2': {'FirstName': 'The Funk #1', "Birthdate": "10/01/1985"}, - '3': {'FirstName': 'The Funk #2', "Birthdate": "10/02/1985"}}, - self.workflow.last_task.data["Family"]["Members"]) - - - - - def actual_test2(self, save_restore=False): - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("Activity_FamSize", task.task_spec.name) - task.update_data({"Family":{"Size": 3}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - # Set the names of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i > 0: - self.assertEqual("FamilyMemberTask"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberTask", task.task_spec.name) - task.update_data({"FamilyMember": {"FirstName": "The Funk #%i" % i}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - self.assertEqual({'1': {'FirstName': 'The Funk #0'}, - '2': {'FirstName': 'The Funk #1'}, - '3': {'FirstName': 'The Funk #2'}}, - task.data["Family"]["Members"]) - - - # Make sure that if we have a list as both input and output - # collection, that we raise an exception - - task = self.workflow.get_ready_user_tasks()[0] - task.data['Family']['Members'] = ['The Funk #0','The Funk #1','The Funk #2'] - self.assertEqual("FamilyMemberBday", task.task_spec.name) - task.update_data( - {"CurrentFamilyMember": {"Birthdate": "10/0%i/1985" % i}}) - with self.assertRaises(WorkflowException) as context: - self.workflow.complete_task_from_id(task.id) - - - def actual_test_with_dict(self, save_restore=False): - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("Activity_FamSize", task.task_spec.name) - task.update_data({"Family":{"Size": 3}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - # Set the names of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i > 0: - self.assertEqual("FamilyMemberTask"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberTask", task.task_spec.name) - task.update_data({"FamilyMember": {"FirstName": "The Funk #%i" % i}}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - self.assertEqual({'1': {'FirstName': 'The Funk #0'}, - '2': {'FirstName': 'The Funk #1'}, - '3': {'FirstName': 'The Funk #2'}}, - task.data["Family"]["Members"]) - - - - # Set the birthdays of the 3 family members. - for i in range(3): - task = self.workflow.get_ready_user_tasks()[0] - if i == 0: - # Modify so that the dict keys are alpha rather than int - task.data["Family"]["Members"] = { - "a": {'FirstName': 'The Funk #0'}, - "b": {'FirstName': 'The Funk #1'}, - "c": {'FirstName': 'The Funk #2'}} - if (i > 0): - self.assertEqual("FamilyMemberBday"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberBday", task.task_spec.name) - task.update_data( - {"CurrentFamilyMember": {"Birthdate": "10/0%i/1985" % i}}) - self.workflow.complete_task_from_id(task.id) -# if save_restore: self.save_restore() - - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - self.assertTrue(self.workflow.is_completed()) - - self.assertEqual({"a": {'FirstName': 'The Funk #0', "Birthdate": "10/00/1985"}, - "b": {'FirstName': 'The Funk #1', "Birthdate": "10/01/1985"}, - "c": {'FirstName': 'The Funk #2', "Birthdate": "10/02/1985"}}, - self.workflow.last_task.data["Family"]["Members"]) - - - - def actual_test_for_extensions(self, save_restore=False): - - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("Activity_FamSize", task.task_spec.name) - extensions = task.task_spec.extensions # assume bpmn - self.assertEqual(extensions,{'Test1':'Value1','Test2':'Value2'}) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceArrayTest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/MultiInstanceDMNTest.py b/tests/SpiffWorkflow/camunda/MultiInstanceDMNTest.py index e31aa083b..d0893c0e5 100644 --- a/tests/SpiffWorkflow/camunda/MultiInstanceDMNTest.py +++ b/tests/SpiffWorkflow/camunda/MultiInstanceDMNTest.py @@ -15,32 +15,21 @@ class MultiInstanceDMNTest(BaseTestCase): self.script_engine = PythonScriptEngine(environment=BoxedTaskDataEnvironment()) self.workflow.script_engine = self.script_engine - def testConstructor(self): - pass # this is accomplished through setup. - def testDmnHappy(self): - self.workflow.do_engine_steps() - self.workflow.complete_next() - self.workflow.do_engine_steps() - self.workflow.complete_next() self.workflow.do_engine_steps() self.assertEqual(self.workflow.data['stuff']['E']['y'], 'D') - def testDmnSaveRestore(self): + self.save_restore() - self.workflow.script_engine = self.script_engine self.workflow.do_engine_steps() self.workflow.complete_next() self.save_restore() - self.workflow.script_engine = self.script_engine self.workflow.do_engine_steps() self.workflow.complete_next() self.save_restore() - self.workflow.script_engine = self.script_engine self.workflow.do_engine_steps() self.save_restore() - self.workflow.script_engine = self.script_engine self.assertEqual(self.workflow.data['stuff']['E']['y'], 'D') diff --git a/tests/SpiffWorkflow/camunda/MultiInstanceDeepDictEdit.py b/tests/SpiffWorkflow/camunda/MultiInstanceDeepDictEdit.py deleted file mode 100644 index 34b3db468..000000000 --- a/tests/SpiffWorkflow/camunda/MultiInstanceDeepDictEdit.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- - - - - -import copy -import sys -import os -import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -__author__ = 'matth' - -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - - -class MultiInstanceDeepDictTest(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - deep_dict = { - "StudyInfo": { - "investigators": { - "PI": { - "affiliation": "", - "department": "", - "display_name": "Daniel Harold Funk", - "email": "dhf8r@virginia.edu", - "given_name": "Daniel", - "sponsor_type": "Contractor", - "telephone_number": "", - "title": "", - "type_full": "Primary Investigator", - "user_id": "dhf8r" - }, - "DC": { - "type_full": "Department Contact", - "user_id": "John Smith" - } - } - } - } - - expected_result = copy.copy(deep_dict) - expected_result["StudyInfo"]["investigators"]["DC"]["email"] = "john.smith@gmail.com" - expected_result["StudyInfo"]["investigators"]["PI"]["email"] = "dan.funk@gmail.com" - - def setUp(self): - self.spec = self.load_workflow_spec( - 'data/multi_instance_parallel_deep_data_edit.bpmn', - 'MultiInstance') - - def testRunThroughHappy(self): - self.actual_test(False) - - def testRunThroughSaveRestore(self): - self.actual_test(True) - - def actual_test(self, save_restore=False): - - self.workflow = BpmnWorkflow(self.spec) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - # The initial task is a script task. Set the data there - # and move one. - task = self.workflow.get_ready_user_tasks()[0] - task.data = self.deep_dict - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - task = self.workflow.get_ready_user_tasks()[0] - taskinfo = task.task_info() - self.assertEqual(taskinfo,{'is_looping':False, - 'is_sequential_mi':False, - 'is_parallel_mi':True, - 'mi_count':2, - 'mi_index':1}) - self.assertEqual("MultiInstanceTask", task.task_spec.name) - self.assertTrue("investigator" in task.data) - data = copy.copy(task.data) - data['investigator']['email'] = "john.smith@gmail.com" - task.update_data(data) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.save_restore() - - - task = self.workflow.get_ready_user_tasks()[0] - taskinfo = task.task_info() - self.assertEqual(taskinfo,{'is_looping':False, - 'is_sequential_mi':False, - 'is_parallel_mi':True, - 'mi_count':2, - 'mi_index':2}) - self.assertEqual("MultiInstanceTask", task.task_spec.name) - self.assertTrue("investigator" in task.data) - data = copy.copy(task.data) - data['investigator']['email'] = "dan.funk@gmail.com" - task.update_data(data) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - self.assertTrue(self.workflow.is_completed()) - task = self.workflow.last_task - self.assertEqual(self.expected_result, task.data) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceDeepDictTest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/MultiInstanceParallelArrayTest.py b/tests/SpiffWorkflow/camunda/MultiInstanceParallelArrayTest.py deleted file mode 100644 index 14373b0c3..000000000 --- a/tests/SpiffWorkflow/camunda/MultiInstanceParallelArrayTest.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest -import random - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - -__author__ = 'matth' - -debug = True - -class MultiInstanceParallelArrayTest(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('multi_instance_array_parallel.bpmn', 'MultiInstanceArray') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - self.actual_test(False) - - def testRunThroughSaveRestore(self): - self.actual_test(True) - - def actual_test(self, save_restore=False): - - first_task = self.workflow.task_tree - - # A previous task (in this case the root task) will set the data - # so it must be found later. - first_task.update_data({"FamilySize": 3}) - self.workflow.do_engine_steps() - if save_restore: self.reload_save_restore() - # Set initial array size to 3 in the first user form. - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual("Activity_FamSize", task.task_spec.name) - task.update_data({"FamilySize": 3}) - self.workflow.complete_task_from_id(task.id) - if save_restore: self.reload_save_restore() - self.workflow.do_engine_steps() - - # Set the names of the 3 family members. - for i in range(3): - - tasks = self.workflow.get_ready_user_tasks() - self.assertEqual(len(tasks),1) # still with sequential MI - task = tasks[0] - if i > 0: - self.assertEqual("FamilyMemberTask"+"_%d"%(i-1), task.task_spec.name) - else: - self.assertEqual("FamilyMemberTask", task.task_spec.name) - task.update_data({"FamilyMember": {"FirstName": "The Funk #%i" % i}}) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: - self.reload_save_restore() - tasks = self.workflow.get_ready_user_tasks() - - self.assertEqual(3,len(tasks)) - # Set the birthdays of the 3 family members. - for i in range(3): # emulate random Access - task = random.choice(tasks) - x = task.internal_data['runtimes'] -1 - self.assertEqual("FamilyMemberBday", task.task_spec.name[:16]) - self.assertEqual({"FirstName": "The Funk #%i" % x}, - task.data["CurrentFamilyMember"]) - task.update_data( - {"CurrentFamilyMember": {"Birthdate": "10/05/1985" + str(x)}}) - self.workflow.do_engine_steps() - self.workflow.complete_task_from_id(task.id) - # We used to check that the current data variable was available in the task, - # but there's no reason to preserve it after the task completes. We removed it - # in some cases and left it in others, which just adds to the confusion. - self.workflow.do_engine_steps() - if save_restore: - self.reload_save_restore() - self.workflow.do_engine_steps() - - tasks = self.workflow.get_ready_user_tasks() - - self.workflow.do_engine_steps() - if save_restore: - self.reload_save_restore() - - names = task.data['FamilyMembers'] - bdays = task.data['FamilyMemberBirthday'] - for x in list(names.keys()): - self.assertEqual(str(names[x]['FirstName'][-1]),str(bdays[x]['Birthdate'][-1])) - self.assertTrue(self.workflow.is_completed()) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(MultiInstanceParallelArrayTest) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/ParseMultiInstanceTest.py b/tests/SpiffWorkflow/camunda/ParseMultiInstanceTest.py new file mode 100644 index 000000000..9f612a6d8 --- /dev/null +++ b/tests/SpiffWorkflow/camunda/ParseMultiInstanceTest.py @@ -0,0 +1,91 @@ +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow + +from .BaseTestCase import BaseTestCase + +# NB: I realize this is bad form, but MultiInstanceDMNTest uses a sequential MI task so I'm not adding tests +# for that here. The task specs are updated the same way, so this should be sufficient. +# I'm not testing the specific of operation here either, because that is pretty extensively tested in the +# main BPMN package + +class ParseMultiInstanceTest(BaseTestCase): + + def testCollectionInCardinality(self): + + spec, subprocesses = self.load_workflow_spec('parallel_multiinstance_cardinality.bpmn', 'main') + self.workflow = BpmnWorkflow(spec) + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': [1, 2, 3]} + self.workflow.do_engine_steps() + + self.save_restore() + + task_spec = self.workflow.get_tasks_from_spec_name('any_task')[0].task_spec + self.assertEqual(task_spec.data_input.name, 'input_data') + self.assertEqual(task_spec.data_output.name, 'output_data') + self.assertEqual(task_spec.input_item.name, 'output_item') + self.assertEqual(task_spec.output_item.name, 'output_item') + + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + for task in ready_tasks: + task.data['output_item'] = task.data['output_item'] * 2 + task.complete() + + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, {'input_data': [1, 2, 3], 'output_data': [2, 4, 6]}) + + def testIntegerCardinality(self): + + spec, subprocesses = self.load_workflow_spec('parallel_multiinstance_cardinality.bpmn', 'main') + self.workflow = BpmnWorkflow(spec) + task_spec = self.workflow.get_tasks_from_spec_name('any_task')[0].task_spec + task_spec.cardinality = 'len(input_data)' + + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': [1, 2, 3]} + self.workflow.do_engine_steps() + + self.save_restore() + + self.assertEqual(task_spec.data_input, None) + self.assertEqual(task_spec.input_item.name, 'output_item') + + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + for task in ready_tasks: + task.data['output_item'] = task.data['output_item'] * 2 + task.complete() + + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, {'input_data': [1, 2, 3], 'output_data': [0, 2, 4]}) + + def testCollection(self): + + spec, subprocesses = self.load_workflow_spec('parallel_multiinstance_collection.bpmn', 'main') + self.workflow = BpmnWorkflow(spec) + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': [1, 2, 3]} + self.workflow.do_engine_steps() + + self.save_restore() + + task_spec = self.workflow.get_tasks_from_spec_name('any_task')[0].task_spec + self.assertEqual(task_spec.data_input.name, 'input_data') + self.assertEqual(task_spec.data_output.name, 'input_data') + self.assertEqual(task_spec.input_item.name, 'input_item') + self.assertEqual(task_spec.output_item.name, 'input_item') + + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 3) + for task in ready_tasks: + task.data['input_item'] = task.data['input_item'] * 2 + task.complete() + + self.workflow.do_engine_steps() + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, {'input_data': [2, 4, 6]}) diff --git a/tests/SpiffWorkflow/camunda/ResetTokenMIParallelTest.py b/tests/SpiffWorkflow/camunda/ResetTokenMIParallelTest.py deleted file mode 100644 index 75f2df361..000000000 --- a/tests/SpiffWorkflow/camunda/ResetTokenMIParallelTest.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow - -__author__ = 'kellym' - -class ResetTokenTestMIParallel(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('token_trial_MIParallel.bpmn', 'token') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - self.actual_test(save_restore=False) - - def testRunThroughSaveRestore(self): - self.actual_test(save_restore=True) - - def actual_test(self, save_restore=False,reset_data=False): - - self.workflow.do_engine_steps() - firsttaskid = None - steps = [{'taskname':'First', - 'task_data': {'do_step':'Yes'}}, - {'taskname': 'FormA', - 'task_data': {'current': {'A' : 'x'}}}, - {'taskname': 'FormA', - 'task_data': {'current': {'A' : 'y'}}}, - {'taskname': 'FormA', - 'task_data': {'current': {'A' : 'z'}}} - ] - for step in steps: - task = self.workflow.get_ready_user_tasks()[0] - if firsttaskid == None and step['taskname']=='FormA': - firsttaskid = task.id - self.assertEqual(step['taskname'], task.task_spec.name[:len(step['taskname'])]) - task.update_data(step['task_data']) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - self.assertEqual({'do_step': 'Yes', - 'output': {'1': {'A': 'x'}, '2': {'A': 'y'}, '3': {'A': 'z'}}}, - self.workflow.last_task.data) - - self.workflow.reset_task_from_id(firsttaskid) - #NB - this won't test random access - steps = [{'taskname': 'FormA', - 'task_data': {'current': {'A' : 'a1'}}}, - {'taskname': 'FormC', - 'task_data': {'C' : 'c'}}, - ] - for step in steps: - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual(step['taskname'], task.task_spec.name) - task.update_data(step['task_data']) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - self.assertTrue(self.workflow.is_completed()) - - self.assertEqual({'do_step': 'Yes', - 'C': 'c', - 'output': {'1': {'A': 'a1'}, - '2': {'A': 'y'}, - '3': {'A': 'z'}}}, - self.workflow.last_task.data) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ResetTokenTestMIParallel) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/ResetTokenMITest.py b/tests/SpiffWorkflow/camunda/ResetTokenMITest.py deleted file mode 100644 index 5d6c2e27e..000000000 --- a/tests/SpiffWorkflow/camunda/ResetTokenMITest.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from SpiffWorkflow.bpmn.workflow import BpmnWorkflow -from tests.SpiffWorkflow.camunda.BaseTestCase import BaseTestCase - -__author__ = 'kellym' - -class ResetTokenTestMI(BaseTestCase): - """The example bpmn diagram tests both a set cardinality from user input - as well as looping over an existing array.""" - - def setUp(self): - spec, subprocesses = self.load_workflow_spec('token_trial_MI.bpmn', 'token') - self.workflow = BpmnWorkflow(spec, subprocesses) - - def testRunThroughHappy(self): - self.actual_test(save_restore=False) - - def testRunThroughSaveRestore(self): - self.actual_test(save_restore=True) - - def actual_test(self, save_restore=False,reset_data=False): - - self.workflow.do_engine_steps() - firsttaskid = None - steps = [{'taskname':'First', - 'task_data': {'do_step':'Yes'}}, - {'taskname': 'FormA', - 'task_data': {'current': {'A' : 'x'}}}, - {'taskname': 'FormA_0', - 'task_data': {'current': {'A' : 'y'}}}, - {'taskname': 'FormA_1', - 'task_data': {'current': {'A' : 'z'}}} - ] - for step in steps: - task = self.workflow.get_ready_user_tasks()[0] - if firsttaskid == None and step['taskname']=='FormA': - firsttaskid = task.id - self.assertEqual(step['taskname'], task.task_spec.name) - task.update_data(step['task_data']) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - self.workflow.reset_task_from_id(firsttaskid) - - steps = [{'taskname': 'FormA', - 'task_data': {'current': {'A': 'a1'}}}, - {'taskname': 'FormA_0', - 'task_data': {'current': {'A': 'a2'}}}, - {'taskname': 'FormA_1', - 'task_data': {'current': {'A': 'a3'}}}, - {'taskname': 'FormC', - 'task_data': {'C': 'c'}} - ] - - for step in steps: - task = self.workflow.get_ready_user_tasks()[0] - self.assertEqual(step['taskname'], task.task_spec.name) - task.update_data(step['task_data']) - self.workflow.complete_task_from_id(task.id) - self.workflow.do_engine_steps() - if save_restore: self.save_restore() - - self.assertTrue(self.workflow.is_completed()) - self.assertEqual({'do_step': 'Yes', - 'output': {'1': {'A': 'a1'}, - '2': {'A': 'a2'}, - '3': {'A': 'a3'}}, - 'C': 'c'}, - self.workflow.last_task.data) - - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(ResetTokenTestMI) - -if __name__ == '__main__': - unittest.TextTestRunner(verbosity=2).run(suite()) diff --git a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn index d00fd87d2..acc7f2fbe 100644 --- a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn +++ b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn @@ -1,27 +1,20 @@ - + Flow_1b29lxw - Flow_0fusz9y + SequenceFlow_06fnqj2 - + - Flow_0z7tfh1 + Flow_09ciw49 SequenceFlow_06fnqj2 - - - Flow_066d5e1 - Flow_0fusz9y - print('EndScript') -print(stuff) - - + This is a test of documentation @@ -33,55 +26,24 @@ of documentation 'D': {'x': 6}, 'E': {'x': 7}} - - - Flow_09ciw49 - Flow_0z7tfh1 - - - - SequenceFlow_06fnqj2 - Flow_066d5e1 - - - - - - - - - - - - - - + - - + + - - - - - - - - - @@ -91,15 +53,15 @@ of documentation + + + - + - - - diff --git a/tests/SpiffWorkflow/camunda/data/common_workflow.bpmn b/tests/SpiffWorkflow/camunda/data/common_workflow.bpmn deleted file mode 100644 index 3902b9b4a..000000000 --- a/tests/SpiffWorkflow/camunda/data/common_workflow.bpmn +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Flow_0xpz6la - Flow_03yam6h - my_custom_function('test 1 from common workflow') - - - Flow_1jz376x - - - - - - - - - Flow_03yam6h - Flow_0pc6yx9 - - - - Flow_0pc6yx9 - Flow_16t7ue6 - my_custom_function('test 2 from common workflow') - - - - - - - - - - - - - Flow_16t7ue6 - Flow_1jz376x - - - Flow_0xpz6la - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/default_gateway_pmi.bpmn b/tests/SpiffWorkflow/camunda/data/default_gateway_pmi.bpmn deleted file mode 100644 index d98baf5d8..000000000 --- a/tests/SpiffWorkflow/camunda/data/default_gateway_pmi.bpmn +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Flow_1wis1un - - - - - - - - Flow_1wis1un - Flow_144jxvd - - - - Flow_144jxvd - Flow_1riszc2 - Flow_0xdvee4 - - - - - Flow_13ncefd - Flow_0xdvee4 - - - - - - - - - Flow_1riszc2 - Flow_13ncefd - - 3 - - - - morestuff == 'No' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/multi_instance_array.bpmn b/tests/SpiffWorkflow/camunda/data/multi_instance_array.bpmn deleted file mode 100644 index f37b7e525..000000000 --- a/tests/SpiffWorkflow/camunda/data/multi_instance_array.bpmn +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Flow_0bplvtg - - - Please enter family size: - - - - - - - - - - - - - - - - - - - - Flow_0bplvtg - Flow_0zpm0rc - - - - Please enter information for family member {{ FamilyMember }}: - - - - - - Flow_0zpm0rc - Flow_0659lqh - - Family.Size - - - - - Enter Birthday for {{ CurrentFamilyMember['FamilyMember.FormField_FirstName'] }} - - - - - - Flow_0659lqh - Flow_0ncqf54 - - - - - - XXX - Flow_0ncqf54 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/multi_instance_array_parallel.bpmn b/tests/SpiffWorkflow/camunda/data/multi_instance_array_parallel.bpmn deleted file mode 100644 index fbcd2cf1d..000000000 --- a/tests/SpiffWorkflow/camunda/data/multi_instance_array_parallel.bpmn +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Flow_0bplvtg - - - Please enter family size: - - - - - - - - - - - - - - - - Flow_0bplvtg - Flow_0zpm0rc - - - - Please enter information for family member {{ FamilyMember }}: - - - - - - Flow_0zpm0rc - Flow_0659lqh - - FamilySize - - - - - Enter Birthday for {{ CurrentFamilyMember['FamilyMember.FormField_FirstName'] }} - - - - - - Flow_0659lqh - Flow_0ncqf54 - - FamilyMembers - - - - - - XXX - Flow_0ncqf54 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/multi_instance_parallel_deep_data_edit.bpmn b/tests/SpiffWorkflow/camunda/data/multi_instance_parallel_deep_data_edit.bpmn deleted file mode 100644 index 7ce994be9..000000000 --- a/tests/SpiffWorkflow/camunda/data/multi_instance_parallel_deep_data_edit.bpmn +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Flow_0t6p1sb - - - - Flow_0ugjw69 - - - - # Please provide addtional information about: -## Investigator ID: {{investigator.user_id}} -## Role: {{investigator.type_full}} - - - - - - SequenceFlow_1p568pp - Flow_0ugjw69 - - - - - Imagine a script task here that loads a complex data set. - Flow_0t6p1sb - SequenceFlow_1p568pp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_cardinality.bpmn b/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_cardinality.bpmn new file mode 100644 index 000000000..75eccb29a --- /dev/null +++ b/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_cardinality.bpmn @@ -0,0 +1,41 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + input_data + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_collection.bpmn b/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_collection.bpmn new file mode 100644 index 000000000..0fbc788c6 --- /dev/null +++ b/tests/SpiffWorkflow/camunda/data/parallel_multiinstance_collection.bpmn @@ -0,0 +1,39 @@ + + + + + Flow_0m77cxj + + + Flow_0m77cxj + Flow_1jbp2el + + + + + Flow_1jbp2el + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/camunda/data/token_trial_MI.bpmn b/tests/SpiffWorkflow/camunda/data/token_trial_MI.bpmn deleted file mode 100644 index 368cd4f08..000000000 --- a/tests/SpiffWorkflow/camunda/data/token_trial_MI.bpmn +++ /dev/null @@ -1,83 +0,0 @@ - - - - - Flow_03vnrmv - - - Do you want to do the next steps? - - - - - - Flow_03vnrmv - Flow_10pdq2v - - - FormC - - - - - - Flow_0ztfesh - Flow_039y4lk - - - - Flow_039y4lk - - - - MI item - - - - - - Flow_10pdq2v - Flow_0ztfesh - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/camunda/data/token_trial_MIParallel.bpmn b/tests/SpiffWorkflow/camunda/data/token_trial_MIParallel.bpmn deleted file mode 100644 index 3e2f1b19b..000000000 --- a/tests/SpiffWorkflow/camunda/data/token_trial_MIParallel.bpmn +++ /dev/null @@ -1,83 +0,0 @@ - - - - - Flow_03vnrmv - - - Do you want to do the next steps? - - - - - - Flow_03vnrmv - Flow_10pdq2v - - - FormC - - - - - - Flow_0ztfesh - Flow_039y4lk - - - - Flow_039y4lk - - - - MI item - - - - - - Flow_10pdq2v - Flow_0ztfesh - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/SpiffWorkflow/specs/ExecuteTest.py b/tests/SpiffWorkflow/specs/ExecuteTest.py index 05653e185..3a10ae75d 100644 --- a/tests/SpiffWorkflow/specs/ExecuteTest.py +++ b/tests/SpiffWorkflow/specs/ExecuteTest.py @@ -40,10 +40,7 @@ class ExecuteTest(TaskSpecTest): expected = 'Start\n testtask\n' workflow = run_workflow(self, self.wf_spec, expected, '') task = workflow.get_tasks_from_spec_name('testtask')[0] - self.assertEqual(task.state_history, [TaskState.FUTURE, - TaskState.WAITING, - TaskState.READY, - TaskState.COMPLETED]) + self.assertEqual(task.state, TaskState.COMPLETED) self.assertIn(b'127.0.0.1', task.results[0]) diff --git a/tests/SpiffWorkflow/specs/TaskSpecTest.py b/tests/SpiffWorkflow/specs/TaskSpecTest.py index 2509d6184..717846566 100644 --- a/tests/SpiffWorkflow/specs/TaskSpecTest.py +++ b/tests/SpiffWorkflow/specs/TaskSpecTest.py @@ -52,14 +52,6 @@ class TaskSpecTest(unittest.TestCase): self.assertEqual(self.spec.outputs, [spec]) self.assertEqual(spec.inputs, [self.spec]) - def testFollow(self): - self.assertEqual(self.spec.outputs, []) - self.assertEqual(self.spec.inputs, []) - spec = self.create_instance() - self.spec.follow(spec) - self.assertEqual(spec.outputs, [self.spec]) - self.assertEqual(self.spec.inputs, [spec]) - def testTest(self): # Should fail because the TaskSpec has no id yet. spec = self.create_instance() @@ -101,12 +93,12 @@ class TaskSpecTest(unittest.TestCase): M = Join(self.wf_spec, 'M') T3 = Simple(self.wf_spec, 'T3') - T1.follow(self.wf_spec.start) - T2A.follow(T1) - T2B.follow(T1) + self.wf_spec.start.connect(T1) + T1.connect(T2A) + T1.connect(T2B) T2A.connect(M) T2B.connect(M) - T3.follow(M) + M.connect(T3) self.assertEqual(T1.ancestors(), [self.wf_spec.start]) self.assertEqual(T2A.ancestors(), [T1, self.wf_spec.start]) @@ -118,8 +110,7 @@ class TaskSpecTest(unittest.TestCase): T1 = Join(self.wf_spec, 'T1') T2 = Simple(self.wf_spec, 'T2') - T1.follow(self.wf_spec.start) - T2.follow(T1) + self.wf_spec.start.connect(T1) T1.connect(T2) self.assertEqual(T1.ancestors(), [self.wf_spec.start]) diff --git a/tests/SpiffWorkflow/specs/WorkflowSpecTest.py b/tests/SpiffWorkflow/specs/WorkflowSpecTest.py index 9b4c0d322..c2a5638e4 100644 --- a/tests/SpiffWorkflow/specs/WorkflowSpecTest.py +++ b/tests/SpiffWorkflow/specs/WorkflowSpecTest.py @@ -102,8 +102,8 @@ class WorkflowSpecTest(unittest.TestCase): task2 = Join(self.wf_spec, 'Second') task1.connect(task2) - task2.follow(task1) - task1.follow(task2) + task1.connect(task2) + task2.connect(task1) results = self.wf_spec.validate() self.assertIn("Found loop with 'Second': Second->First then 'Second' " diff --git a/tests/SpiffWorkflow/spiff/BaseTestCase.py b/tests/SpiffWorkflow/spiff/BaseTestCase.py index f1826a78d..5b8533f50 100644 --- a/tests/SpiffWorkflow/spiff/BaseTestCase.py +++ b/tests/SpiffWorkflow/spiff/BaseTestCase.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- import os -from copy import deepcopy from SpiffWorkflow.spiff.parser.process import SpiffBpmnParser, VALIDATOR from SpiffWorkflow.spiff.serializer.config import SPIFF_SPEC_CONFIG diff --git a/tests/SpiffWorkflow/spiff/CorrelationTest.py b/tests/SpiffWorkflow/spiff/CorrelationTest.py index 1b1a2be30..6589eb2b8 100644 --- a/tests/SpiffWorkflow/spiff/CorrelationTest.py +++ b/tests/SpiffWorkflow/spiff/CorrelationTest.py @@ -1,10 +1,3 @@ -import os -import sys -import unittest - -dirname = os.path.dirname(__file__) -sys.path.insert(0, os.path.join(dirname, '..', '..', '..')) - from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from .BaseTestCase import BaseTestCase diff --git a/tests/SpiffWorkflow/spiff/MultiInstanceTaskTest.py b/tests/SpiffWorkflow/spiff/MultiInstanceTaskTest.py new file mode 100644 index 000000000..61e89e1fd --- /dev/null +++ b/tests/SpiffWorkflow/spiff/MultiInstanceTaskTest.py @@ -0,0 +1,29 @@ +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow + +from .BaseTestCase import BaseTestCase + + +class MultiInstanceTaskTest(BaseTestCase): + + def testMultiInstanceTask(self): + spec, subprocesses = self.load_workflow_spec('spiff_multiinstance.bpmn', 'Process_1') + self.workflow = BpmnWorkflow(spec, subprocesses) + start = self.workflow.get_tasks_from_spec_name('Start')[0] + start.data = {'input_data': [1, 2, 3]} + self.workflow.do_engine_steps() + task = self.workflow.get_tasks_from_spec_name('any_task')[0] + self.workflow.do_engine_steps() + + self.save_restore() + + ready_tasks = self.workflow.get_ready_user_tasks() + for task in ready_tasks: + task.data['output_item'] = task.data['input_item'] * 2 + task.complete() + self.workflow.do_engine_steps() + + self.assertTrue(self.workflow.is_completed()) + self.assertDictEqual(self.workflow.data, { + 'input_data': [2, 3, 4], # Prescript adds 1 to input + 'output_data': [3, 5, 7], # Postscript subtracts 1 from output + }) diff --git a/tests/SpiffWorkflow/spiff/data/spiff_multiinstance.bpmn b/tests/SpiffWorkflow/spiff/data/spiff_multiinstance.bpmn new file mode 100644 index 000000000..f8b5fdbd8 --- /dev/null +++ b/tests/SpiffWorkflow/spiff/data/spiff_multiinstance.bpmn @@ -0,0 +1,49 @@ + + + + + Flow_1hjrex4 + + + + input_data = [ v + 1 for v in input_data ] + output_data = [ v - 1 for v in output_data ] + + Flow_1hjrex4 + Flow_1xndbxy + + input_data + output_data + + + + + + + Flow_1xndbxy + + + + + + + + + + + + + + + + + + + + + + + + + +