From cb4d72445de05ee12b0654f92244f7162913b2bb Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 18 Feb 2023 10:32:56 -0500 Subject: [PATCH] Squashed 'SpiffWorkflow/' changes from 11e4b4f96..b439f69f2 b439f69f2 Merge pull request #296 from sartography/bugfix/subprocess-access-to-data-objects 6d2a2031e update spiff subworkflow tasks too 992c38671 make data objects referenceable within subprocesses 6c8ff5cdf allow subprocesses & call activities to have different data copy policies 2b14f3a48 initialize subprocesses in _update_hook instead of _on_ready_before 791f335d5 Merge pull request #295 from sartography/improvement/remove-camunda-from-base-and-misc-cleanup 28b579beb remove a few unused, duplicative, and debugging methods 8f14d1098 remove some other unused diagrams and tests 408bc6734 rely on top level camunda parser for almost all namespace references 895b2cc9b remove camunda namespace from base bpmn parser 76ecbf7cc Merge pull request #294 from sartography/bugfix/reactivate-boundary-event 82b6c8ad4 hack to ensure timers (and other events) are reset if returned to via loop reset 590903f47 Merge pull request #292 from sartography/feature/multiinstance-refactor 537490043 fix bug & typo f31726db1 raise error on attempting to migrate workflows with MI 44e6d08d8 create spiff multiinstance task 2168c022b create camunda MI that approximates what it used to do 9894cea59 some improvements and bugfixes f857ad5d4 remove some now unused functionality & tests, create a few more tests 6fead9d04 updated serializer & fixes for most tests ec662ecdd add parallel multiinstance bd19b2a8a working sequential multiinstance 2f9c192b6 further cleanup around _update_hook 947792bf6 fix bug in exclusive gateway migration d3d87b28d add io spec to all tasks f1586e275 add support for standard loop tasks git-subtree-dir: SpiffWorkflow git-subtree-split: b439f69f23b547df4de1e8e0c636997f2fd4e33b --- tests/SpiffWorkflow/TaskTest.py | 12 +- tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.py | 42 - .../bpmn/BpmnWorkflowTestCase.py | 3 +- .../bpmn/DataObjectReferenceTest.py | 6 +- .../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 +- .../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 ++ 76 files changed, 3303 insertions(+), 2995 deletions(-) delete mode 100644 tests/SpiffWorkflow/bpmn/AntiLoopTaskTest.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 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 e44f68e6..77e28df6 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 c398ca83..00000000 --- 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/BpmnWorkflowTestCase.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py index ba564abc..3b6c8d03 100644 --- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py +++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py @@ -8,7 +8,6 @@ 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 __author__ = 'matth' @@ -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 0254c5df..fab8db77 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/ExclusiveGatewayIntoMultiInstanceTest.py b/tests/SpiffWorkflow/bpmn/ExclusiveGatewayIntoMultiInstanceTest.py deleted file mode 100644 index 8eaaff41..00000000 --- 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 424f72e9..00000000 --- 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 6b27fc05..b3f70fe6 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 709750c6..00000000 --- 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 305cb3df..00000000 --- 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 e13b943a..00000000 --- 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 6054f99a..00000000 --- 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 00000000..c72948b4 --- /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 67d3c90b..39797448 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 933d8a91..00000000 --- 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 59a32775..25d26fdb 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 00000000..8a94daba --- /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 00000000..ba93fdbe --- /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 00000000..e9d6534c --- /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 83dfcef2..00000000 --- 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 6b02f096..00000000 --- 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 53ecfd4e..00000000 --- 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 a92df4ad..00000000 --- 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 4893f713..00000000 --- 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 c35b237e..00000000 --- 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 d9a72316..00000000 --- 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 298c5fa2..c558cf59 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/exclusive_into_multi.bpmn b/tests/SpiffWorkflow/bpmn/data/exclusive_into_multi.bpmn deleted file mode 100644 index 0fb12a41..00000000 --- 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 bb4bbab0..00000000 --- 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 dc10332f..773f11bc 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 00000000..af89b353 --- /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 00000000..1f0e75b5 --- /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 00000000..1113dd90 --- /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 00000000..e9cce84e --- /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 00000000..7750e4bb --- /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 00000000..0271b3ae --- /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 00000000..a77f86b5 --- /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 00000000..796f5847 --- /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 00000000..b7987255 --- /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 00000000..122d5a21 --- /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 00000000..1e08e3e2 --- /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 00000000..3696e100 --- /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 95e29da0..00000000 --- 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 1fb69933..00000000 --- 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 478e18ff..00000000 --- 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 b89d98f6..00000000 --- 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 363ccc12..00000000 --- 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 29febd24..529852ee 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 1212d776..02a8389f 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 cae051ba..2b169f14 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 96852cc2..00000000 --- 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 1b65ba57..00000000 --- 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 3244f16d..00000000 --- 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 e31aa083..d0893c0e 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 34b3db46..00000000 --- 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 14373b0c..00000000 --- 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 00000000..9f612a6d --- /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 75f2df36..00000000 --- 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 5d6c2e27..00000000 --- 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 d00fd87d..acc7f2fb 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 3902b9b4..00000000 --- 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 d98baf5d..00000000 --- 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 f37b7e52..00000000 --- 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 fbcd2cf1..00000000 --- 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 7ce994be..00000000 --- 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 00000000..75eccb29 --- /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 00000000..0fbc788c --- /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 368cd4f0..00000000 --- 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 3e2f1b19..00000000 --- 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 05653e18..3a10ae75 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 2509d618..71784656 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 9b4c0d32..c2a5638e 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 f1826a78..5b8533f5 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 1b1a2be3..6589eb2b 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 00000000..61e89e1f --- /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 00000000..f8b5fdbd --- /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 + + + + + + + + + + + + + + + + + + + + + + + + + +