Skip to content

Commit

Permalink
Merge branch 'release/0.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
zambrovski committed Oct 25, 2024
2 parents be05d95 + 2af0ecf commit cc8e1b3
Show file tree
Hide file tree
Showing 71 changed files with 1,704 additions and 367 deletions.
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
</parent>

<artifactId>process-engine-api</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
</parent>

<artifactId>process-engine-api-bom</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion engine-adapter/adapter-commons-spring-boot-starter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion engine-adapter/adapter-commons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion engine-adapter/adapter-testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion engine-adapter/camunda-platform-7-embedded-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import dev.bpmcrafters.processengineapi.adapter.c7.embedded.task.delivery.toTask
import dev.bpmcrafters.processengineapi.adapter.commons.task.SubscriptionRepository
import dev.bpmcrafters.processengineapi.adapter.commons.task.TaskSubscriptionHandle
import dev.bpmcrafters.processengineapi.task.TaskType
import mu.KLogging
import org.camunda.bpm.engine.delegate.DelegateTask

class EmbeddedEventBasedUserTaskDelivery(
private val subscriptionRepository: SubscriptionRepository
) : UserTaskDelivery {

companion object : KLogging()

fun userTaskCreated(delegateTask: DelegateTask) {
val subscriptions = subscriptionRepository.getTaskSubscriptions()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package dev.bpmcrafters.processengineapi.adapter.c7.embedded.testing

import com.tngtech.jgiven.Stage
import com.tngtech.jgiven.annotation.As
import com.tngtech.jgiven.annotation.ProvidedScenarioState
import com.tngtech.jgiven.annotation.Quoted
import com.tngtech.jgiven.annotation.ScenarioState
import com.tngtech.jgiven.annotation.*
import dev.bpmcrafters.processengineapi.CommonRestrictions
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.correlation.CorrelationApiImpl
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.correlation.SignalApiImpl
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.deploy.DeploymentApiImpl
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.process.StartProcessApiImpl
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.task.completion.C7ServiceTaskCompletionApiImpl
Expand All @@ -16,20 +15,23 @@ import dev.bpmcrafters.processengineapi.adapter.c7.embedded.task.delivery.pull.E
import dev.bpmcrafters.processengineapi.adapter.c7.embedded.task.subscription.C7TaskSubscriptionApiImpl
import dev.bpmcrafters.processengineapi.adapter.commons.task.InMemSubscriptionRepository
import dev.bpmcrafters.processengineapi.adapter.commons.task.UserTaskSupport
import dev.bpmcrafters.processengineapi.correlation.CorrelationApi
import dev.bpmcrafters.processengineapi.correlation.SignalApi
import dev.bpmcrafters.processengineapi.deploy.DeployBundleCommand
import dev.bpmcrafters.processengineapi.deploy.DeploymentApi
import dev.bpmcrafters.processengineapi.deploy.NamedResource.Companion.fromClasspath
import dev.bpmcrafters.processengineapi.process.StartProcessApi
import dev.bpmcrafters.processengineapi.task.*
import org.assertj.core.api.Assertions
import org.assertj.core.util.Lists
import org.awaitility.Awaitility
import org.camunda.bpm.engine.ProcessEngineServices
import org.camunda.bpm.engine.history.HistoricActivityInstance
import org.camunda.bpm.engine.runtime.ProcessInstance
import org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests
import org.camunda.bpm.engine.variable.VariableMap
import java.util.*
import java.util.concurrent.Executors
import java.util.function.Supplier
import kotlin.collections.set

/**
Expand Down Expand Up @@ -62,6 +64,12 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
@ProvidedScenarioState
protected lateinit var deploymentApi: DeploymentApi

@ProvidedScenarioState
protected lateinit var signalApi: SignalApi

@ProvidedScenarioState
protected lateinit var correlationApi: CorrelationApi

@ProvidedScenarioState
protected lateinit var processEngineServices: ProcessEngineServices

Expand All @@ -71,18 +79,21 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
@ProvidedScenarioState
private lateinit var embeddedPullServiceTaskDelivery: EmbeddedPullServiceTaskDelivery

@ProvidedScenarioState
protected lateinit var processInstanceSupplier: Supplier<ProcessInstance>

@ProvidedScenarioState(resolution = ScenarioState.Resolution.NAME)
private lateinit var topicToExternalTaskId: MutableMap<String, String>

@ProvidedScenarioState(resolution = ScenarioState.Resolution.NAME)
private lateinit var topicToElementId: MutableMap<String, String>

@ProvidedScenarioState(resolution = ScenarioState.Resolution.NAME)
private lateinit var activeEvents: Set<String>

@ProvidedScenarioState
protected lateinit var taskInformation: TaskInformation

@ExpectedScenarioState
protected lateinit var processInstanceId: String


/**
* Initializes the engine. should be called from a method of your test marked with `@BeforeEach`
Expand All @@ -96,6 +107,7 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
): SUBTYPE {
this.topicToExternalTaskId = mutableMapOf()
this.topicToElementId = mutableMapOf()
this.activeEvents = mutableSetOf()

this.restrictions = restrictions
this.processEngineServices = processEngineServices
Expand Down Expand Up @@ -126,6 +138,9 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
taskSubscriptionApi, restrictions, null, null
)

signalApi = SignalApiImpl(processEngineServices.runtimeService)
correlationApi = CorrelationApiImpl(processEngineServices.runtimeService)

initialize()

// activate delivery
Expand All @@ -141,6 +156,11 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
open fun initialize() {
}

@As("process instance is stared $")
open fun process_is_started(processInstanceId: String) {
this.processInstanceId = processInstanceId
BpmnAwareTests.assertThat(getProcessInstance()).isStarted
}

@As("external task of type \$topicName exists")
open fun external_task_exists(@Quoted topicName: String, activityId: String?): SUBTYPE {
Expand Down Expand Up @@ -183,9 +203,48 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
return self()
}

@As("external task of type \$jobType is completed with error \$errorMessage")
open fun external_task_is_completed_with_error(@Quoted topicName: String, errorMessage: String, variables: VariableMap): SUBTYPE {
Objects.requireNonNull(
topicToExternalTaskId[topicName], "No active external service task found, consider to assert using external_task_exists"
)
serviceTaskCompletionApi.completeTaskByError(CompleteTaskByErrorCmd(
topicToExternalTaskId.getValue(topicName), errorMessage
) { variables }).get()
return self()
}

@As("user tasks is assigned to user $")
open fun task_is_assigned_to_user(@Quoted assignee: String): SUBTYPE {
Assertions.assertThat(task().meta["assignee"]).isEqualTo(assignee)
return self()
}

@As("process waits in $")
open fun process_waits_in(@Quoted taskDescriptionKey: String): SUBTYPE {
// try to get the task
Awaitility.await().untilAsserted {
val taskIdOption = findTaskByActivityId(taskDescriptionKey)
Assertions.assertThat(taskIdOption).describedAs("Process is not waiting in user task $taskDescriptionKey", taskDescriptionKey).isNotEmpty()
taskIdOption.ifPresent { taskId -> this.taskInformation = userTaskSupport.getTaskInformation(taskId) }
}
return self()
}

@As("process waits in element $")
open fun process_waits_in_element(@Quoted activityId: String): SUBTYPE {
Awaitility.await().untilAsserted {
val activeActivityIds = processEngineServices.runtimeService.getActiveActivityIds(this.processInstanceId)
Assertions.assertThat(activeActivityIds)
.describedAs("Process is not waiting in element $activityId", activityId)
.contains(activityId)
}
return self()
}

open fun process_continues(elementId: String): SUBTYPE {
Awaitility.await().untilAsserted {
val job = BpmnAwareTests.job(elementId, processInstanceSupplier.get())
val job = BpmnAwareTests.job(elementId, getProcessInstance())
Assertions.assertThat(job).isNotNull()
BpmnAwareTests.execute(job)
}
Expand All @@ -202,43 +261,88 @@ abstract class AbstractC7EmbeddedStage<SUBTYPE : AbstractC7EmbeddedStage<SUBTYPE
}

open fun process_is_finished(): SUBTYPE {
BpmnAwareTests.assertThat(processInstanceSupplier.get()).isEnded()
val message = "Expecting %s to be ended, but it is not!. (Please " +
"make sure you have set the history service of the engine to at least " +
"'activity' or a higher level before making use of this assertion!)"
Assertions.assertThat(processEngineServices.runtimeService.createProcessInstanceQuery().processInstanceId(this.processInstanceId).singleResult())
.overridingErrorMessage(message, this.processInstanceId)
.isNull()
Assertions.assertThat(processEngineServices.historyService.createHistoricProcessInstanceQuery().processInstanceId(this.processInstanceId).singleResult())
.overridingErrorMessage(message, this.processInstanceId)
.isNotNull()
return self()
}

open fun process_has_passed(vararg elementIds: String): SUBTYPE {
BpmnAwareTests.assertThat(processInstanceSupplier.get()).hasPassed(*elementIds)
return self()
}

open fun process_is_stopped(): SUBTYPE {
processEngineServices.runtimeService.deleteProcessInstance(processInstanceSupplier.get().processInstanceId, "Stopped", false, true)
hasPassed(activityIds = elementIds, inOrder = false, hasPassed = true)
return self()
}

@As("process waits in $")
open fun process_waits_in(@Quoted taskDescriptionKey: String): SUBTYPE {
// try to get the task
Awaitility.await().untilAsserted {
val taskIdOption = findTaskByActivityId(taskDescriptionKey)
Assertions.assertThat(taskIdOption).describedAs("Process is not waiting in user task $taskDescriptionKey", taskDescriptionKey).isNotEmpty()
taskIdOption.ifPresent { taskId -> this.taskInformation = userTaskSupport.getTaskInformation(taskId) }
fun hasPassed(vararg activityIds: String, inOrder: Boolean, hasPassed: Boolean) {
require(this::processInstanceId.isInitialized) { "You must initialize with process_is_started() before accessing it." }
Assertions.assertThat(activityIds)
.overridingErrorMessage(
"Expecting list of activityIds not to be null, not to be empty and not to contain null values: %s.",
Lists.newArrayList(*activityIds)
)
.isNotNull().isNotEmpty().doesNotContainNull()
val finishedInstances: List<HistoricActivityInstance> = processEngineServices.historyService.createHistoricActivityInstanceQuery()
.processInstanceId(this.processInstanceId)
.finished()
.orderByHistoricActivityInstanceEndTime().asc()
.orderPartiallyByOccurrence().asc()
.list()
val finished: MutableList<String> = ArrayList(finishedInstances.size)
for (instance in finishedInstances) {
finished.add(instance.activityId)
}
return self()
val message = "Expecting %s " +
(if (hasPassed)
("to have passed activities %s at least once"
+ (if (inOrder) " and in order" else "") + ", ")
else
"NOT to have passed activities %s, ") +
"but actually we found that it passed %s. (Please make sure you have set the history " +
"service of the engine to at least 'activity' or a higher level before making use of this assertion!)"
val assertion = Assertions.assertThat(finished)
.overridingErrorMessage(
message,
this.processInstanceId,
Lists.newArrayList(*activityIds),
Lists.newArrayList(finished)
)
if (hasPassed) {
assertion.contains(*activityIds)
if (inOrder) {
var remainingFinished: List<String> = finished
for (activityId in activityIds) {
Assertions.assertThat(remainingFinished)
.overridingErrorMessage(
message,
this.processInstanceId,
Lists.newArrayList(*activityIds),
Lists.newArrayList(finished)
)
.contains(activityId)
remainingFinished = remainingFinished.subList(remainingFinished.indexOf(activityId) + 1, remainingFinished.size)
}
}
} else assertion.doesNotContain(*activityIds)
}


@As("user tasks is assigned to user $")
open fun task_is_assigned_to_user(@Quoted assignee: String): SUBTYPE {
Assertions.assertThat(task().meta["assignee"]).isEqualTo(assignee)
open fun process_is_stopped(): SUBTYPE {
processEngineServices.runtimeService.deleteProcessInstance(this.processInstanceId, "Stopped", false, true)
return self()
}


open fun task(): TaskInformation {
return Objects.requireNonNull(taskInformation, "No task found, consider to assert using process_waits_in")
}

private fun getProcessInstance(): ProcessInstance {
require(this::processInstanceId.isInitialized) { "You must initialize with process_is_started() before accessing it." }
return BpmnAwareTests.processInstanceQuery().processInstanceId(processInstanceId).singleResult()
}

private fun findTaskByActivityId(taskDescriptionKey: String): Optional<String> {
embeddedPullUserTaskDelivery.refresh()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>dev.bpm-crafters.process-engine-api</groupId>
<artifactId>process-engine-api-root</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -60,6 +60,21 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-bpm-junit5</artifactId>
<version>7.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Conditional
import org.springframework.context.annotation.Configuration
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

Expand Down Expand Up @@ -128,7 +129,7 @@ class C7EmbeddedAdapterAutoConfiguration {

/**
* Creates a default fixed thread pool for 10 threads used for process engine worker executions.
* This one is used for pull-strategies only.
* This one is used for pull-strategies and async event listener execution.
*/
@Bean("c7embedded-user-task-worker-executor")
@ConditionalOnMissingQualifiedBean(beanClass = ExecutorService::class, qualifier = "c7embedded-user-task-worker-executor")
Expand Down
Loading

0 comments on commit cc8e1b3

Please sign in to comment.