Squashed 'SpiffWorkflow/' changes from 96ad2a2b0..73886584b

73886584b Merge pull request #315 from sartography/feature/new-task-states
a04fdd311 Merge remote-tracking branch 'origin/main' into feature/new-task-states
3d376bf9a documentation and comment updates
7e368ee4b copy edit
e7b9fe91c typo
eceef15a7 Called elements (#316)
5a0fd2774 add serialization migration
7211e67ee Merge pull request #314 from sartography/bugfix/data-object-references
403acc1f5 use same data objects & references in subprocesses after deserialization
c54091dee add two more states to spiff
fa04a14a7 clean up script engine a little bit
162a1c5f5 override create parser in spiff package to allow duplicate process names
98a1b37e0 Merge pull request #312 from sartography/bugfix/run-boundary-events-from-engine-steps
067d6a723 do not execute boundary events in catch
1c877dd76 send external events to top level workflow

git-subtree-dir: SpiffWorkflow
git-subtree-split: 73886584b17c7d11a9713d0c4526ed41e411fc45
This commit is contained in:
burnettk 2023-04-21 11:22:52 -04:00
parent f1b8cfcc07
commit c4f4e008d8
38 changed files with 977 additions and 72 deletions

1
.gitignore vendored
View File

@ -277,3 +277,4 @@ coverage.xml
.c9revisions .c9revisions
.idea .idea
/venv /venv
*~

View File

@ -45,7 +45,7 @@ tests-par:
echo " pip install unittest-parallel"; \ echo " pip install unittest-parallel"; \
exit 1; \ exit 1; \
fi fi
unittest-parallel --module-fixtures -vs tests/SpiffWorkflow -p \*Test.py -t . unittest-parallel --module-fixtures -qbs tests/SpiffWorkflow -p \*Test.py -t .
.PHONY : tests-cov .PHONY : tests-cov
tests-cov: tests-cov:

View File

@ -46,6 +46,8 @@ class ApprovalsTest(BpmnWorkflowTestCase):
def testRunThroughHappy(self): def testRunThroughHappy(self):
self.do_next_named_step('First_Approval_Wins.Manager_Approval') self.do_next_named_step('First_Approval_Wins.Manager_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done') self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
self.do_next_named_step('Approvals.Manager_Approval__P_') self.do_next_named_step('Approvals.Manager_Approval__P_')
@ -55,11 +57,15 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.do_next_named_step('Parallel_Approvals_SP.Step1') self.do_next_named_step('Parallel_Approvals_SP.Step1')
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval') self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
self.do_next_named_step('Parallel_Approvals_SP.Supervisor_Approval') self.do_next_named_step('Parallel_Approvals_SP.Supervisor_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done') self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testRunThroughHappyOtherOrders(self): def testRunThroughHappyOtherOrders(self):
self.do_next_named_step('First_Approval_Wins.Supervisor_Approval') self.do_next_named_step('First_Approval_Wins.Supervisor_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done') self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
self.do_next_named_step('Approvals.Supervisor_Approval__P_') self.do_next_named_step('Approvals.Supervisor_Approval__P_')
@ -69,11 +75,15 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval') self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
self.do_next_named_step('Parallel_Approvals_SP.Step1') self.do_next_named_step('Parallel_Approvals_SP.Step1')
self.do_next_named_step('Parallel_Approvals_SP.Supervisor_Approval') self.do_next_named_step('Parallel_Approvals_SP.Supervisor_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done') self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testSaveRestore(self): def testSaveRestore(self):
self.do_next_named_step('First_Approval_Wins.Manager_Approval') self.do_next_named_step('First_Approval_Wins.Manager_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done') self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
@ -86,12 +96,16 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval') self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1') self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval') self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done') self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testSaveRestoreWaiting(self): def testSaveRestoreWaiting(self):
self.do_next_named_step('First_Approval_Wins.Manager_Approval') self.do_next_named_step('First_Approval_Wins.Manager_Approval')
self.save_restore() self.save_restore()
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done') self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
self.save_restore() self.save_restore()
@ -108,6 +122,8 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval') self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.save_restore() self.save_restore()
self.complete_subworkflow()
self.complete_subworkflow()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done') self.do_next_exclusive_step('Approvals.Parallel_SP_Done')

View File

@ -118,6 +118,13 @@ class BpmnWorkflowTestCase(unittest.TestCase):
tasks[0].set_data(**set_attribs) tasks[0].set_data(**set_attribs)
tasks[0].run() tasks[0].run()
def complete_subworkflow(self):
# A side effect of finer grained contol over task execution is that tasks require more explicit intervention
# to change states. Subworkflows tasks no longer go directly to ready when the subworkflow completes.
# So they may need to explicitly refreshed to become ready, and then run.
self.workflow.refresh_waiting_tasks()
self.workflow.do_engine_steps()
def save_restore(self): def save_restore(self):
script_engine = self.workflow.script_engine script_engine = self.workflow.script_engine

View File

@ -6,6 +6,8 @@ from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from .BpmnWorkflowTestCase import BpmnWorkflowTestCase from .BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'kellym' __author__ = 'kellym'
@ -34,13 +36,12 @@ class CallActivityTest(BpmnWorkflowTestCase):
self.workflow = BpmnWorkflow(self.spec, self.subprocesses, self.workflow = BpmnWorkflow(self.spec, self.subprocesses,
script_engine=CustomScriptEngine()) script_engine=CustomScriptEngine())
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())
self.assertIsInstance(self.workflow.script_engine, CustomScriptEngine) self.assertIsInstance(self.workflow.script_engine, CustomScriptEngine)
if save_restore: if save_restore:
self.save_restore() self.save_restore()
# We have to reset the script engine after deserialize.
self.workflow.script_engine = CustomScriptEngine()
# Get the subworkflow # Get the subworkflow
sub_task = self.workflow.get_tasks_from_spec_name('Sub_Bpmn_Task')[0] sub_task = self.workflow.get_tasks_from_spec_name('Sub_Bpmn_Task')[0]
@ -54,6 +55,7 @@ class CallActivityTest(BpmnWorkflowTestCase):
# data should be removed in the final output as well. # data should be removed in the final output as well.
self.workflow = BpmnWorkflow(self.spec, self.subprocesses) self.workflow = BpmnWorkflow(self.spec, self.subprocesses)
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())
self.assertNotIn('remove_this_var', self.workflow.last_task.data.keys()) self.assertNotIn('remove_this_var', self.workflow.last_task.data.keys())
@ -66,6 +68,8 @@ class CallActivityTest(BpmnWorkflowTestCase):
self.assertEquals(2, len(context.exception.task_trace)) self.assertEquals(2, len(context.exception.task_trace))
self.assertRegexpMatches(context.exception.task_trace[0], 'Create Data \(.*?call_activity_call_activity.bpmn\)') self.assertRegexpMatches(context.exception.task_trace[0], 'Create Data \(.*?call_activity_call_activity.bpmn\)')
self.assertRegexpMatches(context.exception.task_trace[1], 'Get Data Call Activity \(.*?call_activity_with_error.bpmn\)') self.assertRegexpMatches(context.exception.task_trace[1], 'Get Data Call Activity \(.*?call_activity_with_error.bpmn\)')
task = self.workflow.get_tasks_from_spec_name('Sub_Bpmn_Task')[0]
self.assertEqual(task.state, TaskState.ERROR)
def suite(): def suite():
return unittest.TestLoader().loadTestsFromTestCase(CallActivityTest) return unittest.TestLoader().loadTestsFromTestCase(CallActivityTest)

View File

@ -27,6 +27,8 @@ class CallActivitySubProcessPropTest(BpmnWorkflowTestCase):
def actualTest(self, save_restore=False): def actualTest(self, save_restore=False):
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.complete_subworkflow()
if save_restore: if save_restore:
self.save_restore() self.save_restore()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())

View File

@ -38,6 +38,8 @@ class CustomInlineScriptTest(BpmnWorkflowTestCase):
def actual_test(self, save_restore): def actual_test(self, save_restore):
if save_restore: self.save_restore() if save_restore: self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.complete_subworkflow()
if save_restore: self.save_restore() if save_restore: self.save_restore()
data = self.workflow.last_task.data data = self.workflow.last_task.data
self.assertEqual(data['c1'], 'HELLO') self.assertEqual(data['c1'], 'HELLO')
@ -49,8 +51,9 @@ class CustomInlineScriptTest(BpmnWorkflowTestCase):
ready_task.data = {'custom_function': "bill"} ready_task.data = {'custom_function': "bill"}
with self.assertRaises(WorkflowTaskException) as e: with self.assertRaises(WorkflowTaskException) as e:
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertTrue('' in str(e.exception))
self.assertTrue('custom_function' in str(e.exception)) self.assertTrue('custom_function' in str(e.exception))
task = self.workflow.get_tasks_from_spec_name('Activity_1y303ko')[0]
self.assertEqual(task.state, TaskState.ERROR)
def suite(): def suite():

View File

@ -72,6 +72,9 @@ class DataObjectReferenceTest(BpmnWorkflowTestCase):
self.assertNotIn('obj_1', ready_tasks[0].data) self.assertNotIn('obj_1', ready_tasks[0].data)
self.assertEqual(self.workflow.data['obj_1'], 'hello') self.assertEqual(self.workflow.data['obj_1'], 'hello')
if save_restore:
self.save_restore()
# Make sure data objects are accessible inside a subprocess # Make sure data objects are accessible inside a subprocess
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
ready_tasks = self.workflow.get_ready_user_tasks() ready_tasks = self.workflow.get_ready_user_tasks()

View File

@ -1,14 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
import os
import unittest import unittest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..'))
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
from SpiffWorkflow.exceptions import WorkflowException from SpiffWorkflow.exceptions import WorkflowException
from SpiffWorkflow.task import TaskState
from .BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'essweine' __author__ = 'essweine'
@ -25,6 +22,8 @@ class ExclusiveGatewayNoDefaultTest(BpmnWorkflowTestCase):
first = self.workflow.get_tasks_from_spec_name('StartEvent_1')[0] first = self.workflow.get_tasks_from_spec_name('StartEvent_1')[0]
first.data = { 'x': 1 } first.data = { 'x': 1 }
self.assertRaises(WorkflowException, self.workflow.do_engine_steps) self.assertRaises(WorkflowException, self.workflow.do_engine_steps)
task = self.workflow.get_tasks_from_spec_name('Gateway_CheckValue')[0]
self.assertEqual(task.state, TaskState.ERROR)
def suite(): def suite():
return unittest.TestLoader().loadTestsFromTestCase(ExclusiveGatewayNoDefaultTest) return unittest.TestLoader().loadTestsFromTestCase(ExclusiveGatewayNoDefaultTest)

View File

@ -62,6 +62,8 @@ class CallActivityDataTest(BpmnWorkflowTestCase):
self.assertNotIn('unused', task.data) self.assertNotIn('unused', task.data)
self.complete_subprocess() self.complete_subprocess()
# Refreshing causes the subprocess to become ready
self.workflow.refresh_waiting_tasks()
task = self.workflow.get_tasks(TaskState.READY)[0] task = self.workflow.get_tasks(TaskState.READY)[0]
# Originals should not change # Originals should not change
self.assertEqual(task.data['in_1'], 1) self.assertEqual(task.data['in_1'], 1)
@ -80,13 +82,11 @@ class CallActivityDataTest(BpmnWorkflowTestCase):
waiting = self.workflow.get_tasks(TaskState.WAITING) waiting = self.workflow.get_tasks(TaskState.WAITING)
def complete_subprocess(self): def complete_subprocess(self):
# When we complete, the subworkflow task will move from WAITING to READY # Complete the ready tasks in the subprocess
waiting = self.workflow.get_tasks(TaskState.WAITING) ready = self.workflow.get_tasks(TaskState.READY)
while len(waiting) > 0: while len(ready) > 0:
next_task = self.workflow.get_tasks(TaskState.READY)[0] ready[0].run()
next_task.run() ready = self.workflow.get_tasks(TaskState.READY)
waiting = self.workflow.get_tasks(TaskState.WAITING)
class IOSpecOnTaskTest(BpmnWorkflowTestCase): class IOSpecOnTaskTest(BpmnWorkflowTestCase):

View File

@ -1,5 +1,6 @@
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.exceptions import WorkflowTaskException from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from .BpmnWorkflowTestCase import BpmnWorkflowTestCase from .BpmnWorkflowTestCase import BpmnWorkflowTestCase
@ -26,6 +27,8 @@ class InclusiveGatewayTest(BpmnWorkflowTestCase):
def testNoPathFromSecondGateway(self): def testNoPathFromSecondGateway(self):
self.set_data({'v': 0, 'u': -1, 'w': -1}) self.set_data({'v': 0, 'u': -1, 'w': -1})
self.assertRaises(WorkflowTaskException, self.workflow.do_engine_steps) self.assertRaises(WorkflowTaskException, self.workflow.do_engine_steps)
task = self.workflow.get_tasks_from_spec_name('second')[0]
self.assertEqual(task.state, TaskState.ERROR)
def testParallelCondition(self): def testParallelCondition(self):
self.set_data({'v': 0, 'u': 1, 'w': 1}) self.set_data({'v': 0, 'u': 1, 'w': 1})

View File

@ -25,9 +25,11 @@ class NestedProcessesTest(BpmnWorkflowTestCase):
self.assertEqual(1, len(self.workflow.get_tasks(TaskState.READY))) self.assertEqual(1, len(self.workflow.get_tasks(TaskState.READY)))
self.do_next_named_step('Action3') self.do_next_named_step('Action3')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.complete_subworkflow()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -32,6 +32,7 @@ class ParallelMultipleSplitsTest(BpmnWorkflowTestCase):
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.do_next_named_step('SP 3 - Yes Task') self.do_next_named_step('SP 3 - Yes Task')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.do_next_named_step('Done') self.do_next_named_step('Done')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()

View File

@ -0,0 +1,24 @@
import os
import unittest
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
from SpiffWorkflow.bpmn.parser.ProcessParser import ProcessParser
def _process_parser(bpmn_filename, process_id):
parser = BpmnParser()
bpmn_file = os.path.join(os.path.dirname(__file__), 'data', bpmn_filename)
parser.add_bpmn_file(bpmn_file)
return parser.get_process_parser(process_id)
class ProcessParserTest(unittest.TestCase):
def testReturnsEmptyListIfNoCallActivities(self):
parser = _process_parser("no-tasks.bpmn", "no_tasks")
assert parser.called_element_ids() == []
def testHandlesSingleCallActivity(self):
parser = _process_parser("single_call_activity.bpmn", "Process_p4pfxhq")
assert parser.called_element_ids() == ["SingleTask_Process"]
def testHandlesMultipleCallActivities(self):
parser = _process_parser("multiple_call_activities.bpmn", "Process_90mmqlw")
assert parser.called_element_ids() == ["Process_sypm122", "Process_diu8ta2", "Process_l14lar1"]

View File

@ -2,7 +2,7 @@ import json
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.PythonScriptEngineEnvironment import BasePythonScriptEngineEnvironment from SpiffWorkflow.bpmn.PythonScriptEngineEnvironment import BasePythonScriptEngineEnvironment, TaskDataEnvironment
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.task import TaskState from SpiffWorkflow.task import TaskState
@ -23,10 +23,19 @@ class NonTaskDataExampleEnvironment(BasePythonScriptEngineEnvironment):
self.environment.update(external_methods or {}) self.environment.update(external_methods or {})
exec(script, self.environment) exec(script, self.environment)
self.environment = {k: v for k, v in self.environment.items() if k not in external_methods} self.environment = {k: v for k, v in self.environment.items() if k not in external_methods}
return True
def user_defined_values(self): def user_defined_values(self):
return {k: v for k, v in self.environment.items() if k not in self.globals} return {k: v for k, v in self.environment.items() if k not in self.globals}
class AsyncScriptEnvironment(TaskDataEnvironment):
def execute(self, script, context, external_methods=None):
super().execute(script, context, external_methods)
return None
class PythonScriptEngineEnvironmentTest(BpmnWorkflowTestCase): class PythonScriptEngineEnvironmentTest(BpmnWorkflowTestCase):
def setUp(self): def setUp(self):
@ -78,3 +87,24 @@ class PythonScriptEngineEnvironmentTest(BpmnWorkflowTestCase):
task_data_len = len(json.dumps(task_data_to_check)) task_data_len = len(json.dumps(task_data_to_check))
return task_data_len return task_data_len
class StartedTaskTest(BpmnWorkflowTestCase):
def setUp(self):
spec, subprocesses = self.load_workflow_spec('script-start.bpmn', 'Process_cozt5fu')
self.workflow = BpmnWorkflow(spec, subprocesses)
def testStartedState(self):
script_engine_environemnt = AsyncScriptEnvironment()
script_engine = PythonScriptEngine(environment=script_engine_environemnt)
self.workflow.script_engine = script_engine
self.workflow.do_engine_steps()
script_task = self.workflow.get_tasks_from_spec_name('script')[0]
self.assertEqual(script_task.state, TaskState.STARTED)
script_task.complete()
manual_task = self.workflow.get_tasks_from_spec_name('manual')[0]
manual_task.run()
self.workflow.do_engine_steps()
end = self.workflow.get_tasks_from_spec_name('End')[0]
self.assertDictEqual(end.data, {'x': 1, 'y': 2, 'z': 3})
self.assertTrue(self.workflow.is_completed())

View File

@ -35,7 +35,7 @@ class ResetSubProcessTest(BpmnWorkflowTestCase):
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
top_level_task = self.workflow.get_ready_user_tasks()[0] top_level_task = self.workflow.get_ready_user_tasks()[0]
self.workflow.run_task_from_id(top_level_task.id) top_level_task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.save_restore() self.save_restore()
@ -50,11 +50,11 @@ class ResetSubProcessTest(BpmnWorkflowTestCase):
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual(1, len(self.workflow.get_ready_user_tasks())) self.assertEqual(1, len(self.workflow.get_ready_user_tasks()))
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(task.get_name(),'SubTask2') self.assertEqual(task.get_name(),'SubTask2')
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
task = self.workflow.get_tasks_from_spec_name('Task1')[0] task = self.workflow.get_tasks_from_spec_name('Task1')[0]
task.reset_token(self.workflow.last_task.data) task.reset_token(self.workflow.last_task.data)
@ -62,19 +62,20 @@ class ResetSubProcessTest(BpmnWorkflowTestCase):
self.reload_save_restore() self.reload_save_restore()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(task.get_name(),'Task1') self.assertEqual(task.get_name(),'Task1')
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(task.get_name(),'Subtask2') self.assertEqual(task.get_name(),'Subtask2')
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(task.get_name(),'Subtask2A') self.assertEqual(task.get_name(),'Subtask2A')
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(task.get_name(),'Task2') self.assertEqual(task.get_name(),'Task2')
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="Process_90mmqlw" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_0b6y930</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_0b6y930" sourceRef="StartEvent_1" targetRef="Activity_185dcnc" />
<bpmn:callActivity id="Activity_185dcnc" calledElement="Process_sypm122">
<bpmn:incoming>Flow_0b6y930</bpmn:incoming>
<bpmn:outgoing>Flow_0eaeoas</bpmn:outgoing>
</bpmn:callActivity>
<bpmn:sequenceFlow id="Flow_0eaeoas" sourceRef="Activity_185dcnc" targetRef="Activity_0rsppq2" />
<bpmn:callActivity id="Activity_0rsppq2" calledElement="Process_diu8ta2">
<bpmn:incoming>Flow_0eaeoas</bpmn:incoming>
<bpmn:outgoing>Flow_0hqm48x</bpmn:outgoing>
</bpmn:callActivity>
<bpmn:sequenceFlow id="Flow_0hqm48x" sourceRef="Activity_0rsppq2" targetRef="Activity_0d5dido" />
<bpmn:endEvent id="Event_0yflyfj">
<bpmn:incoming>Flow_0vhq9kk</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0vhq9kk" sourceRef="Activity_0d5dido" targetRef="Event_0yflyfj" />
<bpmn:callActivity id="Activity_0d5dido" calledElement="Process_l14lar1">
<bpmn:incoming>Flow_0hqm48x</bpmn:incoming>
<bpmn:outgoing>Flow_0vhq9kk</bpmn:outgoing>
</bpmn:callActivity>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_90mmqlw">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1xwhx08_di" bpmnElement="Activity_185dcnc">
<dc:Bounds x="270" y="137" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0c85c6h_di" bpmnElement="Activity_0rsppq2">
<dc:Bounds x="430" y="137" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0yflyfj_di" bpmnElement="Event_0yflyfj">
<dc:Bounds x="752" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1d46rm4_di" bpmnElement="Activity_0d5dido">
<dc:Bounds x="590" y="137" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0b6y930_di" bpmnElement="Flow_0b6y930">
<di:waypoint x="215" y="177" />
<di:waypoint x="270" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0eaeoas_di" bpmnElement="Flow_0eaeoas">
<di:waypoint x="370" y="177" />
<di:waypoint x="430" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0hqm48x_di" bpmnElement="Flow_0hqm48x">
<di:waypoint x="530" y="177" />
<di:waypoint x="590" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0vhq9kk_di" bpmnElement="Flow_0vhq9kk">
<di:waypoint x="690" y="177" />
<di:waypoint x="752" y="177" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="no_tasks" name="No Tasks" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_184umot</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:endEvent id="Event_0qq9il3">
<bpmn:incoming>Flow_184umot</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_184umot" sourceRef="StartEvent_1" targetRef="Event_0qq9il3" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="no_tasks">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0qq9il3_di" bpmnElement="Event_0qq9il3">
<dc:Bounds x="272" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_184umot_di" bpmnElement="Flow_184umot">
<di:waypoint x="215" y="177" />
<di:waypoint x="272" y="177" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="Process_cozt5fu" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1r4la8u</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1r4la8u" sourceRef="StartEvent_1" targetRef="Gateway_1b4ue4p" />
<bpmn:parallelGateway id="Gateway_1b4ue4p">
<bpmn:incoming>Flow_1r4la8u</bpmn:incoming>
<bpmn:outgoing>Flow_0rx8ly6</bpmn:outgoing>
<bpmn:outgoing>Flow_0m6kw0s</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:sequenceFlow id="Flow_0rx8ly6" sourceRef="Gateway_1b4ue4p" targetRef="script" />
<bpmn:sequenceFlow id="Flow_0m6kw0s" sourceRef="Gateway_1b4ue4p" targetRef="manual" />
<bpmn:scriptTask id="script" name="script">
<bpmn:incoming>Flow_0rx8ly6</bpmn:incoming>
<bpmn:outgoing>Flow_1wcrqdb</bpmn:outgoing>
<bpmn:script>x, y = 1, 2
z = x + y</bpmn:script>
</bpmn:scriptTask>
<bpmn:manualTask id="manual" name="manual">
<bpmn:incoming>Flow_0m6kw0s</bpmn:incoming>
<bpmn:outgoing>Flow_0npa1g8</bpmn:outgoing>
</bpmn:manualTask>
<bpmn:sequenceFlow id="Flow_1wcrqdb" sourceRef="script" targetRef="Gateway_0lxkg29" />
<bpmn:sequenceFlow id="Flow_0npa1g8" sourceRef="manual" targetRef="Gateway_0lxkg29" />
<bpmn:parallelGateway id="Gateway_0lxkg29">
<bpmn:incoming>Flow_1wcrqdb</bpmn:incoming>
<bpmn:incoming>Flow_0npa1g8</bpmn:incoming>
<bpmn:outgoing>Flow_1vd5x0n</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:endEvent id="Event_05ezfux">
<bpmn:incoming>Flow_1vd5x0n</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1vd5x0n" sourceRef="Gateway_0lxkg29" targetRef="Event_05ezfux" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_cozt5fu">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0wzobnw_di" bpmnElement="Gateway_1b4ue4p">
<dc:Bounds x="265" y="152" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ufpwld_di" bpmnElement="script">
<dc:Bounds x="370" y="137" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0q6915b_di" bpmnElement="manual">
<dc:Bounds x="370" y="250" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1rol38p_di" bpmnElement="Gateway_0lxkg29">
<dc:Bounds x="535" y="265" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_05ezfux_di" bpmnElement="Event_05ezfux">
<dc:Bounds x="632" y="272" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1r4la8u_di" bpmnElement="Flow_1r4la8u">
<di:waypoint x="215" y="177" />
<di:waypoint x="265" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0rx8ly6_di" bpmnElement="Flow_0rx8ly6">
<di:waypoint x="315" y="177" />
<di:waypoint x="370" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0m6kw0s_di" bpmnElement="Flow_0m6kw0s">
<di:waypoint x="290" y="202" />
<di:waypoint x="290" y="290" />
<di:waypoint x="370" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1wcrqdb_di" bpmnElement="Flow_1wcrqdb">
<di:waypoint x="470" y="177" />
<di:waypoint x="560" y="177" />
<di:waypoint x="560" y="265" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0npa1g8_di" bpmnElement="Flow_0npa1g8">
<di:waypoint x="470" y="290" />
<di:waypoint x="535" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1vd5x0n_di" bpmnElement="Flow_1vd5x0n">
<di:waypoint x="585" y="290" />
<di:waypoint x="632" y="290" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,563 @@
{
"serializer_version": "1.1",
"data": {},
"last_task": "3a4a6596-3b3d-4cd5-9724-cd1ccc263676",
"success": true,
"tasks": {
"d10fb568-6104-4a26-9081-e29c8eb42e70": {
"id": "d10fb568-6104-4a26-9081-e29c8eb42e70",
"parent": null,
"children": [
"f0a4e631-c30a-4444-b2b1-2cdc21179c65"
],
"last_state_change": 1681913960.451874,
"state": 32,
"task_spec": "Root",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"f0a4e631-c30a-4444-b2b1-2cdc21179c65": {
"id": "f0a4e631-c30a-4444-b2b1-2cdc21179c65",
"parent": "d10fb568-6104-4a26-9081-e29c8eb42e70",
"children": [
"3468f48a-c493-4731-9484-0821d046a0bc"
],
"last_state_change": 1681913960.4591289,
"state": 32,
"task_spec": "Start",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"3468f48a-c493-4731-9484-0821d046a0bc": {
"id": "3468f48a-c493-4731-9484-0821d046a0bc",
"parent": "f0a4e631-c30a-4444-b2b1-2cdc21179c65",
"children": [
"0366c1b3-d55e-42e4-a6fd-db2d6a1940eb"
],
"last_state_change": 1681913960.460862,
"state": 32,
"task_spec": "StartEvent_1",
"triggered": false,
"workflow_name": "main",
"internal_data": {
"event_fired": true
},
"data": {}
},
"0366c1b3-d55e-42e4-a6fd-db2d6a1940eb": {
"id": "0366c1b3-d55e-42e4-a6fd-db2d6a1940eb",
"parent": "3468f48a-c493-4731-9484-0821d046a0bc",
"children": [
"afd334bf-f987-46b3-b6df-779562c4b4bf",
"ad8b1640-55ac-4ff5-b07e-16c0b7c92976"
],
"last_state_change": 1681913960.4621637,
"state": 32,
"task_spec": "task_1.BoundaryEventParent",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"afd334bf-f987-46b3-b6df-779562c4b4bf": {
"id": "afd334bf-f987-46b3-b6df-779562c4b4bf",
"parent": "0366c1b3-d55e-42e4-a6fd-db2d6a1940eb",
"children": [
"3a4a6596-3b3d-4cd5-9724-cd1ccc263676"
],
"last_state_change": 1681913960.4634154,
"state": 32,
"task_spec": "task_1",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"3a4a6596-3b3d-4cd5-9724-cd1ccc263676": {
"id": "3a4a6596-3b3d-4cd5-9724-cd1ccc263676",
"parent": "afd334bf-f987-46b3-b6df-779562c4b4bf",
"children": [
"8ee8a04c-e784-4419-adb4-7c7f99f72bf6",
"00c5b447-760e-47dc-a77b-cffbf893d098"
],
"last_state_change": 1681913960.4667528,
"state": 32,
"task_spec": "Gateway_1eg2w56",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"8ee8a04c-e784-4419-adb4-7c7f99f72bf6": {
"id": "8ee8a04c-e784-4419-adb4-7c7f99f72bf6",
"parent": "3a4a6596-3b3d-4cd5-9724-cd1ccc263676",
"children": [
"cee7ab8e-d50b-4681-94f2-51bbd8dd6df1"
],
"last_state_change": 1681913960.4669333,
"state": 16,
"task_spec": "task_2",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"cee7ab8e-d50b-4681-94f2-51bbd8dd6df1": {
"id": "cee7ab8e-d50b-4681-94f2-51bbd8dd6df1",
"parent": "8ee8a04c-e784-4419-adb4-7c7f99f72bf6",
"children": [
"4695356f-8db1-48f6-a8bb-d610b2da7a63"
],
"last_state_change": 1681913960.454116,
"state": 4,
"task_spec": "Gateway_1dpu3vt",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"4695356f-8db1-48f6-a8bb-d610b2da7a63": {
"id": "4695356f-8db1-48f6-a8bb-d610b2da7a63",
"parent": "cee7ab8e-d50b-4681-94f2-51bbd8dd6df1",
"children": [
"f4ab0e07-d985-412f-aca0-369bd29797e1"
],
"last_state_change": 1681913960.45428,
"state": 4,
"task_spec": "Event_1deqprp",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"f4ab0e07-d985-412f-aca0-369bd29797e1": {
"id": "f4ab0e07-d985-412f-aca0-369bd29797e1",
"parent": "4695356f-8db1-48f6-a8bb-d610b2da7a63",
"children": [
"e326e6ec-f20d-4171-8133-24b160ad3404"
],
"last_state_change": 1681913960.4544458,
"state": 4,
"task_spec": "main.EndJoin",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"e326e6ec-f20d-4171-8133-24b160ad3404": {
"id": "e326e6ec-f20d-4171-8133-24b160ad3404",
"parent": "f4ab0e07-d985-412f-aca0-369bd29797e1",
"children": [],
"last_state_change": 1681913960.4546103,
"state": 4,
"task_spec": "End",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"00c5b447-760e-47dc-a77b-cffbf893d098": {
"id": "00c5b447-760e-47dc-a77b-cffbf893d098",
"parent": "3a4a6596-3b3d-4cd5-9724-cd1ccc263676",
"children": [
"c57e4be7-670c-41aa-9740-9fff831f6ccd"
],
"last_state_change": 1681913960.4671006,
"state": 16,
"task_spec": "task_3",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"c57e4be7-670c-41aa-9740-9fff831f6ccd": {
"id": "c57e4be7-670c-41aa-9740-9fff831f6ccd",
"parent": "00c5b447-760e-47dc-a77b-cffbf893d098",
"children": [
"ee2c8edc-5d5e-4fc2-ba4b-1801d000c6c3"
],
"last_state_change": 1681913960.454881,
"state": 4,
"task_spec": "Gateway_1dpu3vt",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"ee2c8edc-5d5e-4fc2-ba4b-1801d000c6c3": {
"id": "ee2c8edc-5d5e-4fc2-ba4b-1801d000c6c3",
"parent": "c57e4be7-670c-41aa-9740-9fff831f6ccd",
"children": [
"91a213bf-bef6-40fa-b0a4-7c7f58552184"
],
"last_state_change": 1681913960.4550629,
"state": 4,
"task_spec": "Event_1deqprp",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"91a213bf-bef6-40fa-b0a4-7c7f58552184": {
"id": "91a213bf-bef6-40fa-b0a4-7c7f58552184",
"parent": "ee2c8edc-5d5e-4fc2-ba4b-1801d000c6c3",
"children": [
"8166e255-1d17-4f94-8c0e-82cefe8500fd"
],
"last_state_change": 1681913960.4552596,
"state": 4,
"task_spec": "main.EndJoin",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"8166e255-1d17-4f94-8c0e-82cefe8500fd": {
"id": "8166e255-1d17-4f94-8c0e-82cefe8500fd",
"parent": "91a213bf-bef6-40fa-b0a4-7c7f58552184",
"children": [],
"last_state_change": 1681913960.455456,
"state": 4,
"task_spec": "End",
"triggered": false,
"workflow_name": "main",
"internal_data": {},
"data": {}
},
"ad8b1640-55ac-4ff5-b07e-16c0b7c92976": {
"id": "ad8b1640-55ac-4ff5-b07e-16c0b7c92976",
"parent": "0366c1b3-d55e-42e4-a6fd-db2d6a1940eb",
"children": [],
"last_state_change": 1681913960.463645,
"state": 64,
"task_spec": "signal",
"triggered": false,
"workflow_name": "main",
"internal_data": {
"event_fired": false
},
"data": {}
}
},
"root": "d10fb568-6104-4a26-9081-e29c8eb42e70",
"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_1deqprp"
],
"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": [
"task_1.BoundaryEventParent"
],
"lane": null,
"documentation": null,
"position": {
"x": 179.0,
"y": 99.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"event_definition": {
"internal": false,
"external": false,
"typename": "NoneEventDefinition"
},
"typename": "StartEvent",
"extensions": {}
},
"task_1": {
"id": "main_5",
"name": "task_1",
"description": "Task 1",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"task_1.BoundaryEventParent"
],
"outputs": [
"Gateway_1eg2w56"
],
"lane": null,
"documentation": null,
"position": {
"x": 270.0,
"y": 77.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"typename": "NoneTask",
"extensions": {}
},
"task_1.BoundaryEventParent": {
"id": "main_6",
"name": "task_1.BoundaryEventParent",
"description": "",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"StartEvent_1"
],
"outputs": [
"task_1",
"signal"
],
"lane": null,
"documentation": null,
"position": {
"x": 0,
"y": 0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"main_child_task_spec": "task_1",
"typename": "_BoundaryEventParent"
},
"signal": {
"id": "main_7",
"name": "signal",
"description": "Signal Event",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"task_1.BoundaryEventParent"
],
"outputs": [],
"lane": null,
"documentation": null,
"position": {
"x": 302.0,
"y": 139.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"event_definition": {
"internal": true,
"external": true,
"name": "Signal_08n3u9r",
"typename": "SignalEventDefinition"
},
"cancel_activity": true,
"typename": "BoundaryEvent",
"extensions": {}
},
"Gateway_1eg2w56": {
"id": "main_8",
"name": "Gateway_1eg2w56",
"description": null,
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"task_1"
],
"outputs": [
"task_2",
"task_3"
],
"lane": null,
"documentation": null,
"position": {
"x": 425.0,
"y": 92.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"split_task": null,
"threshold": null,
"cancel": false,
"typename": "ParallelGateway",
"extensions": {}
},
"task_2": {
"id": "main_9",
"name": "task_2",
"description": "Task 2",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"Gateway_1eg2w56"
],
"outputs": [
"Gateway_1dpu3vt"
],
"lane": null,
"documentation": null,
"position": {
"x": 530.0,
"y": 77.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"typename": "NoneTask",
"extensions": {}
},
"Gateway_1dpu3vt": {
"id": "main_10",
"name": "Gateway_1dpu3vt",
"description": null,
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"task_2",
"task_3"
],
"outputs": [
"Event_1deqprp"
],
"lane": null,
"documentation": null,
"position": {
"x": 685.0,
"y": 92.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"split_task": null,
"threshold": null,
"cancel": false,
"typename": "ParallelGateway",
"extensions": {}
},
"Event_1deqprp": {
"id": "main_11",
"name": "Event_1deqprp",
"description": null,
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"Gateway_1dpu3vt"
],
"outputs": [
"main.EndJoin"
],
"lane": null,
"documentation": null,
"position": {
"x": 792.0,
"y": 99.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"event_definition": {
"internal": false,
"external": false,
"typename": "NoneEventDefinition"
},
"typename": "EndEvent",
"extensions": {}
},
"task_3": {
"id": "main_12",
"name": "task_3",
"description": "Task 3",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [
"Gateway_1eg2w56"
],
"outputs": [
"Gateway_1dpu3vt"
],
"lane": null,
"documentation": null,
"position": {
"x": 530.0,
"y": 190.0
},
"data_input_associations": [],
"data_output_associations": [],
"io_specification": null,
"typename": "NoneTask",
"extensions": {}
},
"Root": {
"id": "main_13",
"name": "Root",
"description": "",
"manual": false,
"internal": false,
"lookahead": 2,
"inputs": [],
"outputs": [],
"typename": "Simple"
}
},
"io_specification": null,
"data_objects": {},
"correlation_keys": {},
"typename": "BpmnProcessSpec"
},
"subprocess_specs": {},
"subprocesses": {},
"bpmn_messages": [],
"correlations": {}
}

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="Process_p4pfxhq" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_04380wl</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_04380wl" sourceRef="StartEvent_1" targetRef="Activity_0q1z4d4" />
<bpmn:endEvent id="Event_05ktmeu">
<bpmn:incoming>Flow_1io4ukf</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1io4ukf" sourceRef="Activity_0q1z4d4" targetRef="Event_05ktmeu" />
<bpmn:callActivity id="Activity_0q1z4d4" calledElement="SingleTask_Process">
<bpmn:incoming>Flow_04380wl</bpmn:incoming>
<bpmn:outgoing>Flow_1io4ukf</bpmn:outgoing>
</bpmn:callActivity>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_p4pfxhq">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_05ktmeu_di" bpmnElement="Event_05ktmeu">
<dc:Bounds x="432" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0tmeu68_di" bpmnElement="Activity_0q1z4d4">
<dc:Bounds x="270" y="137" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_04380wl_di" bpmnElement="Flow_04380wl">
<di:waypoint x="215" y="177" />
<di:waypoint x="270" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1io4ukf_di" bpmnElement="Flow_1io4ukf">
<di:waypoint x="370" y="177" />
<di:waypoint x="432" y="177" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -50,6 +50,7 @@ class ActionManagementTest(BpmnWorkflowTestCase):
self.do_next_named_step("Complete Work", choice="Done") self.do_next_named_step("Complete Work", choice="Done")
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())
@ -91,6 +92,7 @@ class ActionManagementTest(BpmnWorkflowTestCase):
self.do_next_named_step("Complete Work", choice="Done") self.do_next_named_step("Complete Work", choice="Done")
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertTrue(self.workflow.is_completed()) self.assertTrue(self.workflow.is_completed())

View File

@ -80,6 +80,7 @@ class CallActivityEscalationTest(BpmnWorkflowTestCase):
for task in self.workflow.get_tasks(TaskState.READY): for task in self.workflow.get_tasks(TaskState.READY):
task.set_data(should_escalate=False) task.set_data(should_escalate=False)
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.workflow.run_all() self.workflow.run_all()
self.assertEqual(True, self.workflow.is_completed()) self.assertEqual(True, self.workflow.is_completed())

View File

@ -28,6 +28,7 @@ class MessageInterruptsSpTest(BpmnWorkflowTestCase):
self.do_next_exclusive_step('Do Something In a Subprocess') self.do_next_exclusive_step('Do Something In a Subprocess')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_exclusive_step('Ack Subprocess Done') self.do_next_exclusive_step('Ack Subprocess Done')
@ -35,8 +36,7 @@ class MessageInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughInterruptSaveAndRestore(self): def testRunThroughInterruptSaveAndRestore(self):
@ -58,8 +58,7 @@ class MessageInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -30,13 +30,13 @@ class MessageInterruptsTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING)))
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterruptSaveAndRestore(self): def testRunThroughMessageInterruptSaveAndRestore(self):
@ -61,9 +61,9 @@ class MessageInterruptsTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughHappy(self): def testRunThroughHappy(self):
@ -77,11 +77,11 @@ class MessageInterruptsTest(BpmnWorkflowTestCase):
self.do_next_exclusive_step('Do Something That Takes A Long Time') self.do_next_exclusive_step('Do Something That Takes A Long Time')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING)))
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterrupt(self): def testRunThroughMessageInterrupt(self):
@ -101,8 +101,8 @@ class MessageInterruptsTest(BpmnWorkflowTestCase):
self.do_next_exclusive_step('Acknowledge Interrupt Message') self.do_next_exclusive_step('Acknowledge Interrupt Message')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -31,13 +31,13 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING)))
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterruptSaveAndRestore(self): def testRunThroughMessageInterruptSaveAndRestore(self):
@ -71,8 +71,8 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughHappy(self): def testRunThroughHappy(self):
@ -87,11 +87,11 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.do_next_exclusive_step('Do Something That Takes A Long Time') self.do_next_exclusive_step('Do Something That Takes A Long Time')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.WAITING)))
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterrupt(self): def testRunThroughMessageInterrupt(self):
@ -118,8 +118,8 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.do_next_named_step('Do Something That Takes A Long Time') self.do_next_named_step('Do Something That Takes A Long Time')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterruptOtherOrder(self): def testRunThroughMessageInterruptOtherOrder(self):
@ -145,8 +145,8 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.do_next_named_step('Acknowledge Non-Interrupt Message') self.do_next_named_step('Acknowledge Non-Interrupt Message')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageInterruptOtherOrderSaveAndRestore(self): def testRunThroughMessageInterruptOtherOrderSaveAndRestore(self):
@ -177,8 +177,8 @@ class MessageNonInterruptTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -28,6 +28,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.do_next_exclusive_step('Do Something In a Subprocess') self.do_next_exclusive_step('Do Something In a Subprocess')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_exclusive_step('Ack Subprocess Done') self.do_next_exclusive_step('Ack Subprocess Done')
@ -35,8 +36,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageSaveAndRestore(self): def testRunThroughMessageSaveAndRestore(self):
@ -53,6 +53,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.do_next_named_step('Do Something In a Subprocess') self.do_next_named_step('Do Something In a Subprocess')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_named_step('Ack Subprocess Done') self.do_next_named_step('Ack Subprocess Done')
@ -64,8 +65,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageOrder2SaveAndRestore(self): def testRunThroughMessageOrder2SaveAndRestore(self):
@ -81,6 +81,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.workflow.catch(MessageEventDefinition('Test Message')) self.workflow.catch(MessageEventDefinition('Test Message'))
self.do_next_named_step('Do Something In a Subprocess') self.do_next_named_step('Do Something In a Subprocess')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_named_step('Acknowledge SP Parallel Message') self.do_next_named_step('Acknowledge SP Parallel Message')
@ -92,8 +93,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughMessageOrder3SaveAndRestore(self): def testRunThroughMessageOrder3SaveAndRestore(self):
@ -114,6 +114,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.do_next_named_step('Do Something In a Subprocess') self.do_next_named_step('Do Something In a Subprocess')
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.save_restore() self.save_restore()
self.do_next_named_step('Ack Subprocess Done') self.do_next_named_step('Ack Subprocess Done')
@ -121,8 +122,7 @@ class MessageNonInterruptsSpTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -27,12 +27,11 @@ class MessagesTest(BpmnWorkflowTestCase):
self.workflow.catch(MessageEventDefinition('Test Message')) self.workflow.catch(MessageEventDefinition('Test Message'))
self.assertEqual(1, len(self.workflow.get_tasks(TaskState.READY))) self.assertEqual(1, len(self.workflow.get_tasks(TaskState.READY)))
self.assertEqual( self.assertEqual('Test Message', self.workflow.get_tasks(TaskState.READY)[0].task_spec.description)
'Test Message', self.workflow.get_tasks(TaskState.READY)[0].task_spec.description)
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def testRunThroughSaveAndRestore(self): def testRunThroughSaveAndRestore(self):
@ -52,8 +51,8 @@ class MessagesTest(BpmnWorkflowTestCase):
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.assertEqual( self.complete_subworkflow()
0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING))) self.assertEqual(0, len(self.workflow.get_tasks(TaskState.READY | TaskState.WAITING)))
def suite(): def suite():

View File

@ -19,6 +19,7 @@ class MultipleThrowEventIntermediateCatchTest(BpmnWorkflowTestCase):
if save_restore: if save_restore:
self.save_restore() self.save_restore()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(len(self.workflow.get_waiting_tasks()), 0) self.assertEqual(len(self.workflow.get_waiting_tasks()), 0)
self.assertEqual(self.workflow.is_completed(), True) self.assertEqual(self.workflow.is_completed(), True)
@ -44,4 +45,5 @@ class MultipleThrowEventStartsEventTest(BpmnWorkflowTestCase):
self.assertEqual(len(ready_tasks), 1) self.assertEqual(len(ready_tasks), 1)
ready_tasks[0].run() ready_tasks[0].run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(self.workflow.is_completed(), True) self.assertEqual(self.workflow.is_completed(), True)

View File

@ -65,6 +65,8 @@ class NITimerDurationTest(BpmnWorkflowTestCase):
task.run() task.run()
self.workflow.refresh_waiting_tasks() self.workflow.refresh_waiting_tasks()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(self.workflow.is_completed(), True) self.assertEqual(self.workflow.is_completed(), True)
self.assertEqual(self.workflow.last_task.data, {'work_done': 'Yes', 'delay_reason': 'Just Because'}) self.assertEqual(self.workflow.last_task.data, {'work_done': 'Yes', 'delay_reason': 'Just Because'})

View File

@ -25,6 +25,7 @@ class TransactionSubprocessTest(BpmnWorkflowTestCase):
ready_tasks[0].update_data({'quantity': 2}) ready_tasks[0].update_data({'quantity': 2})
ready_tasks[0].run() ready_tasks[0].run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertIn('value', self.workflow.last_task.data) self.assertIn('value', self.workflow.last_task.data)
# Check that workflow and next task completed # Check that workflow and next task completed

View File

@ -23,6 +23,10 @@ class Version_1_0_Test(BaseTestCase):
self.assertEqual('Action3', ready_tasks[0].task_spec.description) self.assertEqual('Action3', ready_tasks[0].task_spec.description)
ready_tasks[0].run() ready_tasks[0].run()
wf.do_engine_steps() wf.do_engine_steps()
wf.refresh_waiting_tasks()
wf.do_engine_steps()
wf.refresh_waiting_tasks()
wf.do_engine_steps()
self.assertEqual(True, wf.is_completed()) self.assertEqual(True, wf.is_completed())
@ -34,12 +38,16 @@ class Version_1_1_Test(BaseTestCase):
wf.script_engine = PythonScriptEngine(environment=TaskDataEnvironment({"time": time})) wf.script_engine = PythonScriptEngine(environment=TaskDataEnvironment({"time": time}))
wf.refresh_waiting_tasks() wf.refresh_waiting_tasks()
wf.do_engine_steps() wf.do_engine_steps()
wf.refresh_waiting_tasks()
wf.do_engine_steps()
self.assertTrue(wf.is_completed()) self.assertTrue(wf.is_completed())
def test_convert_data_specs(self): def test_convert_data_specs(self):
fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-data.json') fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-data.json')
wf = self.serializer.deserialize_json(open(fn).read()) wf = self.serializer.deserialize_json(open(fn).read())
wf.do_engine_steps() wf.do_engine_steps()
wf.refresh_waiting_tasks()
wf.do_engine_steps()
self.assertTrue(wf.is_completed()) self.assertTrue(wf.is_completed())
def test_convert_exclusive_gateway(self): def test_convert_exclusive_gateway(self):
@ -71,3 +79,16 @@ class Version_1_1_Test(BaseTestCase):
wf.refresh_waiting_tasks() wf.refresh_waiting_tasks()
self.assertTrue(wf.is_completed()) self.assertTrue(wf.is_completed())
self.assertEqual(wf.last_task.data['counter'], 20) self.assertEqual(wf.last_task.data['counter'], 20)
def test_update_task_states(self):
fn = os.path.join(self.DATA_DIR, 'serialization', 'v1.1-task-states.json')
wf = self.serializer.deserialize_json(open(fn).read())
start = wf.get_tasks_from_spec_name('Start')[0]
self.assertEqual(start.state, TaskState.COMPLETED)
signal = wf.get_tasks_from_spec_name('signal')[0]
self.assertEqual(signal.state, TaskState.CANCELLED)
ready_tasks = wf.get_tasks(TaskState.READY)
while len(ready_tasks) > 0:
ready_tasks[0].run()
ready_tasks = wf.get_tasks(TaskState.READY)
self.assertTrue(wf.is_completed())

View File

@ -41,7 +41,7 @@ class CallActivityMessageTest(BaseTestCase):
current_task.update_data(step[1]) current_task.update_data(step[1])
current_task.run() current_task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.workflow.refresh_waiting_tasks() self.complete_subworkflow()
if save_restore: self.save_restore() if save_restore: self.save_restore()
ready_tasks = self.workflow.get_tasks(TaskState.READY) ready_tasks = self.workflow.get_tasks(TaskState.READY)
self.assertEqual(self.workflow.is_completed(),True,'Expected the workflow to be complete at this point') self.assertEqual(self.workflow.is_completed(),True,'Expected the workflow to be complete at this point')

View File

@ -50,7 +50,7 @@ class ExternalMessageBoundaryTest(BaseTestCase):
self.workflow.catch(MessageEventDefinition('reset', payload='SomethingDrastic', result_var='reset_var')) self.workflow.catch(MessageEventDefinition('reset', payload='SomethingDrastic', result_var='reset_var'))
ready_tasks = self.workflow.get_tasks(TaskState.READY) ready_tasks = self.workflow.get_tasks(TaskState.READY)
# The user activity was cancelled and we should continue from the boundary event # The user activity was cancelled and we should continue from the boundary event
self.assertEqual(1, len(ready_tasks),'Expected to have two ready tasks') self.assertEqual(2, len(ready_tasks), 'Expected to have two ready tasks')
event = self.workflow.get_tasks_from_spec_name('Event_19detfv')[0] event = self.workflow.get_tasks_from_spec_name('Event_19detfv')[0]
event.run() event.run()
self.assertEqual('SomethingDrastic', event.data['reset_var']) self.assertEqual('SomethingDrastic', event.data['reset_var'])

View File

@ -84,6 +84,7 @@ class NIMessageBoundaryTest(BaseTestCase):
task.data['work_completed'] = 'Lots of Stuff' task.data['work_completed'] = 'Lots of Stuff'
self.workflow.run_task_from_id(task.id) self.workflow.run_task_from_id(task.id)
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
self.assertEqual(self.workflow.is_completed(),True) self.assertEqual(self.workflow.is_completed(),True)
self.assertEqual(self.workflow.last_task.data,{'Event_InterruptBoundary_Response': 'Youre late!', self.assertEqual(self.workflow.last_task.data,{'Event_InterruptBoundary_Response': 'Youre late!',
'flag_task': 'Yes', 'flag_task': 'Yes',

View File

@ -51,7 +51,7 @@ class ResetTokenTestSubProcess(BaseTestCase):
firsttaskid = task.id firsttaskid = task.id
self.assertEqual(step['taskname'], task.task_spec.name) self.assertEqual(step['taskname'], task.task_spec.name)
task.update_data({step['formvar']: step['answer']}) task.update_data({step['formvar']: step['answer']})
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
if save_restore: if save_restore:
self.save_restore() self.save_restore()
@ -75,8 +75,9 @@ class ResetTokenTestSubProcess(BaseTestCase):
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual(step['taskname'], task.task_spec.name) self.assertEqual(step['taskname'], task.task_spec.name)
task.update_data({step['formvar']: step['answer']}) task.update_data({step['formvar']: step['answer']})
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
if save_restore: if save_restore:
self.save_restore() self.save_restore()

View File

@ -31,8 +31,9 @@ class SubWorkflowTest(BaseTestCase):
task = self.workflow.get_ready_user_tasks()[0] task = self.workflow.get_ready_user_tasks()[0]
self.assertEqual("Activity_"+answer, task.task_spec.name) self.assertEqual("Activity_"+answer, task.task_spec.name)
task.update_data({"Field"+answer: answer}) task.update_data({"Field"+answer: answer})
self.workflow.run_task_from_id(task.id) task.run()
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()
if save_restore: self.save_restore() if save_restore: self.save_restore()
self.assertEqual(self.workflow.last_task.data,{'FieldA': 'A', self.assertEqual(self.workflow.last_task.data,{'FieldA': 'A',

View File

@ -58,6 +58,8 @@ class PrescriptPostsciptTest(BaseTestCase):
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
ex = se.exception ex = se.exception
self.assertIn("Error occurred in the Pre-Script", str(ex)) self.assertIn("Error occurred in the Pre-Script", str(ex))
task = self.workflow.get_tasks_from_spec_name('Activity_1iqs4li')[0]
self.assertEqual(task.state, TaskState.ERROR)
def call_activity_test(self, save_restore=False): def call_activity_test(self, save_restore=False):
@ -82,3 +84,4 @@ class PrescriptPostsciptTest(BaseTestCase):
ready_tasks = self.workflow.get_tasks(TaskState.READY) ready_tasks = self.workflow.get_tasks(TaskState.READY)
ready_tasks[0].set_data(**data) ready_tasks[0].set_data(**data)
self.workflow.do_engine_steps() self.workflow.do_engine_steps()
self.complete_subworkflow()