Skip to content

Commit

Permalink
Added special handling for event based gateways (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
gclaussn committed May 1, 2022
1 parent 0f7103b commit 9e2f2fd
Show file tree
Hide file tree
Showing 12 changed files with 391 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_BOUNDARY_EVENT;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_CALL_ACTIVITY;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_END_EVENT;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_EVENT_BASED_GATEWAY;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_INTERMEDIATE_CATCH_EVENT;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_INTERMEDIATE_THROW_EVENT;
import static org.camunda.bpm.model.bpmn.impl.BpmnModelConstants.BPMN_ELEMENT_PROCESS;
Expand Down Expand Up @@ -226,6 +227,10 @@ public boolean isCallActivity(String flowNodeId) {
return is(flowNodeId, BPMN_ELEMENT_CALL_ACTIVITY);
}

public boolean isEventBasedGateway(String flowNodeId) {
return is(flowNodeId, BPMN_ELEMENT_EVENT_BASED_GATEWAY);
}

public boolean isExternalTask(String flowNodeId) {
if (is(flowNodeId, BPMN_ELEMENT_SERVICE_TASK)) {
ServiceTask serviceTask = (ServiceTask) flowNodes.get(flowNodeId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public boolean hasPrev() {
}

public boolean isAsyncAfter() {
return flowNode.isCamundaAsyncAfter();
return type != TestCaseActivityType.EVENT_BASED_GATEWAY && flowNode.isCamundaAsyncAfter();
}

public boolean isAsyncBefore() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum TestCaseActivityType {
CONDITIONAL_CATCH,
ERROR_BOUNDARY,
ESCALATION_BOUNDARY,
EVENT_BASED_GATEWAY,
EXTERNAL_TASK,
MESSAGE_BOUNDARY,
MESSAGE_CATCH,
Expand All @@ -39,6 +40,7 @@ public enum TestCaseActivityType {

WAIT_STATE_TYPES = EnumSet.noneOf(TestCaseActivityType.class);
WAIT_STATE_TYPES.add(CONDITIONAL_CATCH);
WAIT_STATE_TYPES.add(EVENT_BASED_GATEWAY);
WAIT_STATE_TYPES.add(EXTERNAL_TASK);
WAIT_STATE_TYPES.add(MESSAGE_CATCH);
WAIT_STATE_TYPES.add(SIGNAL_CATCH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public TestCaseContext apply(TestCase testCase) {

if (bpmnSupport.isCallActivity(flowNodeId)) {
activity.setType(TestCaseActivityType.CALL_ACTIVITY);
} else if (bpmnSupport.isEventBasedGateway(flowNodeId)) {
activity.setType(TestCaseActivityType.EVENT_BASED_GATEWAY);
} else if (bpmnSupport.isExternalTask(flowNodeId)) {
activity.setType(TestCaseActivityType.EXTERNAL_TASK);
activity.setTopicName(bpmnSupport.getTopicName(flowNodeId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.community.bpmndt.GeneratorStrategy;
import org.camunda.community.bpmndt.TestCaseActivity;
import org.camunda.community.bpmndt.TestCaseActivityType;
import org.camunda.community.bpmndt.TestCaseContext;

import com.squareup.javapoet.MethodSpec;
Expand Down Expand Up @@ -51,18 +52,24 @@ public MethodSpec apply(TestCaseContext ctx) {
strategy.applyHandlerAfter(builder);
}

String passed = getPassed(activity);
if (activity.hasNext() || activity.isProcessEnd()) {
builder.addStatement("assertThat(pi).hasPassed($S)", passed);
if (activity.hasPrev() && activity.getPrev().getType() == TestCaseActivityType.EVENT_BASED_GATEWAY) {
// ensure that event base gateway has been passed
builder.addStatement("assertThat(pi).hasPassed($S)", activity.getPrev().getId());
}

if (activity.getType() == TestCaseActivityType.EVENT_BASED_GATEWAY) {
builder.addStatement("assertThat(pi).isWaitingAt($S)", activity.getId());
} else if (activity.hasNext() || activity.isProcessEnd()) {
builder.addStatement("assertThat(pi).hasPassed($S)", getActivityId(activity));
} else {
builder.addStatement("assertThat(pi).isWaitingAt($S)", passed);
builder.addStatement("assertThat(pi).isWaitingAt($S)", getActivityId(activity));
}
}

return builder.build();
}

protected String getPassed(TestCaseActivity activity) {
protected String getActivityId(TestCaseActivity activity) {
if (activity.isMultiInstance()) {
return String.format("%s#%s", activity.getId(), ActivityTypes.MULTI_INSTANCE_BODY);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import javax.lang.model.element.Modifier;

import org.camunda.community.bpmndt.TestCaseActivity;
import org.camunda.community.bpmndt.TestCaseActivityType;

import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
Expand Down Expand Up @@ -36,7 +37,11 @@ protected CodeBlock buildHandlerMethodJavadoc() {

@Override
public void applyHandler(MethodSpec.Builder methodBuilder) {
if (activity.getType().isWaitState()) {
if (activity.hasPrev() && activity.getPrev().getType() == TestCaseActivityType.EVENT_BASED_GATEWAY) {
// if an event or job is part of an event based gateway
// the process instance is waiting at the gateway and not at the event or job
methodBuilder.addStatement("instance.apply($L)", activity.getLiteral());
} else if (activity.getType().isWaitState()) {
methodBuilder.addStatement("assertThat(pi).isWaitingAt($S)", activity.getId());
methodBuilder.addStatement("instance.apply($L)", activity.getLiteral());
}
Expand Down
7 changes: 7 additions & 0 deletions maven-plugin/src/test/it/simple.robot
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ mvn clean test
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simplecallactivity/TC_startEvent__endEvent.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simplecollaboration/TC_startEvent__endEvent.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simpleconditionalcatchevent/TC_startEvent__endEvent.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simpleeventbasedgateway/TC_Message.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simpleeventbasedgateway/TC_startEvent__eventBasedGateway.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simpleeventbasedgateway/TC_Timer.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simpleexternaltask/TC_startEvent__endEvent.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simplemessagecatchevent/TC_startEvent__endEvent.java
Should contain ${result.stdout} Writing file: target/bpmndt/generated/simplemessagethrowevent/TC_startEvent__endEvent.java
Expand All @@ -62,6 +65,9 @@ mvn clean test
File should exist ${testSources}/generated/simplecallactivity/TC_startEvent__endEvent.java
File should exist ${testSources}/generated/simplecollaboration/TC_startEvent__endEvent.java
File should exist ${testSources}/generated/simpleconditionalcatchevent/TC_startEvent__endEvent.java
File should exist ${testSources}/generated/simpleeventbasedgateway/TC_Message.java
File should exist ${testSources}/generated/simpleeventbasedgateway/TC_startEvent__eventBasedGateway.java
File should exist ${testSources}/generated/simpleeventbasedgateway/TC_Timer.java
File should exist ${testSources}/generated/simpleexternaltask/TC_startEvent__endEvent.java
File should exist ${testSources}/generated/simplemessagecatchevent/TC_startEvent__endEvent.java
File should exist ${testSources}/generated/simplemessagethrowevent/TC_startEvent__endEvent.java
Expand Down Expand Up @@ -105,6 +111,7 @@ mvn clean test
Should contain ${result.stdout} Running org.example.it.SimpleCallActivityTest
Should contain ${result.stdout} Running org.example.it.SimpleCollaborationTest
Should contain ${result.stdout} Running org.example.it.SimpleConditionalCatchEventTest
Should contain ${result.stdout} Running org.example.it.SimpleEventBasedGatewayTest
Should contain ${result.stdout} Running org.example.it.SimpleExternalTaskTest
Should contain ${result.stdout} Running org.example.it.SimpleMessageCatchEventTest
Should contain ${result.stdout} Running org.example.it.SimpleMessageThrowEventTest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?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:bpmndt="http://camunda.org/schema/extension/bpmn-driven-testing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_11jbinj" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.4.0">
<bpmn:process id="simpleEventBasedGateway" isExecutable="true">
<bpmn:extensionElements>
<bpmndt:testCases>
<bpmndt:testCase>
<bpmndt:name>Message</bpmndt:name>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>eventBasedGateway</bpmndt:node>
<bpmndt:node>messageCatchEvent</bpmndt:node>
<bpmndt:node>exclusiveGateway</bpmndt:node>
<bpmndt:node>endEvent</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
<bpmndt:testCase>
<bpmndt:name>Timer</bpmndt:name>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>eventBasedGateway</bpmndt:node>
<bpmndt:node>timerCatchEvent</bpmndt:node>
<bpmndt:node>exclusiveGateway</bpmndt:node>
<bpmndt:node>endEvent</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
<bpmndt:testCase>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>eventBasedGateway</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
</bpmndt:testCases>
</bpmn:extensionElements>
<bpmn:startEvent id="startEvent">
<bpmn:outgoing>Flow_08rm99z</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_08rm99z" sourceRef="startEvent" targetRef="eventBasedGateway" />
<bpmn:eventBasedGateway id="eventBasedGateway">
<bpmn:incoming>Flow_08rm99z</bpmn:incoming>
<bpmn:outgoing>Flow_1bslquq</bpmn:outgoing>
<bpmn:outgoing>Flow_0v360v4</bpmn:outgoing>
</bpmn:eventBasedGateway>
<bpmn:intermediateCatchEvent id="messageCatchEvent">
<bpmn:incoming>Flow_1bslquq</bpmn:incoming>
<bpmn:outgoing>Flow_1bsarw0</bpmn:outgoing>
<bpmn:messageEventDefinition id="MessageEventDefinition_0sbwaf9" messageRef="Message_1ae3ahb" />
</bpmn:intermediateCatchEvent>
<bpmn:sequenceFlow id="Flow_1bslquq" sourceRef="eventBasedGateway" targetRef="messageCatchEvent" />
<bpmn:intermediateCatchEvent id="timerCatchEvent">
<bpmn:incoming>Flow_0v360v4</bpmn:incoming>
<bpmn:outgoing>Flow_1yd6t7n</bpmn:outgoing>
<bpmn:timerEventDefinition id="TimerEventDefinition_0pymvfi">
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT1H</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:intermediateCatchEvent>
<bpmn:sequenceFlow id="Flow_0v360v4" sourceRef="eventBasedGateway" targetRef="timerCatchEvent" />
<bpmn:exclusiveGateway id="exclusiveGateway">
<bpmn:incoming>Flow_1bsarw0</bpmn:incoming>
<bpmn:incoming>Flow_1yd6t7n</bpmn:incoming>
<bpmn:outgoing>Flow_15m9bx7</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_1bsarw0" sourceRef="messageCatchEvent" targetRef="exclusiveGateway" />
<bpmn:sequenceFlow id="Flow_1yd6t7n" sourceRef="timerCatchEvent" targetRef="exclusiveGateway" />
<bpmn:endEvent id="endEvent">
<bpmn:incoming>Flow_15m9bx7</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_15m9bx7" sourceRef="exclusiveGateway" targetRef="endEvent" />
</bpmn:process>
<bpmn:message id="Message_1ae3ahb" name="simpleMessage" />
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="simpleEventBasedGateway">
<bpmndi:BPMNEdge id="Flow_08rm99z_di" bpmnElement="Flow_08rm99z">
<di:waypoint x="215" y="107" />
<di:waypoint x="265" y="107" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bslquq_di" bpmnElement="Flow_1bslquq">
<di:waypoint x="315" y="107" />
<di:waypoint x="372" y="107" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0v360v4_di" bpmnElement="Flow_0v360v4">
<di:waypoint x="290" y="132" />
<di:waypoint x="290" y="220" />
<di:waypoint x="372" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1bsarw0_di" bpmnElement="Flow_1bsarw0">
<di:waypoint x="408" y="107" />
<di:waypoint x="465" y="107" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yd6t7n_di" bpmnElement="Flow_1yd6t7n">
<di:waypoint x="408" y="220" />
<di:waypoint x="490" y="220" />
<di:waypoint x="490" y="132" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_15m9bx7_di" bpmnElement="Flow_15m9bx7">
<di:waypoint x="515" y="107" />
<di:waypoint x="572" y="107" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="startEvent">
<dc:Bounds x="179" y="89" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1gubnfg_di" bpmnElement="eventBasedGateway">
<dc:Bounds x="265" y="82" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0tvu4hg_di" bpmnElement="messageCatchEvent">
<dc:Bounds x="372" y="89" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_15sz4kh_di" bpmnElement="timerCatchEvent">
<dc:Bounds x="372" y="202" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1wxau1l_di" bpmnElement="exclusiveGateway" isMarkerVisible="true">
<dc:Bounds x="465" y="82" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0j4mpjn_di" bpmnElement="endEvent">
<dc:Bounds x="572" y="89" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.example.it;

import org.junit.Rule;
import org.junit.Test;

import generated.simpleeventbasedgateway.TC_Message;
import generated.simpleeventbasedgateway.TC_Timer;
import generated.simpleeventbasedgateway.TC_startEvent__eventBasedGateway;

public class SimpleEventBasedGatewayTest {

@Rule
public TC_startEvent__eventBasedGateway tc = new TC_startEvent__eventBasedGateway();
@Rule
public TC_Message tcMessage = new TC_Message();
@Rule
public TC_Timer tcTimer = new TC_Timer();

@Test
public void testExecute() {
tc.createExecutor().execute();
}

@Test
public void testExecuteMessage() {
tcMessage.createExecutor().execute();
}

@Test
public void testExecuteTimer() {
tcTimer.createExecutor().execute();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ public void testIsCallActivity() {
assertThat(bpmnSupport.isCallActivity("callActivity"), is(true));
}

@Test
public void testIsEventBasedGateway() {
bpmnSupport = BpmnSupport.of(simple.resolve("simpleEventBasedGateway.bpmn"));
assertThat(bpmnSupport.isEventBasedGateway("eventBasedGateway"), is(true));
}

@Test
public void testIsExternalTask() {
bpmnSupport = BpmnSupport.of(simple.resolve("simpleExternalTask.bpmn"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,39 @@ public void testSimpleConditionalCatchEvent() {
containsCode(typeSpec.methodSpecs.get(1)).contains("instance.apply(conditionalCatchEvent);");
}

@Test
public void testSimpleEventBasedGateway() {
generator.generateTestCases(ctx, bpmnFile);
assertThat(result.getFiles(), hasSize(3));
assertThat(result.getFiles().get(0).typeSpec.name, equalTo("TC_Message"));
assertThat(result.getFiles().get(1).typeSpec.name, equalTo("TC_Timer"));
assertThat(result.getFiles().get(2).typeSpec.name, equalTo("TC_startEvent__eventBasedGateway"));

TypeSpec typeSpec;

typeSpec = result.getFiles().get(0).typeSpec;
assertThat(typeSpec.fieldSpecs, hasSize(1));
assertThat(typeSpec.fieldSpecs.get(0).name, equalTo("messageCatchEvent"));
assertThat(typeSpec.fieldSpecs.get(0).type, equalTo(EVENT_HANDLER));
assertThat(typeSpec.methodSpecs, hasSize(7));
assertThat(typeSpec.methodSpecs.get(6).name, equalTo("handleMessageCatchEvent"));
assertThat(typeSpec.methodSpecs.get(6).returnType, equalTo(EVENT_HANDLER));

typeSpec = result.getFiles().get(1).typeSpec;
assertThat(typeSpec.fieldSpecs, hasSize(1));
assertThat(typeSpec.fieldSpecs.get(0).name, equalTo("timerCatchEvent"));
assertThat(typeSpec.fieldSpecs.get(0).type, equalTo(JOB_HANDLER));
assertThat(typeSpec.methodSpecs, hasSize(7));
assertThat(typeSpec.methodSpecs.get(6).name, equalTo("handleTimerCatchEvent"));
assertThat(typeSpec.methodSpecs.get(6).returnType, equalTo(JOB_HANDLER));

typeSpec = result.getFiles().get(2).typeSpec;
assertThat(typeSpec.fieldSpecs, hasSize(0));
assertThat(typeSpec.methodSpecs, hasSize(7));
assertThat(typeSpec.methodSpecs.get(6).name, equalTo("isProcessEnd"));
containsCode(typeSpec.methodSpecs.get(6)).contains("return false");
}

@Test
public void testSimpleExternalTask() {
generator.generateTestCases(ctx, bpmnFile);
Expand Down
Loading

0 comments on commit 9e2f2fd

Please sign in to comment.