Skip to content

Commit

Permalink
added limited recursion protection by avoiding going into Diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
christophevg committed Mar 5, 2024
1 parent 94e4869 commit aeb7225
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 6 deletions.
2 changes: 1 addition & 1 deletion bpmn_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
BPMN Tools is a collection of tools to work with BPMN ;-)
"""

__version__ = "0.10.0"
__version__ = "0.10.1"
2 changes: 1 addition & 1 deletion bpmn_tools/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def __init__(self, on=None, **kwargs):
def on(self):
if self._on:
return self._on
return self.root.find("id", self["attachedToRef"], skip=self)
return self.root.find("id", self["attachedToRef"], skip=self, skip_classes=["Diagram"])

@property
def attributes(self):
Expand Down
7 changes: 5 additions & 2 deletions bpmn_tools/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def root(self):
else:
return self

def find(self, key, value, skip=None, stack=None):
def find(self, key, value, skip=None, skip_classes=None, stack=None):
if stack is None:
stack = []

Expand All @@ -71,6 +71,9 @@ def find(self, key, value, skip=None, stack=None):
if self is skip:
return None

if skip_classes and self.__class__.__name__ in skip_classes:
return None

# do I have the key=value attribute?
try:
if self._attributes[key] == value:
Expand All @@ -80,7 +83,7 @@ def find(self, key, value, skip=None, stack=None):

# recurse down children
for child in self.children:
match = child.find(key, value, skip=skip, stack=stack+[self])
match = child.find(key, value, skip=skip, skip_classes=skip_classes, stack=stack+[self])
if match:
return match

Expand Down
12 changes: 10 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from bpmn_tools.builder.process import Task, Branch

folder = Path(__file__).resolve().parent / "models"

def compare_strings(result, expected):
# print to std, which shows up in test output when assertion fails
print("".join(unified_diff(
Expand All @@ -22,11 +24,17 @@ def compare(result,expected):
compare_strings(result_str, expected_str)

def load_model_src(filename):
return (Path(__file__).parent / "models" / filename).read_text()
return (folder / filename).read_text()

@pytest.fixture(name="model")
def model_fixture():
def fixture(filename):
return load_model_src(filename)
return fixture

def compare_to_file(result, filename, save_to=None):
if save_to:
(Path(__file__).parent / "models" / save_to).write_text(result)
(folder / save_to).write_text(result)
try:
expected = load_model_src(filename)
expected = sanitize_xml(expected)
Expand Down
29 changes: 29 additions & 0 deletions tests/models/bad-boundaries.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance" id="definitions" exporter="Camunda Modeler" exporterVersion="5.9.0">
<bpmn:process id="process" isExecutable="false">
<bpmn:task id="task-TimerEventDefinition" name="Task" />
<bpmn:boundaryEvent id="boundary-event-TimerEventDefinition" attachedToRef="task-TimerEventDefinition">
<bpmn:timerEventDefinition id="message-event-definition-TimerEventDefinition" />
</bpmn:boundaryEvent>
<bpmn:boundaryEvent id="bad-boundary-event" attachedToRef="unknown-task">
<bpmn:timerEventDefinition id="unknown-message-event-definition" />
</bpmn:boundaryEvent>
</bpmn:process>
<bpmn:collaboration id="collaboration">
<bpmn:participant id="participant" name="lane" processRef="process" />
</bpmn:collaboration>
<bpmndi:BPMNDiagram id="diagram">
<bpmndi:BPMNPlane id="plane_collaboration" bpmnElement="collaboration">
<bpmndi:BPMNShape id="shape_participant" bpmnElement="participant" isHorizontal="true">
<dc:Bounds x="160" y="60" width="300" height="125" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape_task-TimerEventDefinition" bpmnElement="task-TimerEventDefinition">
<dc:Bounds x="250" y="90" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape_boundary-event-TimerEventDefinition" bpmnElement="boundary-event-TimerEventDefinition">
<dc:Bounds x="332" y="72" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
14 changes: 14 additions & 0 deletions tests/test_boundaries.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import xmltodict

from bpmn_tools.notation import Definitions
from bpmn_tools.collaboration import Collaboration, Participant
from bpmn_tools.flow import Process, Task
Expand Down Expand Up @@ -45,3 +47,15 @@ def test_message_boundaries(compare_model_to_file):
)

compare_model_to_file(definitions, "boundaries.bpmn", save_to="boundaries-test.bpmn")

def test_dangling_boundaries(model):
xml = model("bad-boundaries.bpmn")
d = xmltodict.parse(xml)
definitions = Definitions.from_dict(d)
for event in definitions.children_oftype(BoundaryEvent, recurse=True):
try:
assert event.on
assert event.id != "bad-boundary-event", "dangling boundary should have None"
except AssertionError:
pass

0 comments on commit aeb7225

Please sign in to comment.