mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-01-17 05:31:09 +00:00
1bed0fb3ee
cd4da465 Merge pull request #264 from sartography/bugfix/dmn-equality-with-boolean 414a59eb disambiguate DMN expressions eea53c91 Merge pull request #263 from sartography/feature/cleanup-task-completion d248d5b1 execute postscript before other complete hook tasks c09f1a90 streamline predict & remove some duplicated calls to it 64c21791 remove duplicate calls to update 4ca1076d move task update to _on_complete to ensure data is copied consistently after task related activities are done d037a7eb small changes for readability 025bc30f Quick patch -- is_executable needs to be accurate immediately. 14d3d8c3 Merge pull request #262 from sartography/feature/parser_info_features 849c223e We are jumping through a lot of complex xml parsing in SpiffWorkflow-Backend because we need to know some basic information about a BPMN process at the moment it is saved. Rather than do that work in the backend, it seems better to have SpiffWorkflow handle parsing the xml and providing a bit of metadata, including: git-subtree-dir: SpiffWorkflow git-subtree-split: cd4da465e125ca1ae1b57d227bfa324d9d4c507c
115 lines
3.8 KiB
Python
115 lines
3.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import time
|
|
from SpiffWorkflow.task import Task, TaskState
|
|
from SpiffWorkflow.workflow import Workflow
|
|
|
|
|
|
def on_reached_cb(workflow, task, taken_path):
|
|
reached_key = "%s_reached" % str(task.get_name())
|
|
n_reached = task.get_data(reached_key, 0) + 1
|
|
task.set_data(**{reached_key: n_reached,
|
|
'two': 2,
|
|
'three': 3,
|
|
'test_attribute1': 'false',
|
|
'test_attribute2': 'true'})
|
|
|
|
# Collect a list of all data.
|
|
atts = []
|
|
for key, value in list(task.data.items()):
|
|
if key in ['data',
|
|
'two',
|
|
'three',
|
|
'test_attribute1',
|
|
'test_attribute2']:
|
|
continue
|
|
if key.endswith('reached'):
|
|
continue
|
|
atts.append('='.join((key, str(value))))
|
|
|
|
# Collect a list of all task data.
|
|
props = []
|
|
for key, value in list(task.task_spec.data.items()):
|
|
props.append('='.join((key, str(value))))
|
|
|
|
# Store the list of data in the workflow.
|
|
atts = ';'.join(atts)
|
|
props = ';'.join(props)
|
|
old = task.get_data('data', '')
|
|
data = task.get_name() + ': ' + atts + '/' + props + '\n'
|
|
task.set_data(data=old + data)
|
|
|
|
# In workflows that load a subworkflow, the newly loaded children
|
|
# will not have on_reached_cb() assigned. By using this function, we
|
|
# re-assign the function in every step, thus making sure that new
|
|
# children also call on_reached_cb().
|
|
for child in task.children:
|
|
track_task(child.task_spec, taken_path)
|
|
return True
|
|
|
|
|
|
def on_complete_cb(workflow, task, taken_path):
|
|
# Record the path.
|
|
indent = ' ' * (task._get_depth() - 1)
|
|
taken_path.append('%s%s' % (indent, task.get_name()))
|
|
return True
|
|
|
|
|
|
def track_task(task_spec, taken_path):
|
|
if task_spec.reached_event.is_connected(on_reached_cb):
|
|
task_spec.reached_event.disconnect(on_reached_cb)
|
|
task_spec.reached_event.connect(on_reached_cb, taken_path)
|
|
if task_spec.completed_event.is_connected(on_complete_cb):
|
|
task_spec.completed_event.disconnect(on_complete_cb)
|
|
task_spec.completed_event.connect(on_complete_cb, taken_path)
|
|
|
|
|
|
def track_workflow(wf_spec, taken_path=None):
|
|
if taken_path is None:
|
|
taken_path = []
|
|
for name in wf_spec.task_specs:
|
|
track_task(wf_spec.task_specs[name], taken_path)
|
|
return taken_path
|
|
|
|
|
|
def run_workflow(test, wf_spec, expected_path, expected_data, workflow=None):
|
|
# Execute all tasks within the Workflow.
|
|
if workflow is None:
|
|
taken_path = track_workflow(wf_spec)
|
|
workflow = Workflow(wf_spec)
|
|
else:
|
|
taken_path = track_workflow(workflow.spec)
|
|
|
|
test.assertFalse(workflow.is_completed())
|
|
try:
|
|
# We allow the workflow to require a maximum of 5 seconds to
|
|
# complete, to allow for testing long running tasks.
|
|
for i in range(10):
|
|
workflow.complete_all(False)
|
|
if workflow.is_completed():
|
|
break
|
|
time.sleep(0.5)
|
|
except:
|
|
workflow.task_tree.dump()
|
|
raise
|
|
|
|
# workflow.task_tree.dump()
|
|
test.assertTrue(workflow.is_completed(), workflow.task_tree.get_dump())
|
|
|
|
# Make sure that there are no waiting tasks left in the tree.
|
|
for thetask in Task.Iterator(workflow.task_tree, TaskState.READY):
|
|
workflow.task_tree.dump()
|
|
raise Exception('Task with state READY: %s' % thetask.name)
|
|
|
|
# Check whether the correct route was taken.
|
|
if expected_path is not None:
|
|
taken_path = '\n'.join(taken_path) + '\n'
|
|
test.assertEqual(taken_path, expected_path)
|
|
|
|
# Check data availibility.
|
|
if expected_data is not None:
|
|
result = workflow.get_data('data', '')
|
|
test.assertIn(result, expected_data)
|
|
|
|
return workflow
|