Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gclaussn committed Jan 1, 2025
1 parent 855f4db commit 6aabf4d
Show file tree
Hide file tree
Showing 16 changed files with 418 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ void broadcast(ZeebeClient client, String signalName) {
}

private SignalSubscriptionMemo getSignalSubscription(TestCaseInstance instance, long flowScopeKey) {
var flowScopeKeys = instance.getKeys(flowScopeKey);

return instance.select(memo -> {
var signalSubscription = memo.signalSubscriptions.stream().filter(s ->
s.flowScopeKey == flowScopeKey && Objects.equals(s.elementId, element.id)
flowScopeKeys.contains(s.flowScopeKey) && Objects.equals(s.elementId, element.id)
).findFirst();

if (signalSubscription.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.camunda.community.bpmndt.api;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
Expand Down Expand Up @@ -116,8 +118,8 @@ public long getFlowScopeKey(long elementInstanceKey) {
return flowScopeKey != null ? flowScopeKey : -1;
}

public long getProcessInstanceKey(long flowScopeKey) {
return select(memo -> memo.getProcessInstanceKey(flowScopeKey));
public long getProcessInstanceKey(long elementInstanceKey) {
return select(memo -> memo.getProcessInstanceKey(elementInstanceKey));
}

public void hasPassed(long flowScopeKey, String elementId) {
Expand Down Expand Up @@ -220,6 +222,25 @@ public void isWaitingAt(long flowScopeKey, String elementId) {
});
}

List<Long> getKeys(long key) {
return select(memo -> {
var keys = new ArrayList<Long>(1);

var current = key;
while (true) {
keys.add(current);

var parent = memo.keys.get(current);
if (parent == null) {
break;
}
current = parent;
}

return keys;
});
}

JobMemo getJob(long flowScopeKey, String elementId) {
return select(memo -> {
var job = memo.jobs.stream().filter(j ->
Expand All @@ -238,9 +259,11 @@ JobMemo getJob(long flowScopeKey, String elementId) {
}

MessageSubscriptionMemo getMessageSubscription(long flowScopeKey, String elementId) {
var flowScopeKeys = getKeys(flowScopeKey);

return select(memo -> {
var messageSubscription = memo.messageSubscriptions.stream().filter(s ->
s.flowScopeKey == flowScopeKey && Objects.equals(s.elementId, elementId)
flowScopeKeys.contains(s.flowScopeKey) && Objects.equals(s.elementId, elementId)
).findFirst();

if (messageSubscription.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ Duration toDuration(long dueDate, long creationDate) {
}

private TimerMemo getTimer(TestCaseInstance instance, long flowScopeKey) {
var flowScopeKeys = instance.getKeys(flowScopeKey);

return instance.select(memo -> {
var timer = memo.timers.stream().filter(t ->
t.flowScopeKey == flowScopeKey && Objects.equals(t.elementId, element.id)
flowScopeKeys.contains(t.flowScopeKey) && Objects.equals(t.elementId, element.id)
).findFirst();

if (timer.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.camunda.community.bpmndt.cmd;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
Expand Down Expand Up @@ -78,6 +80,22 @@ public TestCaseContext apply(TestCase testCase) {
int nestingLevel = testCase.getStartElement().getNestingLevel();
BpmnElementScope scope = null;

if (nestingLevel != 0) { // add strategies for all parent scopes
var parents = new ArrayList<BpmnElementScope>(1);

var current = testCase.getStartElement();
while (current.hasParent()) {
parents.add(current.getParent());
current = current.getParent();
}

Collections.reverse(parents);

for (BpmnElementScope parent : parents) {
ctx.addStrategy(new SubProcessStrategy(parent));
}
}

// add strategies
for (BpmnElement element : testCase.getElements()) {
if (element.getNestingLevel() < nestingLevel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,10 @@ void testSimpleSignalStartEvent() {
void testSimpleSubProcess() {
generator.generateTestCases(ctx, bpmnFile);

// BPMN process contains 2 test cases
assertThat(result.getFiles()).hasSize(2);
assertThat(result.getFiles()).hasSize(3);
assertThat(result.getFiles().get(0).typeSpec).hasName("TC_startEvent__endEvent");
assertThat(result.getFiles().get(1).typeSpec).hasName("TC_startEvent__subProcessEndEvent");
assertThat(result.getFiles().get(2).typeSpec).hasName("TC_subProcessStartEvent__endEvent");

var typeSpec = result.getFiles().get(0).typeSpec;
assertThat(typeSpec).hasMethods(8);
Expand All @@ -322,15 +322,33 @@ void testSimpleSubProcess() {
assertThat(typeSpec.methodSpecs.get(2)).containsCode("instance.hasPassed(flowScopeKey, \"subProcessStartEvent\");");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("// endEvent: subProcessEndEvent");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("instance.hasPassed(flowScopeKey, \"subProcessEndEvent\");");

typeSpec = result.getFiles().get(2).typeSpec;
assertThat(typeSpec).hasMethods(9);

assertThat(typeSpec.methodSpecs.get(1)).hasName("execute");
assertThat(typeSpec.methodSpecs.get(1)).hasParameters("instance", "flowScopeKey");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("// subProcess: subProcess");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("executeSubProcess(instance, flowScopeKey);");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("// endEvent: endEvent");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("instance.hasPassed(flowScopeKey, \"endEvent\");");

assertThat(typeSpec.methodSpecs.get(2)).hasName("executeSubProcess");
assertThat(typeSpec.methodSpecs.get(2)).hasParameters("instance", "parentFlowScopeKey");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("long flowScopeKey = instance.getElementInstanceKey(parentFlowScopeKey, \"subProcess\");");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("// startEvent: subProcessStartEvent");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("instance.hasPassed(flowScopeKey, \"subProcessStartEvent\");");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("// endEvent: subProcessEndEvent");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("instance.hasPassed(flowScopeKey, \"subProcessEndEvent\");");
}

@Test
void testSimpleSubProcessNested() {
generator.generateTestCases(ctx, bpmnFile);

// BPMN process contains 2 test cases
assertThat(result.getFiles()).hasSize(1);
assertThat(result.getFiles()).hasSize(2);
assertThat(result.getFiles().get(0).typeSpec).hasName("TC_startEvent__endEvent");
assertThat(result.getFiles().get(1).typeSpec).hasName("TC_userTask__endEvent");

var typeSpec = result.getFiles().get(0).typeSpec;
assertThat(typeSpec).hasMethods(10);
Expand Down Expand Up @@ -365,6 +383,37 @@ void testSimpleSubProcessNested() {
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.hasPassed(flowScopeKey, \"userTask\");");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("// endEvent: nestedSubProcessEndEvent");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.hasPassed(flowScopeKey, \"nestedSubProcessEndEvent\");");

typeSpec = result.getFiles().get(1).typeSpec;
assertThat(typeSpec).hasMethods(11);

assertThat(typeSpec.methodSpecs.get(1)).hasName("execute");
assertThat(typeSpec.methodSpecs.get(1)).hasParameters("instance", "flowScopeKey");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("// subProcess: subProcess");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("executeSubProcess(instance, flowScopeKey);");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("// endEvent: endEvent");
assertThat(typeSpec.methodSpecs.get(1)).containsCode("instance.hasPassed(flowScopeKey, \"endEvent\");");

assertThat(typeSpec.methodSpecs.get(2)).hasName("executeSubProcess");
assertThat(typeSpec.methodSpecs.get(2)).hasParameters("instance", "parentFlowScopeKey");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("long flowScopeKey = instance.getElementInstanceKey(parentFlowScopeKey, \"subProcess\");");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("// subProcess: nestedSubProcess");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("executeNestedSubProcess(instance, flowScopeKey);");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("// endEvent: subProcessEndEvent");
assertThat(typeSpec.methodSpecs.get(2)).containsCode("instance.hasPassed(flowScopeKey, \"subProcessEndEvent\");");

assertThat(typeSpec.methodSpecs.get(3)).hasName("executeNestedSubProcess");
assertThat(typeSpec.methodSpecs.get(3)).hasParameters("instance", "parentFlowScopeKey");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("long flowScopeKey = instance.getElementInstanceKey(parentFlowScopeKey, \"nestedSubProcess\");");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("// userTask: userTask");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.isWaitingAt(flowScopeKey, \"userTask\");");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.apply(flowScopeKey, userTask);");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.hasPassed(flowScopeKey, \"userTask\");");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("// endEvent: nestedSubProcessEndEvent");
assertThat(typeSpec.methodSpecs.get(3)).containsCode("instance.hasPassed(flowScopeKey, \"nestedSubProcessEndEvent\");");

assertThat(typeSpec.methodSpecs.get(9)).hasName("isProcessStart");
assertThat(typeSpec.methodSpecs.get(9)).containsCode("return false;");
}

@Test
Expand Down
4 changes: 3 additions & 1 deletion integration-tests-8/advanced-multi-instance.robot
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ mvn clean test
Should contain ${result.stdout} Running org.example.it.SequentialTest
Should contain ${result.stdout} Running org.example.it.UserTaskErrorTest
Should contain ${result.stdout} Running org.example.it.UserTaskMessageTest
Should contain ${result.stdout} Running org.example.it.UserTaskSignalTest
Should contain ${result.stdout} Running org.example.it.UserTaskTimerTest
# tests executed successfully
Should contain ${result.stdout} Failures: 0, Errors: 0, Skipped: 1
Should contain ${result.stdout} Failures: 0, Errors: 0, Skipped: 0

Should be equal as integers ${result.rc} 0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?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:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:bpmndt="http://camunda.org/schema/extension/bpmn-driven-testing" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1gcoroz" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.20.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
<bpmn:process id="userTaskSignal" isExecutable="true">
<bpmn:extensionElements>
<bpmndt:testCases>
<bpmndt:testCase>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>userTask</bpmndt:node>
<bpmndt:node>signalBoundaryEvent</bpmndt:node>
<bpmndt:node>endEvent</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
</bpmndt:testCases>
</bpmn:extensionElements>
<bpmn:startEvent id="startEvent">
<bpmn:outgoing>Flow_13sy9pd</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_13sy9pd" sourceRef="startEvent" targetRef="userTask" />
<bpmn:userTask id="userTask">
<bpmn:extensionElements>
<zeebe:formDefinition formKey="advanced" />
</bpmn:extensionElements>
<bpmn:incoming>Flow_13sy9pd</bpmn:incoming>
<bpmn:outgoing>Flow_047aznh</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics isSequential="true">
<bpmn:extensionElements>
<zeebe:loopCharacteristics inputCollection="=elements" />
</bpmn:extensionElements>
</bpmn:multiInstanceLoopCharacteristics>
</bpmn:userTask>
<bpmn:endEvent id="Event_18k9i1r">
<bpmn:incoming>Flow_047aznh</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_047aznh" sourceRef="userTask" targetRef="Event_18k9i1r" />
<bpmn:endEvent id="endEvent">
<bpmn:incoming>Flow_0evrcz3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0evrcz3" sourceRef="signalBoundaryEvent" targetRef="endEvent" />
<bpmn:boundaryEvent id="signalBoundaryEvent" attachedToRef="userTask">
<bpmn:outgoing>Flow_0evrcz3</bpmn:outgoing>
<bpmn:signalEventDefinition id="SignalEventDefinition_0d57h78" signalRef="Signal_39qq38d" />
</bpmn:boundaryEvent>
</bpmn:process>
<bpmn:signal id="Signal_39qq38d" name="userTaskSignal" />
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="userTaskSignal">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="startEvent">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_17i6ixt_di" bpmnElement="userTask">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18k9i1r_di" bpmnElement="Event_18k9i1r">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1cad1me_di" bpmnElement="endEvent">
<dc:Bounds x="432" y="222" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1178vqm_di" bpmnElement="signalBoundaryEvent">
<dc:Bounds x="332" y="139" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_13sy9pd_di" bpmnElement="Flow_13sy9pd">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_047aznh_di" bpmnElement="Flow_047aznh">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0evrcz3_di" bpmnElement="Flow_0evrcz3">
<di:waypoint x="350" y="175" />
<di:waypoint x="350" y="240" />
<di:waypoint x="432" y="240" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?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:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:bpmndt="http://camunda.org/schema/extension/bpmn-driven-testing" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1gcoroz" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.20.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.4.0">
<bpmn:process id="userTaskTimer" isExecutable="true">
<bpmn:extensionElements>
<bpmndt:testCases>
<bpmndt:testCase>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>userTask</bpmndt:node>
<bpmndt:node>timerBoundaryEvent</bpmndt:node>
<bpmndt:node>endEvent</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
</bpmndt:testCases>
</bpmn:extensionElements>
<bpmn:startEvent id="startEvent">
<bpmn:outgoing>Flow_13sy9pd</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_13sy9pd" sourceRef="startEvent" targetRef="userTask" />
<bpmn:userTask id="userTask">
<bpmn:extensionElements>
<zeebe:formDefinition formKey="advanced" />
</bpmn:extensionElements>
<bpmn:incoming>Flow_13sy9pd</bpmn:incoming>
<bpmn:outgoing>Flow_047aznh</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics isSequential="true">
<bpmn:extensionElements>
<zeebe:loopCharacteristics inputCollection="=elements" />
</bpmn:extensionElements>
</bpmn:multiInstanceLoopCharacteristics>
</bpmn:userTask>
<bpmn:endEvent id="Event_18k9i1r">
<bpmn:incoming>Flow_047aznh</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_047aznh" sourceRef="userTask" targetRef="Event_18k9i1r" />
<bpmn:endEvent id="endEvent">
<bpmn:incoming>Flow_0evrcz3</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0evrcz3" sourceRef="timerBoundaryEvent" targetRef="endEvent" />
<bpmn:boundaryEvent id="timerBoundaryEvent" attachedToRef="userTask">
<bpmn:outgoing>Flow_0evrcz3</bpmn:outgoing>
<bpmn:timerEventDefinition id="TimerEventDefinition_1mcgmi3">
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT1H</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:boundaryEvent>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="userTaskTimer">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="startEvent">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_17i6ixt_di" bpmnElement="userTask">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_18k9i1r_di" bpmnElement="Event_18k9i1r">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1cad1me_di" bpmnElement="endEvent">
<dc:Bounds x="432" y="222" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_11w22zx_di" bpmnElement="timerBoundaryEvent">
<dc:Bounds x="332" y="139" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_13sy9pd_di" bpmnElement="Flow_13sy9pd">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_047aznh_di" bpmnElement="Flow_047aznh">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0evrcz3_di" bpmnElement="Flow_0evrcz3">
<di:waypoint x="350" y="175" />
<di:waypoint x="350" y="240" />
<di:waypoint x="432" y="240" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ void testExecute() {
} else {
instance.apply(flowScopeKey, userTaskHandler);
}

loopCount++;
});

tc.createExecutor(engine)
Expand Down
Loading

0 comments on commit 6aabf4d

Please sign in to comment.