Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for Issues #8 and #9 #49

Merged
merged 17 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,7 @@ dmypy.json
# JetBrains IDE
.idea/

.vscode/
.vscode/

tutorial/conf.py
test.mmd
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit-pick: I wouldn't ignore the test.mmd file, which seems to be kind of random...

13 changes: 13 additions & 0 deletions bpmnconstraints/parser/bpmn_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,25 @@ def run(self):
self.__mark_gateway_elements()
if self.transitivity:
self.__add_transitivity()
self.validate_edge_cases()
return self.sequence
except Exception:
logging.warning(
"\nCould not execute model. Make sure that model is:\n1. Formatted correctly.\n2. File ends with .xml or .json."
)

def validate_edge_cases(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment/docstring here that describes the edge cases that you are fixing?
Perhaps, it makes sense to have a more specific function name, because an edge case could be just about anything...

item_indices = {item["name"]: index for index, item in enumerate(self.sequence)}
for cfo in self.sequence:
if cfo["is start"] and cfo["name"] == "XOR":
cfo["is start"] = False
for successor in cfo["successor"]:
self.sequence[item_indices[successor["name"]]]["is start"] = True
if cfo["is end"] and cfo["name"] in GATEWAY_NAMES:
cfo["is end"] = False
for predecessor in cfo["predecessor"]:
self.sequence[item_indices[predecessor["name"]]]["is end"] = True

def __mark_gateway_elements(self):
for cfo in self.sequence:
predecessors = cfo.get("predecessor")
Expand Down
24 changes: 23 additions & 1 deletion tests/test_end_constraints.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from test_utils import init_test_setup_for_compiler
from test_utils import init_test_setup_for_compiler, init_test_setup_for_parser
from file_constants import (
MULTIPLE_ENDINGS_DIAGRAM,
LINEAR_SEQUENCE_DIAGRAM_WITHOUT_START_AND_END,
XOR_GATEWAY_SEQUENCE_DIAGRAM,
LINEAR_MERMAID_GRAPH,
)


Expand All @@ -15,6 +17,26 @@ def test_end_constraint_is_generated_when_multiple_endings():
assert all(constraint in res for constraint in expected_ending_constraints)


def test_end_constraint_is_generated_with_linear_parser():
res = init_test_setup_for_parser(LINEAR_MERMAID_GRAPH)
assert res[-1]["is end"] == True


def test_end_constraint_is_generated_without_explicit_end_event():
res = init_test_setup_for_compiler(LINEAR_SEQUENCE_DIAGRAM_WITHOUT_START_AND_END)
assert "End[second element]" in res


def test_end_constraint_is_generated_when_multiple_endings():
res = init_test_setup_for_parser(XOR_GATEWAY_SEQUENCE_DIAGRAM)

assert res[-1]["is end"] and res[-2]["is end"] and not res[3]["is end"]


def test_end_constraint_is_generated_when_xor_gateway():
res = init_test_setup_for_compiler(XOR_GATEWAY_SEQUENCE_DIAGRAM)
expected_ending_constraints = [
"End[activity four]",
"End[activity five]",
]
assert all(constraint in res for constraint in expected_ending_constraints)
20 changes: 18 additions & 2 deletions tests/test_init_constraints.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from test_utils import init_test_setup_for_compiler
from test_utils import init_test_setup_for_compiler, init_test_setup_for_parser
from file_constants import (
LINEAR_SEQUENCE_DIAGRAM_WITHOUT_START_AND_END,
MULTIPLE_STARTS_DIAGRAM,
XOR_GATEWAY_SEQUENCE_DIAGRAM,
)


Expand All @@ -12,4 +13,19 @@ def test_init_constraint_is_generated_without_explicit_start_event():

def test_that_each_start_has_init_constraint():
res = init_test_setup_for_compiler(MULTIPLE_STARTS_DIAGRAM)
assert ["Init[path one]", "Init[path two]"] == res
expected_init_constraints = ["Init[path one]", "Init[path two]"]
assert all(constraint in res for constraint in expected_init_constraints)


def test_missing_init_constraints_for_XOR_gate_parser():
res = init_test_setup_for_parser(XOR_GATEWAY_SEQUENCE_DIAGRAM)
assert res[4]["is start"] and res[5]["is start"] and not res[0]["is start"]


def test_missing_init_constraints_for_XOR_gate():
res = init_test_setup_for_compiler(XOR_GATEWAY_SEQUENCE_DIAGRAM)
expected_init_constraints = [
"Init[activity one]",
"Init[activity two]",
]
assert all(constraint in res for constraint in expected_init_constraints)