> stream() {
41 | return stream;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/assertions/src/main/java/io/camunda/zeebe/process/test/inspections/model/InspectedProcessInstance.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.inspections.model;
17 |
18 | /**
19 | * Helper object to gain access to {@link
20 | * io.camunda.zeebe.process.test.assertions.ProcessInstanceAssert}. All this object does is wrap a
21 | * process instance key. This object is required to use {@link
22 | * io.camunda.zeebe.process.test.assertions.BpmnAssert#assertThat(InspectedProcessInstance)}.
23 | *
24 | * The helper object enabled asserting process instances which were not started with a command
25 | * send by the client (e.g. by a timer or a call activity).
26 | */
27 | public class InspectedProcessInstance {
28 |
29 | private final long processInstanceKey;
30 |
31 | public InspectedProcessInstance(final long processInstanceKey) {
32 | this.processInstanceKey = processInstanceKey;
33 | }
34 |
35 | /**
36 | * Get the process instance key.
37 | *
38 | * @return the wrapped process instance key
39 | */
40 | public long getProcessInstanceKey() {
41 | return processInstanceKey;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/spring-test/embedded/src/main/java/io/camunda/zeebe/spring/test/ZeebeSpringTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Inherited;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 | import org.springframework.context.annotation.Import;
24 | import org.springframework.test.context.TestExecutionListeners;
25 |
26 | /** Annotation for the Spring test. */
27 | @Target({ElementType.TYPE})
28 | @Retention(RetentionPolicy.RUNTIME)
29 | @Inherited
30 | // this pulls in the Configuration NOT as AutoConfiguration but directly creates beans, so the
31 | // marker is present
32 | // when the normal CamundaAutoConfiguration is used by the normal meta-inf/services way
33 | @Import({CamundaTestAutoConfiguration.class})
34 | // this listener hooks up into test execution
35 | @TestExecutionListeners(
36 | listeners = ZeebeTestExecutionListener.class,
37 | mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
38 | public @interface ZeebeSpringTest {}
39 |
--------------------------------------------------------------------------------
/spring-test/testcontainer/src/main/java/io/camunda/zeebe/spring/test/ZeebeSpringTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test;
17 |
18 | import java.lang.annotation.ElementType;
19 | import java.lang.annotation.Inherited;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 | import org.springframework.context.annotation.Import;
24 | import org.springframework.test.context.TestExecutionListeners;
25 |
26 | /** Annotation for the Spring test. */
27 | @Target({ElementType.TYPE})
28 | @Retention(RetentionPolicy.RUNTIME)
29 | @Inherited
30 | // this pulls in the Configuration NOT as AutoConfiguration but directly creates beans, so the
31 | // marker is present
32 | // when the normal CamundaAutoConfiguration is used by the normal meta-inf/services way
33 | @Import({CamundaTestAutoConfiguration.class})
34 | // this listener hooks up into test execution
35 | @TestExecutionListeners(
36 | listeners = ZeebeTestExecutionListener.class,
37 | mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
38 | public @interface ZeebeSpringTest {}
39 |
--------------------------------------------------------------------------------
/qa/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.camunda
7 | zeebe-process-test-root
8 | 8.9.0-SNAPSHOT
9 | ../pom.xml
10 |
11 |
12 | zeebe-process-test-qa
13 | pom
14 |
15 | Zeebe Process Test QA
16 |
17 | QA tests for testing the Zeebe Process Test project.
18 |
19 |
20 | abstracts
21 | embedded
22 | testcontainers
23 |
24 |
25 |
26 |
27 |
28 | io.camunda
29 | zeebe-process-test-qa-abstracts
30 | 8.9.0-SNAPSHOT
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | org.apache.maven.plugins
39 | maven-dependency-plugin
40 |
41 | true
42 |
43 |
44 | org.slf4j:slf4j-simple
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/assertions/src/main/java/io/camunda/zeebe/process/test/inspections/FormInspectionsUtility.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.camunda.zeebe.process.test.inspections;
18 |
19 | import io.camunda.zeebe.process.test.assertions.BpmnAssert;
20 | import io.camunda.zeebe.process.test.filters.StreamFilter;
21 | import io.camunda.zeebe.protocol.record.Record;
22 | import io.camunda.zeebe.protocol.record.value.deployment.FormMetadataValue;
23 | import java.util.Comparator;
24 | import java.util.Optional;
25 | import java.util.stream.Stream;
26 |
27 | public class FormInspectionsUtility {
28 |
29 | /**
30 | * Find the latest version of a form
31 | *
32 | * @param formId the id of the form
33 | * @return the {@link Optional} latest version of the form if available
34 | */
35 | public static Optional findLatestFormById(final String formId) {
36 | return getForms()
37 | .filter(form -> formId.equals(form.getFormId()))
38 | .max(Comparator.comparingInt(FormMetadataValue::getVersion));
39 | }
40 |
41 | private static Stream getForms() {
42 | return StreamFilter.forms(BpmnAssert.getRecordStream()).stream().map(Record::getValue);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/resources/message-start-event.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_1nsh1lf
6 |
7 |
8 |
9 | Flow_1nsh1lf
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/CamundaTestAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test;
17 |
18 | import io.camunda.client.spring.configuration.CamundaAutoConfiguration;
19 | import io.camunda.client.spring.testsupport.CamundaSpringProcessTestContext;
20 | import io.camunda.zeebe.spring.test.configuration.ZeebeTestDefaultConfiguration;
21 | import io.camunda.zeebe.spring.test.proxy.TestProxyConfiguration;
22 | import org.springframework.boot.autoconfigure.AutoConfigureBefore;
23 | import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
24 | import org.springframework.boot.test.context.TestConfiguration;
25 | import org.springframework.context.annotation.Bean;
26 |
27 | @TestConfiguration
28 | @ImportAutoConfiguration({
29 | TestProxyConfiguration.class,
30 | ZeebeTestDefaultConfiguration.class,
31 | CamundaAutoConfiguration.class
32 | })
33 | @AutoConfigureBefore(CamundaAutoConfiguration.class)
34 | public class CamundaTestAutoConfiguration {
35 |
36 | @Bean
37 | public CamundaSpringProcessTestContext enableTestContext() {
38 | // add marker bean to Spring context that we are running in a test case
39 | return new CamundaSpringProcessTestContext();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/extension-testcontainer/src/main/java/io/camunda/zeebe/process/test/extension/testcontainer/RecordStreamSourceImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.extension.testcontainer;
17 |
18 | import io.camunda.zeebe.process.test.api.RecordStreamSource;
19 | import io.camunda.zeebe.protocol.record.Record;
20 | import java.util.ArrayList;
21 |
22 | /**
23 | * The source for record processed by the test engine. This class is responsible for getting the
24 | * records from the test engine and storing them locally.
25 | */
26 | public class RecordStreamSourceImpl implements RecordStreamSource {
27 |
28 | private final ContainerizedEngine engine;
29 | private Iterable> records;
30 |
31 | public RecordStreamSourceImpl(final ContainerizedEngine engine) {
32 | this(engine, new ArrayList<>());
33 | }
34 |
35 | public RecordStreamSourceImpl(
36 | final ContainerizedEngine engine, final Iterable> records) {
37 | this.engine = engine;
38 | this.records = records;
39 | }
40 |
41 | /** {@inheritDoc} */
42 | @Override
43 | public Iterable> getRecords() {
44 | updateWithNewRecords();
45 | return records;
46 | }
47 |
48 | private void updateWithNewRecords() {
49 | records = engine.getRecords();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/db/FullyQualifiedKey.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.db;
9 |
10 | import io.camunda.zeebe.db.DbKey;
11 | import io.camunda.zeebe.db.impl.ZeebeDbConstants;
12 | import org.agrona.DirectBuffer;
13 | import org.agrona.ExpandableArrayBuffer;
14 | import org.agrona.concurrent.UnsafeBuffer;
15 |
16 | /**
17 | * Helper class that represents a fully qualified key. A fully qualified key is constructed from a
18 | * column family index and the key inside that column family
19 | */
20 | final class FullyQualifiedKey {
21 |
22 | private final Bytes keyBytes;
23 |
24 | FullyQualifiedKey(final Enum columnFamily, final DbKey dbKey) {
25 | final ExpandableArrayBuffer keyBuffer = new ExpandableArrayBuffer();
26 | keyBuffer.putLong(0, columnFamily.ordinal(), ZeebeDbConstants.ZB_DB_BYTE_ORDER);
27 | dbKey.write(keyBuffer, Long.BYTES);
28 | keyBytes = Bytes.fromExpandableArrayBuffer(keyBuffer);
29 | }
30 |
31 | Bytes getKeyBytes() {
32 | return keyBytes;
33 | }
34 |
35 | /**
36 | * Extract the key from a byte array containing a fully qualified key
37 | *
38 | * @param rawKeyBytes raw key as it is stored in the database, contains column family index as
39 | * prefix
40 | * @return direct buffer with key part of
41 | */
42 | static DirectBuffer wrapKey(final byte[] rawKeyBytes) {
43 | final DirectBuffer keyViewBuffer = new UnsafeBuffer(0, 0);
44 |
45 | keyViewBuffer.wrap(rawKeyBytes, Long.BYTES, rawKeyBytes.length - Long.BYTES);
46 |
47 | return keyViewBuffer;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/proxy/CamundaClientProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test.proxy;
17 |
18 | import io.camunda.client.CamundaClient;
19 | import java.lang.reflect.Method;
20 | import org.checkerframework.checker.nullness.qual.Nullable;
21 |
22 | /**
23 | * Dynamic proxy to delegate to a {@link CamundaClient} which allows to swap the CamundaClient
24 | * object under the hood. This is used in test environments, where the Zeebe engine is
25 | * re-initialized for every test case.
26 | */
27 | public class CamundaClientProxy extends AbstractInvocationHandler {
28 |
29 | private CamundaClient delegate;
30 |
31 | public void swapZeebeClient(final CamundaClient client) {
32 | delegate = client;
33 | }
34 |
35 | public void removeCamundaClient() {
36 | delegate = null;
37 | }
38 |
39 | @Override
40 | protected Object handleInvocation(
41 | final Object proxy, final Method method, @Nullable final Object[] args) throws Throwable {
42 | if (delegate == null) {
43 | throw new RuntimeException(
44 | "Cannot invoke "
45 | + method
46 | + " on CamundaClient, as CamundaClient is currently not initialized. Maybe you run outside of a testcase?");
47 | }
48 | return method.invoke(delegate, args);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/extension/src/test/java/io/camunda/zeebe/process/test/extension/ZeebeProcessTestExtensionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.extension;
9 |
10 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
11 | import static org.mockito.Mockito.mock;
12 |
13 | import io.camunda.zeebe.process.test.filters.RecordStream;
14 | import org.junit.jupiter.api.Nested;
15 | import org.junit.jupiter.api.Test;
16 | import org.junit.jupiter.api.extension.ExtensionContext;
17 | import org.mockito.Mockito;
18 |
19 | class ZeebeProcessTestExtensionTest {
20 |
21 | @Nested
22 | class MultipleInjectedFields {
23 |
24 | private RecordStream recordStreamOne;
25 | private RecordStream recordStreamTwo;
26 |
27 | @Test
28 | void testMultipleInjectedFieldsThrowError() {
29 | // given
30 | final ZeebeProcessTestExtension extension = new ZeebeProcessTestExtension();
31 | final ExtensionContext extensionContext = mock(ExtensionContext.class);
32 |
33 | // when
34 | Mockito.>when(extensionContext.getRequiredTestClass()).thenReturn(this.getClass());
35 | Mockito.when(extensionContext.getRequiredTestInstance()).thenReturn(this);
36 |
37 | // then
38 | assertThatThrownBy(() -> extension.beforeEach(extensionContext))
39 | .isInstanceOf(IllegalStateException.class)
40 | .hasMessage(
41 | "Expected at most one field of type RecordStream, but found 2. "
42 | + "Please make sure at most one field of type RecordStream has been "
43 | + "declared in the test class.");
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/proxy/ZeebeClientProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test.proxy;
17 |
18 | import io.camunda.zeebe.client.ZeebeClient;
19 | import java.lang.reflect.Method;
20 | import org.checkerframework.checker.nullness.qual.Nullable;
21 |
22 | /**
23 | * Dynamic proxy to delegate to a {@link io.camunda.zeebe.client.ZeebeClient} which allows to swap
24 | * the ZeebeClient object under the hood. This is used in test environments, where the Zeebe engine
25 | * is re-initialized for every test case.
26 | */
27 | public class ZeebeClientProxy extends AbstractInvocationHandler {
28 |
29 | private ZeebeClient delegate;
30 |
31 | public void swapZeebeClient(final ZeebeClient client) {
32 | delegate = client;
33 | }
34 |
35 | public void removeZeebeClient() {
36 | delegate = null;
37 | }
38 |
39 | @Override
40 | protected Object handleInvocation(
41 | final Object proxy, final Method method, @Nullable final Object[] args) throws Throwable {
42 | if (delegate == null) {
43 | throw new RuntimeException(
44 | "Cannot invoke "
45 | + method
46 | + " on ZeebeClient, as ZeebeClient is currently not initialized. Maybe you run outside of a testcase?");
47 | }
48 | return method.invoke(delegate, args);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/proxy/ZeebeTestEngineProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test.proxy;
17 |
18 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
19 | import java.lang.reflect.Method;
20 | import org.checkerframework.checker.nullness.qual.Nullable;
21 |
22 | /**
23 | * Dynamic proxy to delegate to a {@link ZeebeTestEngine} which allows to swap the {@link
24 | * ZeebeTestEngine} object under the hood. This is used in test environments, where the while
25 | * ZeebeEngine is re-initialized for every test case
26 | */
27 | public class ZeebeTestEngineProxy extends AbstractInvocationHandler {
28 |
29 | private ZeebeTestEngine delegate;
30 |
31 | public void swapZeebeEngine(ZeebeTestEngine client) {
32 | this.delegate = client;
33 | }
34 |
35 | public void removeZeebeEngine() {
36 | this.delegate = null;
37 | }
38 |
39 | @Override
40 | protected Object handleInvocation(Object proxy, Method method, @Nullable Object[] args)
41 | throws Throwable {
42 | if (delegate == null) {
43 | throw new RuntimeException(
44 | "Cannot invoke "
45 | + method
46 | + " on ZeebeTestEngine, as ZeebeTestEngine is currently not initialized. Maybe you run outside of a testcase?");
47 | }
48 | return method.invoke(delegate, args);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/java/io/camunda/zeebe/process/test/qa/abstracts/mapper/AbstractMapperNotSerializationDeserializationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.camunda.zeebe.process.test.qa.abstracts.mapper;
18 |
19 | import io.camunda.zeebe.client.ZeebeClient;
20 | import io.camunda.zeebe.client.api.JsonMapper;
21 | import io.camunda.zeebe.client.api.command.InternalClientException;
22 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
23 | import java.time.LocalDateTime;
24 | import org.junit.jupiter.api.Assertions;
25 | import org.junit.jupiter.api.Test;
26 |
27 | public abstract class AbstractMapperNotSerializationDeserializationTest {
28 | protected ZeebeClient client;
29 | protected ZeebeTestEngine engine;
30 |
31 | @Test
32 | void shouldNotSerialize() {
33 | final JsonMapper jsonMapper = client.getConfiguration().getJsonMapper();
34 | final LocalDateTime localDateTime = LocalDateTime.of(2023, 7, 31, 12, 0, 0);
35 | Assertions.assertThrows(InternalClientException.class, () -> jsonMapper.toJson(localDateTime));
36 | }
37 |
38 | @Test
39 | void shouldNotDeserialize() {
40 | final JsonMapper jsonMapper = client.getConfiguration().getJsonMapper();
41 | final String json = "\"2023-07-31T12:00:00\"";
42 | Assertions.assertThrows(
43 | InternalClientException.class, () -> jsonMapper.fromJson(json, LocalDateTime.class));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/resources/timer-start-event-daily.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_0cilgmu
6 |
7 | R/P1D
8 |
9 |
10 |
11 | Flow_0cilgmu
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/VariableRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.RejectionType;
20 | import io.camunda.zeebe.protocol.record.value.VariableRecordValue;
21 | import java.util.stream.Stream;
22 | import java.util.stream.StreamSupport;
23 |
24 | public class VariableRecordStreamFilter {
25 |
26 | private Stream> stream;
27 |
28 | public VariableRecordStreamFilter(final Iterable> records) {
29 | stream = StreamSupport.stream(records.spliterator(), false);
30 | }
31 |
32 | public VariableRecordStreamFilter(final Stream> stream) {
33 | this.stream = stream;
34 | }
35 |
36 | public VariableRecordStreamFilter withProcessInstanceKey(final long processInstanceKey) {
37 | return new VariableRecordStreamFilter(
38 | stream.filter(record -> record.getValue().getProcessInstanceKey() == processInstanceKey));
39 | }
40 |
41 | public VariableRecordStreamFilter withRejectionType(final RejectionType rejectionType) {
42 | return new VariableRecordStreamFilter(
43 | stream.filter(record -> record.getRejectionType() == rejectionType));
44 | }
45 |
46 | public Stream> stream() {
47 | return stream;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/spring-test/embedded/src/test/java/io/camunda/zeebe/spring/client/jobhandling/ZeebeClientDisabledInCamundaSpringTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.client.jobhandling;
17 |
18 | import static org.junit.jupiter.api.Assertions.assertEquals;
19 |
20 | import io.camunda.zeebe.client.ZeebeClient;
21 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
22 | import io.camunda.zeebe.spring.test.ZeebeSpringTest;
23 | import org.junit.jupiter.api.Test;
24 | import org.springframework.beans.factory.annotation.Autowired;
25 | import org.springframework.boot.test.context.SpringBootTest;
26 | import org.springframework.context.ApplicationContext;
27 |
28 | @SpringBootTest(
29 | classes = {ZeebeClientDisabledInCamundaSpringTest.class},
30 | properties = {"camunda.client.zeebe.enabled=false"})
31 | @ZeebeSpringTest
32 | public class ZeebeClientDisabledInCamundaSpringTest {
33 |
34 | @Autowired private ApplicationContext ctx;
35 |
36 | @Test
37 | public void testStartup() {
38 | // a testcase with @ZeebeSpringTests ALWAYS creates a ZeebeEngine and a ZeebeClient (!), even
39 | // when "zeebe.client.enabled=false" is configured
40 | // In essence, this is an invalid configuration state - when you don't want to use
41 | // ZeebeClient,
42 | // don't use @ZeebeSpringTest
43 | assertEquals(1, ctx.getBeanNamesForType(ZeebeClient.class).length);
44 | assertEquals(1, ctx.getBeanNamesForType(ZeebeTestEngine.class).length);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/JobRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.intent.JobIntent;
20 | import io.camunda.zeebe.protocol.record.value.JobRecordValue;
21 | import java.util.stream.Stream;
22 | import java.util.stream.StreamSupport;
23 |
24 | public class JobRecordStreamFilter {
25 |
26 | private final Stream> stream;
27 |
28 | public JobRecordStreamFilter(final Iterable> records) {
29 | stream = StreamSupport.stream(records.spliterator(), false);
30 | }
31 |
32 | public JobRecordStreamFilter(final Stream> stream) {
33 | this.stream = stream;
34 | }
35 |
36 | public JobRecordStreamFilter withKey(final long key) {
37 | return new JobRecordStreamFilter(stream.filter(record -> record.getKey() == key));
38 | }
39 |
40 | public JobRecordStreamFilter withIntent(final JobIntent intent) {
41 | return new JobRecordStreamFilter(stream.filter(record -> record.getIntent() == intent));
42 | }
43 |
44 | public JobRecordStreamFilter withElementId(final String elementId) {
45 | return new JobRecordStreamFilter(
46 | stream.filter(record -> record.getValue().getElementId().equals(elementId)));
47 | }
48 |
49 | public Stream> stream() {
50 | return stream;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/engine-agent/src/main/java/io/camunda/zeebe/process/test/engine/agent/AgentProperties.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.agent;
9 |
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.util.Properties;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | public class AgentProperties {
17 |
18 | private static final Logger LOG = LoggerFactory.getLogger(AgentProperties.class);
19 |
20 | private static final String PROPERTIES_FILE = "/config.properties";
21 | public static final String GATEWAY_PORT = "gateway.port";
22 | public static final String CONTROLLER_PORT = "controller.port";
23 | private static final Properties PROPERTIES = new Properties();
24 |
25 | static {
26 | try (final InputStream inputStream =
27 | AgentProperties.class.getResourceAsStream(PROPERTIES_FILE)) {
28 | PROPERTIES.load(inputStream);
29 | } catch (NullPointerException e) {
30 | LOG.error(
31 | "Could not find property file with name "
32 | + PROPERTIES_FILE
33 | + ". Please make sure this property file is available in the resources folder.",
34 | e);
35 | throw new RuntimeException(e);
36 | } catch (IOException e) {
37 | LOG.error("Could not read properties from file", e);
38 | throw new RuntimeException(e);
39 | }
40 | }
41 |
42 | public static int getControllerPort() {
43 | return Integer.parseInt(getProperty(CONTROLLER_PORT));
44 | }
45 |
46 | public static int getGatewayPort() {
47 | return Integer.parseInt(getProperty(GATEWAY_PORT));
48 | }
49 |
50 | private static String getProperty(final String property) {
51 | return PROPERTIES.getProperty(property);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/db/InMemoryDbTransactionContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.db;
9 |
10 | import io.camunda.zeebe.db.TransactionContext;
11 | import io.camunda.zeebe.db.TransactionOperation;
12 | import io.camunda.zeebe.db.ZeebeDbInconsistentException;
13 | import io.camunda.zeebe.db.ZeebeDbTransaction;
14 | import java.util.TreeMap;
15 |
16 | class InMemoryDbTransactionContext implements TransactionContext {
17 | private final InMemoryDbTransaction transaction;
18 |
19 | public InMemoryDbTransactionContext(final TreeMap database) {
20 | transaction = new InMemoryDbTransaction(database);
21 | }
22 |
23 | @Override
24 | public void runInTransaction(final TransactionOperation operations) {
25 | try {
26 | if (transaction.isInCurrentTransaction()) {
27 | operations.run();
28 | } else {
29 | runInNewTransaction(operations);
30 | }
31 | } catch (final ZeebeDbInconsistentException e) {
32 | throw e;
33 | } catch (final Exception e) {
34 | throw new RuntimeException(
35 | "Unexpected error occurred during zeebe db transaction operation.", e);
36 | }
37 | }
38 |
39 | @Override
40 | public ZeebeDbTransaction getCurrentTransaction() {
41 | if (!transaction.isInCurrentTransaction()) {
42 | transaction.resetTransaction();
43 | }
44 | return transaction;
45 | }
46 |
47 | private void runInNewTransaction(final TransactionOperation operations) throws Exception {
48 | try {
49 | transaction.resetTransaction();
50 | operations.run();
51 | transaction.commit();
52 | } catch (final Exception e) {
53 | transaction.rollback();
54 | throw e;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/spring-test/embedded/src/main/java/io/camunda/zeebe/spring/test/ZeebeTestExecutionListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test;
17 |
18 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
19 | import io.camunda.zeebe.process.test.engine.EngineFactory;
20 | import java.lang.invoke.MethodHandles;
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 | import org.springframework.core.Ordered;
24 | import org.springframework.lang.NonNull;
25 | import org.springframework.test.context.TestContext;
26 | import org.springframework.test.context.TestExecutionListener;
27 |
28 | /** Test execution listener binding the Zeebe engine to current test context. */
29 | public class ZeebeTestExecutionListener extends AbstractZeebeTestExecutionListener
30 | implements TestExecutionListener, Ordered {
31 |
32 | private static final Logger LOGGER =
33 | LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
34 |
35 | private ZeebeTestEngine zeebeEngine;
36 |
37 | @Override
38 | public void beforeTestMethod(@NonNull final TestContext testContext) {
39 | LOGGER.info("Creating Zeebe in-memory engine...");
40 | zeebeEngine = EngineFactory.create();
41 | zeebeEngine.start();
42 | LOGGER.info("Successfully started Zeebe in-memory engine.");
43 |
44 | setupWithZeebeEngine(testContext, zeebeEngine);
45 | }
46 |
47 | @Override
48 | public void afterTestMethod(@NonNull final TestContext testContext) {
49 | cleanup(testContext, zeebeEngine);
50 | zeebeEngine.stop();
51 | }
52 |
53 | @Override
54 | public int getOrder() {
55 | return Ordered.HIGHEST_PRECEDENCE;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/db/Bytes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.db;
9 |
10 | import io.camunda.zeebe.db.DbValue;
11 | import java.util.Arrays;
12 | import org.agrona.ExpandableArrayBuffer;
13 |
14 | /** Wrapper around a {@code byte[]} to make it {@code Comparable} */
15 | final class Bytes implements Comparable {
16 |
17 | private final byte[] byteArray;
18 |
19 | private Bytes(final byte[] byteArray) {
20 | this.byteArray = byteArray;
21 | }
22 |
23 | @Override
24 | public int hashCode() {
25 | return Arrays.hashCode(byteArray);
26 | }
27 |
28 | @Override
29 | public boolean equals(final Object o) {
30 | if (this == o) {
31 | return true;
32 | }
33 | if (o == null || getClass() != o.getClass()) {
34 | return false;
35 | }
36 |
37 | final Bytes bytes = (Bytes) o;
38 |
39 | return Arrays.equals(byteArray, bytes.byteArray);
40 | }
41 |
42 | @Override
43 | public int compareTo(final Bytes other) {
44 | return Arrays.compareUnsigned(byteArray, other.byteArray);
45 | }
46 |
47 | byte[] toBytes() {
48 | return byteArray;
49 | }
50 |
51 | static Bytes fromByteArray(final byte[] array, final int length) {
52 | return new Bytes(Arrays.copyOfRange(array, 0, length));
53 | }
54 |
55 | static Bytes fromByteArray(final byte[] array) {
56 | return new Bytes(Arrays.copyOf(array, array.length));
57 | }
58 |
59 | static Bytes fromExpandableArrayBuffer(final ExpandableArrayBuffer buffer) {
60 | return fromByteArray(buffer.byteArray());
61 | }
62 |
63 | static Bytes fromDbValue(final DbValue value) {
64 | final ExpandableArrayBuffer valueBuffer = new ExpandableArrayBuffer(0);
65 | value.write(valueBuffer, 0);
66 | return Bytes.fromExpandableArrayBuffer(valueBuffer);
67 | }
68 |
69 | public static Bytes empty() {
70 | return new Bytes(new byte[0]);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/extension-testcontainer/src/main/java/io/camunda/zeebe/process/test/extension/testcontainer/EngineContainer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.extension.testcontainer;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.testcontainers.containers.GenericContainer;
21 | import org.testcontainers.containers.output.Slf4jLogConsumer;
22 | import org.testcontainers.containers.wait.strategy.Wait;
23 | import org.testcontainers.utility.DockerImageName;
24 |
25 | /** Singleton object which manages access to the testcontainer that's running the test engine */
26 | public final class EngineContainer extends GenericContainer {
27 |
28 | private static final Logger LOG = LoggerFactory.getLogger("io.camunda.zeebe-process-test");
29 |
30 | private static EngineContainer INSTANCE;
31 |
32 | private EngineContainer(final String imageName) {
33 | super(DockerImageName.parse(imageName));
34 | }
35 |
36 | /**
37 | * Gets the testcontainer if it exists, else creates it
38 | *
39 | * @return the testcontainer
40 | */
41 | public static EngineContainer getContainer() {
42 | if (INSTANCE == null) {
43 | createContainer();
44 | }
45 | return INSTANCE;
46 | }
47 |
48 | private static void createContainer() {
49 | INSTANCE =
50 | new EngineContainer(ContainerProperties.getDockerImageName())
51 | .withExposedPorts(
52 | ContainerProperties.getContainerPort(), ContainerProperties.getGatewayPort())
53 | .withLogConsumer(new Slf4jLogConsumer(LOG))
54 | .waitingFor(Wait.forLogMessage(".*ZeebeProcessTestEngine container has started.*", 1));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/java/io/camunda/zeebe/process/test/qa/abstracts/inspections/AbstractFormInspectionsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.camunda.zeebe.process.test.qa.abstracts.inspections;
18 |
19 | import static org.assertj.core.api.Assertions.assertThat;
20 |
21 | import io.camunda.zeebe.client.ZeebeClient;
22 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
23 | import io.camunda.zeebe.process.test.inspections.FormInspectionsUtility;
24 | import io.camunda.zeebe.process.test.qa.abstracts.util.Utilities;
25 | import io.camunda.zeebe.process.test.qa.abstracts.util.Utilities.FormPack;
26 | import io.camunda.zeebe.protocol.record.value.deployment.FormMetadataValue;
27 | import java.time.Duration;
28 | import java.util.Optional;
29 | import java.util.concurrent.TimeoutException;
30 | import org.junit.jupiter.api.Test;
31 |
32 | public abstract class AbstractFormInspectionsTest {
33 |
34 | private ZeebeClient client;
35 | private ZeebeTestEngine engine;
36 |
37 | @Test
38 | void shouldFindTheLatestVersion() throws InterruptedException, TimeoutException {
39 | // given
40 | Utilities.deployResource(client, FormPack.RESOURCE_NAME);
41 | Utilities.deployResources(client, FormPack.FORM_V2_RESOURCE_NAME);
42 | engine.waitForIdleState(Duration.ofSeconds(1));
43 |
44 | // when
45 | final Optional latestForm =
46 | FormInspectionsUtility.findLatestFormById(FormPack.FORM_ID);
47 |
48 | // then
49 | assertThat(latestForm.isPresent()).isTrue();
50 |
51 | final FormMetadataValue form = latestForm.get();
52 | assertThat(form.getFormId()).isEqualTo(FormPack.FORM_ID);
53 | assertThat(form.getVersion()).isEqualTo(2);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/CommandSender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine;
9 |
10 | import io.camunda.zeebe.protocol.impl.encoding.AuthInfo;
11 | import io.camunda.zeebe.protocol.impl.record.RecordMetadata;
12 | import io.camunda.zeebe.protocol.impl.record.UnifiedRecordValue;
13 | import io.camunda.zeebe.protocol.record.RecordType;
14 | import io.camunda.zeebe.protocol.record.ValueType;
15 | import io.camunda.zeebe.protocol.record.intent.Intent;
16 | import io.camunda.zeebe.stream.api.InterPartitionCommandSender;
17 |
18 | final class CommandSender implements InterPartitionCommandSender {
19 | private final CommandWriter writer;
20 |
21 | CommandSender(final CommandWriter writer) {
22 | this.writer = writer;
23 | }
24 |
25 | @Override
26 | public void sendCommand(
27 | final int receiverPartitionId,
28 | final ValueType valueType,
29 | final Intent intent,
30 | final UnifiedRecordValue command) {
31 | final RecordMetadata metadata =
32 | new RecordMetadata().recordType(RecordType.COMMAND).intent(intent).valueType(valueType);
33 | writer.writeCommandWithoutKey(command, metadata);
34 | }
35 |
36 | @Override
37 | public void sendCommand(
38 | final int receiverPartitionId,
39 | final ValueType valueType,
40 | final Intent intent,
41 | final Long recordKey,
42 | final UnifiedRecordValue command) {
43 | sendCommand(receiverPartitionId, valueType, intent, recordKey, command, null);
44 | }
45 |
46 | @Override
47 | public void sendCommand(
48 | final int receiverPartitionId,
49 | final ValueType valueType,
50 | final Intent intent,
51 | final Long recordKey,
52 | final UnifiedRecordValue command,
53 | final AuthInfo authInfo) {
54 | final RecordMetadata metadata =
55 | new RecordMetadata().recordType(RecordType.COMMAND).intent(intent).valueType(valueType);
56 | writer.writeCommandWithKey(recordKey, command, metadata);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/configuration/ZeebeTestDefaultConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test.configuration;
17 |
18 | import static com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT;
19 | import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
20 |
21 | import com.fasterxml.jackson.databind.ObjectMapper;
22 | import io.camunda.client.impl.CamundaObjectMapper;
23 | import io.camunda.zeebe.client.api.JsonMapper;
24 | import io.camunda.zeebe.client.impl.ZeebeObjectMapper;
25 | import io.micrometer.core.instrument.MeterRegistry;
26 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
27 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
28 | import org.springframework.context.annotation.Bean;
29 |
30 | /** Fallback values if certain beans are missing */
31 | public class ZeebeTestDefaultConfiguration {
32 |
33 | @Bean(name = "zeebeJsonMapper")
34 | @ConditionalOnMissingBean
35 | public JsonMapper jsonMapper(final ObjectMapper objectMapper) {
36 | return new ZeebeObjectMapper(objectMapper);
37 | }
38 |
39 | @Bean(name = "camundaJsonMapper")
40 | @ConditionalOnMissingBean
41 | public io.camunda.client.api.JsonMapper camundaJsonMapper(final ObjectMapper objectMapper) {
42 | return new CamundaObjectMapper(objectMapper);
43 | }
44 |
45 | @Bean
46 | @ConditionalOnMissingBean
47 | public ObjectMapper objectMapper() {
48 | return new ObjectMapper()
49 | .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
50 | .configure(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);
51 | }
52 |
53 | @Bean
54 | @ConditionalOnMissingBean
55 | public MeterRegistry meterRegistry() {
56 | return new SimpleMeterRegistry();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/extension/src/main/java/io/camunda/zeebe/process/test/extension/ZeebeProcessTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.extension;
9 |
10 | import java.lang.annotation.ElementType;
11 | import java.lang.annotation.Inherited;
12 | import java.lang.annotation.Retention;
13 | import java.lang.annotation.RetentionPolicy;
14 | import java.lang.annotation.Target;
15 | import org.junit.jupiter.api.extension.ExtendWith;
16 |
17 | /**
18 | * This annotation can be used to test BPMN processes. It will run an in memory Zeebe engine. To use
19 | * this annotation Java 21 or higher is required.
20 | *
21 | * Annotating test classes with this annotation will do a couple of things:
22 | *
23 | *
24 | * - It will manage the lifecycle of the embedded test engine
25 | *
- It will create a client which can be used to interact with the engine.
26 | *
- It will (optionally) inject 3 fields in your test class:
27 | *
28 | * - ZeebeTestEngine - This is the engine that will run your process. It will provide some
29 | * basic functionality to help you write your tests, such as waiting for an idle state
30 | * and increasing the time.
31 | *
- ZeebeClient - This is the client that allows you to send commands to the engine, such
32 | * as starting a process instance. The interface of this client is identical to the
33 | * interface you use to connect to a real Zeebe engine.
34 | *
- RecordStream - This gives you access to all the records that are processed by the
35 | * engine. Assertions use the records for verifying expectations. This grants you the
36 | * freedom to create your own assertions.
37 | *
38 | *
39 | *
40 | * Lifecycle:
41 | *
42 | *
43 | * - Before each test create a new Zeebe test engine
44 | *
- Run the test
45 | *
- After each test stop the Zeebe test engine
46 | *
47 | *
48 | * @since Java 21
49 | */
50 | @Target(ElementType.TYPE)
51 | @Retention(RetentionPolicy.RUNTIME)
52 | @Inherited
53 | @ExtendWith(ZeebeProcessTestExtension.class)
54 | public @interface ZeebeProcessTest {}
55 |
--------------------------------------------------------------------------------
/engine/src/test/java/io/camunda/zeebe/process/test/engine/GrpcToLogStreamGatewayTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 |
9 | package io.camunda.zeebe.process.test.engine;
10 |
11 | import static org.assertj.core.api.Assertions.assertThat;
12 |
13 | import io.camunda.zeebe.gateway.protocol.GatewayGrpc.GatewayImplBase;
14 | import java.lang.reflect.Method;
15 | import java.util.Arrays;
16 | import java.util.List;
17 | import java.util.Optional;
18 | import java.util.stream.Stream;
19 | import org.junit.jupiter.params.ParameterizedTest;
20 | import org.junit.jupiter.params.provider.Arguments;
21 | import org.junit.jupiter.params.provider.MethodSource;
22 |
23 | class GrpcToLogStreamGatewayTest {
24 |
25 | static final List UNSUPPORTED_METHODS = List.of("evaluateConditional");
26 |
27 | static final List IGNORED_METHODS =
28 | List.of(
29 | "bindService",
30 | "equals",
31 | "getClass",
32 | "hashCode",
33 | "notify",
34 | "notifyAll",
35 | "toString",
36 | "wait");
37 |
38 | @ParameterizedTest(name = "{0}")
39 | @MethodSource("provideMethods")
40 | void testImplementsGatewayEndpoint(final String methodName) {
41 | final Optional optionalMethod =
42 | Arrays.stream(GrpcToLogStreamGateway.class.getDeclaredMethods())
43 | .filter(m -> m.getName().equals(methodName))
44 | .findAny();
45 |
46 | assertThat(optionalMethod)
47 | .describedAs(
48 | """
49 | Expected method %s to be implemented. \
50 | When this test fails, it's likely a new RPC that ZPT should support. \
51 | Please check whether it should be supported by ZPT. \
52 | If it should be suported, add a test case to EngineClientTest.java""",
53 | methodName)
54 | .isPresent();
55 | }
56 |
57 | static Stream provideMethods() {
58 | return Arrays.stream(GatewayImplBase.class.getMethods())
59 | .map(Method::getName)
60 | .filter(name -> !IGNORED_METHODS.contains(name))
61 | .filter(name -> !UNSUPPORTED_METHODS.contains(name))
62 | .map(Arguments::of);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/resources/call-activity.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_1oizqpb
6 |
7 |
8 |
9 |
10 |
11 |
12 | Flow_1oizqpb
13 | Flow_0ytr5rb
14 |
15 |
16 | Flow_0ytr5rb
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/spring-test/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.camunda
7 | zeebe-process-test-root
8 | 8.9.0-SNAPSHOT
9 | ../pom.xml
10 |
11 |
12 | spring-boot-starter-camunda-test-pom
13 | pom
14 |
15 | Spring Boot Starter Camunda Test POM
16 |
17 |
18 | common
19 | embedded
20 | testcontainer
21 |
22 |
23 |
24 | 5.0.0
25 | 17
26 |
27 |
28 |
29 |
30 |
31 | org.apache.maven.plugins
32 | maven-dependency-plugin
33 |
34 | true
35 |
36 |
37 | org.slf4j:slf4j-simple
38 |
39 |
40 |
41 |
42 | com.mycila
43 | license-maven-plugin
44 | ${plugin.version.license}
45 |
46 | com/mycila/maven/plugin/license/templates/APACHE-2.txt
47 |
48 | camunda services GmbH
49 | info@camunda.com
50 |
51 |
52 | **/*.java
53 |
54 |
55 |
56 | SLASHSTAR_STYLE
57 |
58 |
59 |
60 |
61 | add-license
62 |
63 | format
64 |
65 | process-sources
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/java/io/camunda/zeebe/process/test/qa/abstracts/multithread/AbstractWorkerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.qa.abstracts.multithread;
17 |
18 | import static io.camunda.zeebe.process.test.assertions.BpmnAssert.assertThat;
19 |
20 | import io.camunda.zeebe.client.ZeebeClient;
21 | import io.camunda.zeebe.client.api.response.ProcessInstanceResult;
22 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
23 | import io.camunda.zeebe.process.test.qa.abstracts.util.Utilities;
24 | import io.camunda.zeebe.process.test.qa.abstracts.util.Utilities.ProcessPackLoopingServiceTask;
25 | import java.util.Collections;
26 | import java.util.Map;
27 | import java.util.concurrent.TimeoutException;
28 | import org.junit.jupiter.api.Test;
29 |
30 | public abstract class AbstractWorkerTest {
31 |
32 | @Test
33 | void testJobsCanBeProcessedAsynchronouslyByWorker()
34 | throws InterruptedException, TimeoutException {
35 | // given
36 | getClient()
37 | .newWorker()
38 | .jobType(ProcessPackLoopingServiceTask.JOB_TYPE)
39 | .handler((client, job) -> client.newCompleteCommand(job.getKey()).send())
40 | .open();
41 |
42 | Utilities.deployResource(getClient(), ProcessPackLoopingServiceTask.RESOURCE_NAME);
43 | final Map variables =
44 | Collections.singletonMap(ProcessPackLoopingServiceTask.TOTAL_LOOPS, 3);
45 |
46 | // when
47 | final ProcessInstanceResult instanceEvent =
48 | Utilities.startProcessInstanceWithResult(
49 | getEngine(), getClient(), ProcessPackLoopingServiceTask.PROCESS_ID, variables);
50 |
51 | // then
52 | assertThat(instanceEvent).isStarted();
53 | assertThat(instanceEvent)
54 | .hasPassedElement(ProcessPackLoopingServiceTask.ELEMENT_ID, 3)
55 | .isCompleted();
56 | }
57 |
58 | public abstract ZeebeClient getClient();
59 |
60 | public abstract ZeebeTestEngine getEngine();
61 | }
62 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/ProcessEventRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.ValueType;
20 | import io.camunda.zeebe.protocol.record.intent.ProcessEventIntent;
21 | import io.camunda.zeebe.protocol.record.value.ProcessEventRecordValue;
22 | import java.util.stream.Stream;
23 | import java.util.stream.StreamSupport;
24 |
25 | public class ProcessEventRecordStreamFilter {
26 |
27 | private final Stream> stream;
28 |
29 | public ProcessEventRecordStreamFilter(final Iterable> records) {
30 | stream =
31 | StreamSupport.stream(records.spliterator(), true)
32 | .filter(record -> record.getValueType() == ValueType.PROCESS_EVENT)
33 | .map(record -> (Record) record);
34 | }
35 |
36 | public ProcessEventRecordStreamFilter(final Stream> stream) {
37 | this.stream = stream;
38 | }
39 |
40 | public ProcessEventRecordStreamFilter withIntent(final ProcessEventIntent intent) {
41 | return new ProcessEventRecordStreamFilter(
42 | stream.filter(record -> record.getIntent() == intent));
43 | }
44 |
45 | public ProcessEventRecordStreamFilter withTargetElementId(final String targetElementId) {
46 | return new ProcessEventRecordStreamFilter(
47 | stream.filter(record -> record.getValue().getTargetElementId().equals(targetElementId)));
48 | }
49 |
50 | public ProcessEventRecordStreamFilter withProcessDefinitionKey(final long processDefinitionKey) {
51 | return new ProcessEventRecordStreamFilter(
52 | stream.filter(
53 | record -> record.getValue().getProcessDefinitionKey() == processDefinitionKey));
54 | }
55 |
56 | public Stream> stream() {
57 | return stream;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/extension-testcontainer/src/main/java/io/camunda/zeebe/process/test/extension/testcontainer/ContainerProperties.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.extension.testcontainer;
17 |
18 | import java.io.FileNotFoundException;
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.util.Properties;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | public final class ContainerProperties {
26 |
27 | private static final Logger LOG = LoggerFactory.getLogger("io.camunda.zeebe-process-test");
28 |
29 | private static final String PROPERTIES_FILE = "/config.properties";
30 | public static final String IMAGE_NAME = "container.image.name";
31 | public static final String IMAGE_TAG = "container.image.tag";
32 | public static final String GATEWAY_PORT = "container.gateway.port";
33 | public static final String PORT = "container.port";
34 | private static final Properties PROPERTIES = new Properties();
35 |
36 | static {
37 | try (final InputStream inputStream =
38 | ContainerProperties.class.getResourceAsStream(PROPERTIES_FILE)) {
39 | PROPERTIES.load(inputStream);
40 | } catch (FileNotFoundException e) {
41 | LOG.error("Could not find property file with name " + PROPERTIES_FILE, e);
42 | throw new RuntimeException(e);
43 | } catch (IOException e) {
44 | LOG.error("Could not read properties from file", e);
45 | throw new RuntimeException(e);
46 | }
47 | }
48 |
49 | public static String getDockerImageName() {
50 | return getProperty(IMAGE_NAME) + ":" + getProperty(IMAGE_TAG);
51 | }
52 |
53 | public static int getContainerPort() {
54 | return Integer.parseInt(getProperty(PORT));
55 | }
56 |
57 | public static int getGatewayPort() {
58 | return Integer.parseInt(getProperty(GATEWAY_PORT));
59 | }
60 |
61 | private static String getProperty(final String property) {
62 | return PROPERTIES.getProperty(property);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/spring-test/common/src/main/java/io/camunda/zeebe/spring/test/proxy/TestProxyConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test.proxy;
17 |
18 | import io.camunda.client.CamundaClient;
19 | import io.camunda.zeebe.client.ZeebeClient;
20 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
21 | import java.lang.invoke.MethodHandles;
22 | import java.lang.reflect.Proxy;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import org.springframework.context.annotation.Bean;
26 | import org.springframework.context.annotation.Primary;
27 |
28 | public class TestProxyConfiguration {
29 | private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
30 |
31 | @Bean
32 | public ZeebeClientProxy zeebeClientProxy() {
33 | return new ZeebeClientProxy();
34 | }
35 |
36 | @Bean
37 | @Primary
38 | public ZeebeClient proxiedZeebeClient(final ZeebeClientProxy zeebeClientProxy) {
39 | return (ZeebeClient)
40 | Proxy.newProxyInstance(
41 | getClass().getClassLoader(), new Class[] {ZeebeClient.class}, zeebeClientProxy);
42 | }
43 |
44 | @Bean
45 | public ZeebeTestEngineProxy zeebeTestEngineProxy() {
46 | return new ZeebeTestEngineProxy();
47 | }
48 |
49 | @Bean
50 | public ZeebeTestEngine proxiedZeebeTestEngine(final ZeebeTestEngineProxy zeebeTestEngineProxy) {
51 | return (ZeebeTestEngine)
52 | Proxy.newProxyInstance(
53 | getClass().getClassLoader(), new Class[] {ZeebeTestEngine.class}, zeebeTestEngineProxy);
54 | }
55 |
56 | @Bean
57 | public CamundaClientProxy camundaClientProxy() {
58 | return new CamundaClientProxy();
59 | }
60 |
61 | @Bean
62 | @Primary
63 | public CamundaClient proxiedCamundaClient(final CamundaClientProxy camundaClientProxy) {
64 | return (CamundaClient)
65 | Proxy.newProxyInstance(
66 | getClass().getClassLoader(), new Class[] {CamundaClient.class}, camundaClientProxy);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/MessageStartEventSubscriptionStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.RejectionType;
20 | import io.camunda.zeebe.protocol.record.intent.MessageStartEventSubscriptionIntent;
21 | import io.camunda.zeebe.protocol.record.value.MessageStartEventSubscriptionRecordValue;
22 | import java.util.stream.Stream;
23 | import java.util.stream.StreamSupport;
24 |
25 | public class MessageStartEventSubscriptionStreamFilter {
26 |
27 | private final Stream> stream;
28 |
29 | public MessageStartEventSubscriptionStreamFilter(
30 | final Iterable> records) {
31 | stream = StreamSupport.stream(records.spliterator(), false);
32 | }
33 |
34 | public MessageStartEventSubscriptionStreamFilter(
35 | final Stream> stream) {
36 | this.stream = stream;
37 | }
38 |
39 | public MessageStartEventSubscriptionStreamFilter withMessageKey(final long messageKey) {
40 | return new MessageStartEventSubscriptionStreamFilter(
41 | stream.filter(record -> record.getValue().getMessageKey() == messageKey));
42 | }
43 |
44 | public MessageStartEventSubscriptionStreamFilter withRejectionType(
45 | final RejectionType rejectionType) {
46 | return new MessageStartEventSubscriptionStreamFilter(
47 | stream.filter(record -> record.getRejectionType() == rejectionType));
48 | }
49 |
50 | public MessageStartEventSubscriptionStreamFilter withIntent(
51 | final MessageStartEventSubscriptionIntent intent) {
52 | return new MessageStartEventSubscriptionStreamFilter(
53 | stream.filter(record -> record.getIntent() == intent));
54 | }
55 |
56 | public Stream> stream() {
57 | return stream;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/java/io/camunda/zeebe/process/test/qa/abstracts/mapper/AbstractMapperSerializationDeserializationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.camunda.zeebe.process.test.qa.abstracts.mapper;
18 |
19 | import static org.junit.jupiter.api.Assertions.assertEquals;
20 |
21 | import com.fasterxml.jackson.databind.ObjectMapper;
22 | import com.fasterxml.jackson.databind.SerializationFeature;
23 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
24 | import io.camunda.zeebe.client.ZeebeClient;
25 | import io.camunda.zeebe.client.api.JsonMapper;
26 | import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
27 | import java.time.LocalDateTime;
28 | import org.junit.jupiter.api.Test;
29 |
30 | public abstract class AbstractMapperSerializationDeserializationTest {
31 | protected ZeebeClient client;
32 | protected ZeebeTestEngine engine;
33 | protected ObjectMapper mapper = configureObjectMapper();
34 |
35 | @Test
36 | void shouldSerialize() {
37 | final JsonMapper jsonMapper = client.getConfiguration().getJsonMapper();
38 | final LocalDateTime localDateTime = LocalDateTime.of(2023, 7, 31, 12, 0, 0);
39 | final String expectedJson = "\"2023-07-31T12:00:00\"";
40 | final String actualJson = jsonMapper.toJson(localDateTime);
41 | assertEquals(expectedJson, actualJson);
42 | }
43 |
44 | @Test
45 | void shouldDeserialize() {
46 | final JsonMapper jsonMapper = client.getConfiguration().getJsonMapper();
47 | final String json = "\"2023-07-31T12:00:00\"";
48 | final LocalDateTime expectedLocalDateTime = LocalDateTime.of(2023, 7, 31, 12, 0, 0);
49 | final LocalDateTime actualLocalDateTime = jsonMapper.fromJson(json, LocalDateTime.class);
50 | assertEquals(expectedLocalDateTime, actualLocalDateTime);
51 | }
52 |
53 | private ObjectMapper configureObjectMapper() {
54 | final ObjectMapper objectMapper = new ObjectMapper();
55 | objectMapper.registerModule(new JavaTimeModule());
56 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
57 | return objectMapper;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/ProcessRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.camunda.zeebe.process.test.filters;
18 |
19 | import io.camunda.zeebe.client.api.response.DeploymentEvent;
20 | import io.camunda.zeebe.protocol.record.Record;
21 | import io.camunda.zeebe.protocol.record.intent.ProcessIntent;
22 | import io.camunda.zeebe.protocol.record.value.deployment.Process;
23 | import java.util.Objects;
24 | import java.util.stream.Stream;
25 | import java.util.stream.StreamSupport;
26 |
27 | public class ProcessRecordStreamFilter {
28 | private final Stream> stream;
29 |
30 | public ProcessRecordStreamFilter(final Iterable> records) {
31 | stream = StreamSupport.stream(records.spliterator(), false);
32 | }
33 |
34 | public ProcessRecordStreamFilter(final Stream> stream) {
35 | this.stream = stream;
36 | }
37 |
38 | public Stream getProcessDefinitions() {
39 |
40 | return stream.map(Record::getValue);
41 | }
42 |
43 | public ProcessRecordStreamFilter withBpmnProcessId(final String bpmnProcessId) {
44 | return new ProcessRecordStreamFilter(
45 | stream.filter(
46 | record -> Objects.equals(record.getValue().getBpmnProcessId(), bpmnProcessId)));
47 | }
48 |
49 | public ProcessRecordStreamFilter withDeployment(final DeploymentEvent deployment) {
50 | return new ProcessRecordStreamFilter(
51 | stream.filter(
52 | record ->
53 | deployment.getProcesses().stream()
54 | .anyMatch(
55 | process ->
56 | process.getProcessDefinitionKey()
57 | == record.getValue().getProcessDefinitionKey())));
58 | }
59 |
60 | public ProcessRecordStreamFilter withIntent(final ProcessIntent intent) {
61 | return new ProcessRecordStreamFilter(
62 | stream.filter(record -> record.getIntent().equals(intent)));
63 | }
64 |
65 | public Stream> stream() {
66 | return stream;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/MessageRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.RejectionType;
20 | import io.camunda.zeebe.protocol.record.intent.MessageIntent;
21 | import io.camunda.zeebe.protocol.record.value.MessageRecordValue;
22 | import java.util.stream.Stream;
23 | import java.util.stream.StreamSupport;
24 |
25 | public class MessageRecordStreamFilter {
26 |
27 | private final Stream> stream;
28 |
29 | public MessageRecordStreamFilter(final Iterable> messageRecords) {
30 | stream = StreamSupport.stream(messageRecords.spliterator(), false);
31 | }
32 |
33 | public MessageRecordStreamFilter(final Stream> stream) {
34 | this.stream = stream;
35 | }
36 |
37 | public MessageRecordStreamFilter withKey(final long key) {
38 | return new MessageRecordStreamFilter(stream.filter(record -> record.getKey() == key));
39 | }
40 |
41 | public MessageRecordStreamFilter withMessageName(final String messageName) {
42 | return new MessageRecordStreamFilter(
43 | stream.filter(record -> record.getValue().getName().equals(messageName)));
44 | }
45 |
46 | public MessageRecordStreamFilter withCorrelationKey(final String correlationKey) {
47 | return new MessageRecordStreamFilter(
48 | stream.filter(record -> record.getValue().getCorrelationKey().equals(correlationKey)));
49 | }
50 |
51 | public MessageRecordStreamFilter withIntent(final MessageIntent intent) {
52 | return new MessageRecordStreamFilter(stream.filter(record -> record.getIntent() == intent));
53 | }
54 |
55 | public MessageRecordStreamFilter withRejectionType(final RejectionType rejectionType) {
56 | return new MessageRecordStreamFilter(
57 | stream.filter(record -> record.getRejectionType() == rejectionType));
58 | }
59 |
60 | public Stream> stream() {
61 | return stream;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/IncidentRecordStreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | import io.camunda.zeebe.protocol.record.Record;
19 | import io.camunda.zeebe.protocol.record.RejectionType;
20 | import io.camunda.zeebe.protocol.record.intent.IncidentIntent;
21 | import io.camunda.zeebe.protocol.record.value.IncidentRecordValue;
22 | import java.util.stream.Stream;
23 | import java.util.stream.StreamSupport;
24 |
25 | public class IncidentRecordStreamFilter {
26 | private final Stream> stream;
27 |
28 | public IncidentRecordStreamFilter(final Iterable> records) {
29 | stream = StreamSupport.stream(records.spliterator(), false);
30 | }
31 |
32 | public IncidentRecordStreamFilter(final Stream> stream) {
33 | this.stream = stream;
34 | }
35 |
36 | public IncidentRecordStreamFilter withIncidentKey(final long incidentKey) {
37 | return new IncidentRecordStreamFilter(stream.filter(record -> record.getKey() == incidentKey));
38 | }
39 |
40 | public IncidentRecordStreamFilter withRejectionType(final RejectionType rejectionType) {
41 | return new IncidentRecordStreamFilter(
42 | stream.filter(record -> record.getRejectionType() == rejectionType));
43 | }
44 |
45 | public IncidentRecordStreamFilter withProcessInstanceKey(final long processInstanceKey) {
46 | return new IncidentRecordStreamFilter(
47 | stream.filter(record -> record.getValue().getProcessInstanceKey() == processInstanceKey));
48 | }
49 |
50 | public IncidentRecordStreamFilter withJobKey(final long jobKey) {
51 | return new IncidentRecordStreamFilter(
52 | stream.filter(record -> record.getValue().getJobKey() == jobKey));
53 | }
54 |
55 | public IncidentRecordStreamFilter withIntent(final IncidentIntent intent) {
56 | return new IncidentRecordStreamFilter(stream.filter(record -> record.getIntent() == intent));
57 | }
58 |
59 | public Stream> stream() {
60 | return stream;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/db/InMemoryDbColumnFamilyIterationContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.db;
9 |
10 | import io.camunda.zeebe.db.DbKey;
11 | import io.camunda.zeebe.db.impl.ZeebeDbConstants;
12 | import java.nio.ByteBuffer;
13 | import java.util.ArrayDeque;
14 | import java.util.List;
15 | import java.util.Queue;
16 | import java.util.function.Consumer;
17 | import org.agrona.ExpandableArrayBuffer;
18 | import org.agrona.concurrent.UnsafeBuffer;
19 |
20 | /**
21 | * This class allows iterating over a subset of keys in the database. The subset is identified by a
22 | * common prefix for all keys in that subset. It also implements a recursion guard by checking that
23 | * iterations can only be nested up to a certain maximum depth.
24 | */
25 | final class InMemoryDbColumnFamilyIterationContext {
26 |
27 | private final long columnFamilyPrefix;
28 |
29 | private final Queue prefixKeyBuffers =
30 | new ArrayDeque<>(List.of(new ExpandableArrayBuffer(), new ExpandableArrayBuffer()));
31 |
32 | InMemoryDbColumnFamilyIterationContext(final long columnFamilyPrefix) {
33 | this.columnFamilyPrefix = columnFamilyPrefix;
34 | }
35 |
36 | void withPrefixKey(final DbKey prefix, final Consumer prefixKeyConsumer) {
37 | if (prefixKeyBuffers.peek() == null) {
38 | throw new IllegalStateException(
39 | "Currently nested prefix iterations of this depth are not supported! This will cause unexpected behavior.");
40 | }
41 |
42 | final ExpandableArrayBuffer prefixKeyBuffer = prefixKeyBuffers.remove();
43 | try {
44 | prefixKeyBuffer.putLong(0, columnFamilyPrefix, ZeebeDbConstants.ZB_DB_BYTE_ORDER);
45 | prefix.write(prefixKeyBuffer, Long.BYTES);
46 | final int prefixLength = Long.BYTES + prefix.getLength();
47 | prefixKeyConsumer.accept(Bytes.fromByteArray(prefixKeyBuffer.byteArray(), prefixLength));
48 | } finally {
49 | prefixKeyBuffers.add(prefixKeyBuffer);
50 | }
51 | }
52 |
53 | public ByteBuffer keyWithColumnFamily(final DbKey key) {
54 | final var bytes = ByteBuffer.allocate(Long.BYTES + key.getLength());
55 | final var buffer = new UnsafeBuffer(bytes);
56 |
57 | buffer.putLong(0, columnFamilyPrefix, ZeebeDbConstants.ZB_DB_BYTE_ORDER);
58 | key.write(buffer, Long.BYTES);
59 | return bytes;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/filters/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.camunda
7 | zeebe-process-test-root
8 | 8.9.0-SNAPSHOT
9 | ../pom.xml
10 |
11 |
12 | zeebe-process-test-filters
13 | 8.9.0-SNAPSHOT
14 |
15 | Zeebe Process Test Filters
16 |
17 | Filters for filtering through a list of Records.
18 |
19 |
20 | 8
21 |
22 |
23 |
24 |
25 | io.camunda
26 | zeebe-client-java
27 |
28 |
29 |
30 | io.camunda
31 | zeebe-process-test-api
32 |
33 |
34 |
35 | io.camunda
36 | zeebe-protocol
37 |
38 |
39 |
40 | org.slf4j
41 | slf4j-api
42 |
43 |
44 |
45 |
46 | org.junit.jupiter
47 | junit-jupiter-api
48 | test
49 |
50 |
51 |
52 | org.assertj
53 | assertj-core
54 | test
55 |
56 |
57 |
58 | org.slf4j
59 | slf4j-simple
60 | test
61 |
62 |
63 |
64 | org.junit.jupiter
65 | junit-jupiter-params
66 | test
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-dependency-plugin
75 |
76 | true
77 |
78 |
79 | org.slf4j:slf4j-simple
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/qa/abstracts/src/main/resources/message-event.bpmn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flow_1yhq8uc
6 |
7 |
8 |
9 | Flow_0mpo91e
10 |
11 |
12 |
13 | Flow_1yhq8uc
14 | Flow_0mpo91e
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/db/InMemoryDb.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine.db;
9 |
10 | import io.camunda.zeebe.db.*;
11 | import io.camunda.zeebe.db.impl.DbNil;
12 | import io.camunda.zeebe.protocol.EnumValue;
13 | import io.camunda.zeebe.protocol.ScopedColumnFamily;
14 | import io.micrometer.core.instrument.MeterRegistry;
15 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
16 | import java.io.File;
17 | import java.util.Optional;
18 | import java.util.TreeMap;
19 |
20 | /**
21 | * In memory implementation of {@code ZeebeDb}
22 | *
23 | * This implementation does not support
24 | *
25 | *
26 | * - concurrent access
27 | *
- locking between transactions
28 | *
- Taking snapshots
29 | *
30 | *
31 | * This implementation is backed by a tree map.
32 | *
33 | * @param
34 | */
35 | final class InMemoryDb<
36 | ColumnFamilyType extends Enum extends EnumValue> & EnumValue & ScopedColumnFamily>
37 | implements ZeebeDb {
38 |
39 | private final TreeMap database = new TreeMap<>();
40 |
41 | @Override
42 | public
43 | ColumnFamily createColumnFamily(
44 | final ColumnFamilyType columnFamily,
45 | final TransactionContext context,
46 | final KeyType keyInstance,
47 | final ValueType valueInstance) {
48 | return new InMemoryDbColumnFamily<>(columnFamily, context, keyInstance, valueInstance);
49 | }
50 |
51 | @Override
52 | public void createSnapshot(final File snapshotDir) {
53 | throw new IllegalStateException("No snapshots supported");
54 | }
55 |
56 | @Override
57 | public Optional getProperty(final String propertyName) {
58 | return Optional.empty();
59 | }
60 |
61 | @Override
62 | public TransactionContext createContext() {
63 | return new InMemoryDbTransactionContext(database);
64 | }
65 |
66 | @Override
67 | public boolean isEmpty(final ColumnFamilyType column, final TransactionContext context) {
68 | return createColumnFamily(column, context, DbNullKey.INSTANCE, DbNil.INSTANCE).isEmpty();
69 | }
70 |
71 | @Override
72 | public MeterRegistry getMeterRegistry() {
73 | return new SimpleMeterRegistry();
74 | }
75 |
76 | @Override
77 | public void close() {
78 | database.clear();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/qa/embedded/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 | 4.0.0
19 |
20 | io.camunda
21 | zeebe-process-test-qa
22 | 8.9.0-SNAPSHOT
23 |
24 |
25 | zeebe-process-test-qa-embedded
26 |
27 | Zeebe Process Test QA Embedded
28 |
29 |
30 | 21
31 |
32 |
33 |
34 |
35 | io.camunda
36 | zeebe-process-test-extension
37 | test
38 |
39 |
40 |
41 | io.camunda
42 | zeebe-process-test-qa-abstracts
43 | test
44 |
45 |
46 |
47 | io.github.classgraph
48 | classgraph
49 | test
50 |
51 |
52 |
53 | org.junit.jupiter
54 | junit-jupiter-params
55 | test
56 |
57 |
58 |
59 | io.camunda
60 | zeebe-process-test-filters
61 | test
62 |
63 |
64 |
65 | io.camunda
66 | zeebe-client-java
67 | test
68 |
69 |
70 |
71 | io.camunda
72 | zeebe-process-test-api
73 | test
74 |
75 |
76 |
77 | org.assertj
78 | assertj-core
79 | test
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/spring-test/testcontainer/src/main/java/io/camunda/zeebe/spring/test/ZeebeTestExecutionListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.spring.test;
17 |
18 | import io.camunda.zeebe.process.test.extension.testcontainer.ContainerProperties;
19 | import io.camunda.zeebe.process.test.extension.testcontainer.ContainerizedEngine;
20 | import io.camunda.zeebe.process.test.extension.testcontainer.EngineContainer;
21 | import java.lang.invoke.MethodHandles;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 | import org.springframework.core.Ordered;
25 | import org.springframework.lang.NonNull;
26 | import org.springframework.test.context.TestContext;
27 | import org.springframework.test.context.TestExecutionListener;
28 |
29 | /** Test execution listener binding the Zeebe engine to current test context. */
30 | public class ZeebeTestExecutionListener extends AbstractZeebeTestExecutionListener
31 | implements TestExecutionListener, Ordered {
32 |
33 | private static final Logger LOGGER =
34 | LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
35 |
36 | private ContainerizedEngine containerizedEngine;
37 |
38 | public void beforeTestClass(@NonNull TestContext testContext) {
39 | LOGGER.info("Creating Zeebe Testcontainer...");
40 |
41 | final EngineContainer container = EngineContainer.getContainer();
42 | container.start();
43 | containerizedEngine =
44 | new ContainerizedEngine(
45 | container.getHost(),
46 | container.getMappedPort(ContainerProperties.getContainerPort()),
47 | container.getMappedPort(ContainerProperties.getGatewayPort()));
48 |
49 | LOGGER.info("...finished creating Zeebe Testcontainer");
50 | }
51 |
52 | public void beforeTestMethod(@NonNull TestContext testContext) {
53 | LOGGER.info("Create Zeebe Testcontainer engine");
54 | containerizedEngine.start();
55 | setupWithZeebeEngine(testContext, containerizedEngine);
56 | }
57 |
58 | public void afterTestMethod(@NonNull TestContext testContext) {
59 | cleanup(testContext, containerizedEngine);
60 | containerizedEngine.reset();
61 | }
62 |
63 | @Override
64 | public int getOrder() {
65 | return Integer.MAX_VALUE;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/qa/testcontainers/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | io.camunda
6 | zeebe-process-test-qa
7 | 8.9.0-SNAPSHOT
8 |
9 |
10 | zeebe-process-test-qa-testcontainers
11 |
12 | Zeebe Process Test QA Testcontainers
13 |
14 |
15 |
16 | 7.19.0
17 | 8
18 |
19 |
20 |
21 |
22 |
23 | org.camunda.bpm.model
24 | camunda-dmn-model
25 | ${dependency.camundamodel.version}
26 |
27 |
28 |
29 | org.camunda.bpm.model
30 | camunda-xml-model
31 | ${dependency.camundamodel.version}
32 |
33 |
34 |
35 |
36 |
37 |
38 | io.camunda
39 | zeebe-process-test-extension-testcontainer
40 | test
41 |
42 |
43 |
44 | io.camunda
45 | zeebe-process-test-qa-abstracts
46 | test
47 |
48 |
49 |
50 | io.github.classgraph
51 | classgraph
52 | test
53 |
54 |
55 |
56 | org.junit.jupiter
57 | junit-jupiter-params
58 | test
59 |
60 |
61 |
62 | io.camunda
63 | zeebe-process-test-filters
64 | test
65 |
66 |
67 |
68 | io.camunda
69 | zeebe-client-java
70 | test
71 |
72 |
73 |
74 | io.camunda
75 | zeebe-process-test-api
76 | test
77 |
78 |
79 |
80 | org.assertj
81 | assertj-core
82 | test
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/engine/src/main/java/io/camunda/zeebe/process/test/engine/RecordStreamSourceImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
3 | * one or more contributor license agreements. See the NOTICE file distributed
4 | * with this work for additional information regarding copyright ownership.
5 | * Licensed under the Zeebe Community License 1.1. You may not use this file
6 | * except in compliance with the Zeebe Community License 1.1.
7 | */
8 | package io.camunda.zeebe.process.test.engine;
9 |
10 | import io.camunda.zeebe.logstreams.log.LogStreamReader;
11 | import io.camunda.zeebe.logstreams.log.LoggedEvent;
12 | import io.camunda.zeebe.process.test.api.RecordStreamSource;
13 | import io.camunda.zeebe.protocol.impl.record.CopiedRecord;
14 | import io.camunda.zeebe.protocol.impl.record.RecordMetadata;
15 | import io.camunda.zeebe.protocol.impl.record.UnifiedRecordValue;
16 | import io.camunda.zeebe.protocol.record.Record;
17 | import java.util.ArrayList;
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | class RecordStreamSourceImpl implements RecordStreamSource {
22 |
23 | private final LogStreamReader logStreamReader;
24 | private final int partitionId;
25 | private final List> records = new ArrayList<>();
26 | private volatile long lastPosition = -1L;
27 |
28 | public RecordStreamSourceImpl(final LogStreamReader logStreamReader, final int partitionId) {
29 | this.logStreamReader = logStreamReader;
30 | this.partitionId = partitionId;
31 | }
32 |
33 | @Override
34 | public Iterable> getRecords() {
35 | updateWithNewRecords();
36 | return Collections.unmodifiableList(records);
37 | }
38 |
39 | private void updateWithNewRecords() {
40 | synchronized (logStreamReader) {
41 | if (lastPosition < 0) {
42 | logStreamReader.seekToFirstEvent();
43 | } else {
44 | logStreamReader.seekToNextEvent(lastPosition);
45 | }
46 |
47 | while (logStreamReader.hasNext()) {
48 | final LoggedEvent event = logStreamReader.next();
49 | final CopiedRecord record = mapToRecord(event);
50 | records.add(record);
51 | lastPosition = event.getPosition();
52 | }
53 | }
54 | }
55 |
56 | private CopiedRecord mapToRecord(final LoggedEvent event) {
57 | final RecordMetadata metadata = new RecordMetadata();
58 | event.readMetadata(metadata);
59 |
60 | final UnifiedRecordValue value;
61 | try {
62 | value = UnifiedRecordValue.allRecordsMap().get(metadata.getValueType());
63 | } catch (final Exception e) {
64 | throw new RuntimeException(e);
65 | }
66 |
67 | event.readValue(value);
68 |
69 | return new CopiedRecord<>(
70 | value,
71 | metadata,
72 | event.getKey(),
73 | partitionId,
74 | event.getPosition(),
75 | event.getSourceEventPosition(),
76 | event.getTimestamp());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "enabled": true,
3 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
4 | "extends": [
5 | "config:recommended"
6 | ],
7 | "commitMessagePrefix": "deps:",
8 | "baseBranchPatterns": [
9 | "/^stable\\/8\\.([5-9]|[1-9][0-9])/",
10 | "main"
11 | ],
12 | "dependencyDashboard": true,
13 | "prConcurrentLimit": 30,
14 | "prHourlyLimit": 2,
15 | "updateNotScheduled": false,
16 | "schedule": [
17 | "at any time"
18 | ],
19 | "vulnerabilityAlerts": {
20 | "labels": [
21 | "area/security"
22 | ],
23 | "enabled": true
24 | },
25 | "lockFileMaintenance": {
26 | "enabled": true,
27 | "automerge": true,
28 | "addLabels": [
29 | "automerge"
30 | ]
31 | },
32 | "packageRules": [
33 | {
34 | "description": "Only patch updates for our maintenance branches to avoid breaking changes.",
35 | "matchBaseBranches": [
36 | "/^stable\\/8\\..*/"
37 | ],
38 | "matchUpdateTypes": [
39 | "minor",
40 | "major"
41 | ],
42 | "enabled": false
43 | },
44 | {
45 | "description": "Digest updates cover all use cases since they are used as base, so we disable other types.",
46 | "matchManagers": [
47 | "dockerfile"
48 | ],
49 | "matchFileNames": [
50 | "Dockerfile"
51 | ],
52 | "matchUpdateTypes": [
53 | "major",
54 | "minor",
55 | "patch"
56 | ],
57 | "enabled": true
58 | },
59 | {
60 | "matchManagers": [
61 | "maven"
62 | ],
63 | "allowedVersions": "!/0.8.9/",
64 | "matchPackageNames": [
65 | "org.jacoco{/,}**"
66 | ]
67 | },
68 | {
69 | "description": "Exclude BPMN model dependencies which target JDK 11 (since this library targets JDK 8)",
70 | "matchManagers": [
71 | "maven"
72 | ],
73 | "allowedVersions": "<7.20.0",
74 | "matchPackageNames": [
75 | "org.camunda.bpmn.model{/,}**"
76 | ]
77 | },
78 | {
79 | "description": "Exclude SNAPSHOT versions, renovate may suggest them for pre-release values.",
80 | "matchManagers": [
81 | "maven"
82 | ],
83 | "allowedVersions": "!/-SNAPSHOT$/",
84 | "matchPackageNames": [
85 | "/.*/"
86 | ]
87 | },
88 | {
89 | "description": "Exclude io.camunda updates, we manage deps to camunda components manually.",
90 | "matchManagers": [
91 | "maven"
92 | ],
93 | "matchPackageNames": [
94 | "io.camunda{/,}**"
95 | ],
96 | "enabled": false
97 | },
98 | {
99 | "description": "Automerge all updates with green CI.",
100 | "automerge": true,
101 | "addLabels": [
102 | "automerge"
103 | ],
104 | "matchPackageNames": [
105 | "*"
106 | ]
107 | }
108 | ]
109 | }
110 |
--------------------------------------------------------------------------------
/qa/abstracts/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | io.camunda
6 | zeebe-process-test-qa
7 | 8.9.0-SNAPSHOT
8 | ../pom.xml
9 |
10 |
11 | zeebe-process-test-qa-abstracts
12 | jar
13 |
14 | Zeebe Process Test QA Abstracts
15 |
16 |
17 | 8
18 |
19 |
20 |
21 |
22 | org.junit.jupiter
23 | junit-jupiter-api
24 |
25 |
26 |
27 | org.mockito
28 | mockito-core
29 |
30 |
31 |
32 | org.apache.commons
33 | commons-lang3
34 |
35 |
36 |
37 | io.camunda
38 | zeebe-process-test-filters
39 |
40 |
41 |
42 | io.camunda
43 | zeebe-process-test-assertions
44 |
45 |
46 |
47 | io.camunda
48 | zeebe-protocol
49 |
50 |
51 |
52 | io.camunda
53 | zeebe-client-java
54 |
55 |
56 |
57 | io.camunda
58 | zeebe-process-test-api
59 |
60 |
61 |
62 | org.assertj
63 | assertj-core
64 |
65 |
66 |
67 | org.slf4j
68 | slf4j-simple
69 |
70 |
71 |
72 | org.slf4j
73 | slf4j-api
74 |
75 |
76 |
77 | com.fasterxml.jackson.datatype
78 | jackson-datatype-jsr310
79 |
80 |
81 |
82 | com.fasterxml.jackson.core
83 | jackson-databind
84 |
85 |
86 |
87 | org.junit.jupiter
88 | junit-jupiter-params
89 |
90 |
91 |
92 | org.awaitility
93 | awaitility
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/filters/src/main/java/io/camunda/zeebe/process/test/filters/StreamFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2021 camunda services GmbH (info@camunda.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.camunda.zeebe.process.test.filters;
17 |
18 | public class StreamFilter {
19 |
20 | public static ProcessInstanceRecordStreamFilter processInstance(final RecordStream recordStream) {
21 | return new ProcessInstanceRecordStreamFilter(recordStream.processInstanceRecords());
22 | }
23 |
24 | public static ProcessMessageSubscriptionRecordStreamFilter processMessageSubscription(
25 | final RecordStream recordStream) {
26 | return new ProcessMessageSubscriptionRecordStreamFilter(
27 | recordStream.processMessageSubscriptionRecords());
28 | }
29 |
30 | public static VariableRecordStreamFilter variable(final RecordStream recordStream) {
31 | return new VariableRecordStreamFilter(recordStream.variableRecords());
32 | }
33 |
34 | public static MessageRecordStreamFilter message(final RecordStream recordStream) {
35 | return new MessageRecordStreamFilter(recordStream.messageRecords());
36 | }
37 |
38 | public static IncidentRecordStreamFilter incident(final RecordStream recordStream) {
39 | return new IncidentRecordStreamFilter(recordStream.incidentRecords());
40 | }
41 |
42 | public static MessageStartEventSubscriptionStreamFilter messageStartEventSubscription(
43 | final RecordStream recordStream) {
44 | return new MessageStartEventSubscriptionStreamFilter(
45 | recordStream.messageStartEventSubscriptionRecords());
46 | }
47 |
48 | public static ProcessEventRecordStreamFilter processEventRecords(
49 | final RecordStream recordStream) {
50 | return new ProcessEventRecordStreamFilter(recordStream.records());
51 | }
52 |
53 | public static JobRecordStreamFilter jobRecords(final RecordStream recordStream) {
54 | return new JobRecordStreamFilter(recordStream.jobRecords());
55 | }
56 |
57 | public static TimerRecordStreamFilter timerRecords(final RecordStream recordStream) {
58 | return new TimerRecordStreamFilter(recordStream.timerRecords());
59 | }
60 |
61 | public static ProcessRecordStreamFilter processRecords(final RecordStream recordStream) {
62 | return new ProcessRecordStreamFilter(recordStream.processRecords());
63 | }
64 |
65 | public static FormStreamFilter forms(final RecordStream recordStream) {
66 | return new FormStreamFilter(recordStream.forms());
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/.github/workflows/snapshot-test.yml:
--------------------------------------------------------------------------------
1 | name: Zeebe SNAPSHOT test
2 | on:
3 | workflow_dispatch: { }
4 | workflow_call: { }
5 | schedule:
6 | - cron: "0 3 * * 1-5"
7 | jobs:
8 | test-against-zeebe-snapshot:
9 | name: Run tests against Zeebe SNAPSHOT version
10 | timeout-minutes: 15
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v5
16 |
17 | - name: Set up Java environment
18 | uses: actions/setup-java@v5
19 | with:
20 | distribution: temurin
21 | java-version: 21
22 |
23 | - name: Build with Zeebe SNAPSHOT version
24 | run: |
25 | CURRENT_ZEEBE_VERSION=$(mvn help:evaluate -Dexpression=dependency.zeebe.version -DforceStdout -q)
26 | if grep -q "alpha" <<< "$CURRENT_ZEEBE_VERSION"; then
27 | NEW_ZEEBE_VERSION=$(echo $CURRENT_ZEEBE_VERSION | sed "s/alpha.*/SNAPSHOT/")
28 | elif grep -q "SNAPSHOT" <<< "$CURRENT_ZEEBE_VERSION"; then
29 | NEW_ZEEBE_VERSION=$CURRENT_ZEEBE_VERSION
30 | else
31 | NEW_ZEEBE_VERSION=`echo $CURRENT_ZEEBE_VERSION | awk -F. '/[0-9]+\./{$2++;print}' OFS=.`-SNAPSHOT
32 | fi
33 | echo $NEW_ZEEBE_VERSION
34 | mvn -B -U -P !localBuild "-Dsurefire.rerunFailingTestsCount=5" -Ddependency.zeebe.version=$NEW_ZEEBE_VERSION clean install
35 |
36 | - name: Archive Test Results
37 | uses: actions/upload-artifact@v4
38 | if: always()
39 | with:
40 | name: Unit Test Results Against Zeebe Snapshot
41 | path: "**/target/surefire-reports/"
42 | retention-days: 7
43 |
44 | notify-if-failed:
45 | name: Send slack notification on build failure
46 | runs-on: ubuntu-latest
47 | needs: [test-against-zeebe-snapshot]
48 | if: failure()
49 | steps:
50 | - id: slack-notify
51 | name: Send slack notification
52 | uses: slackapi/slack-github-action@v2.1.1
53 | with:
54 | webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
55 | webhook-type: incoming-webhook
56 | # For posting a rich message using Block Kit
57 | payload: |
58 | {
59 | "text": ":alarm: `zeebe-process-test` build against Zeebe SNAPSHOT version failed! :alarm:",
60 | "blocks": [
61 | {
62 | "type": "section",
63 | "text": {
64 | "type": "mrkdwn",
65 | "text": ":alarm: `zeebe-process-test` build against Zeebe SNAPSHOT version failed! :alarm:"
66 | }
67 | },
68 | {
69 | "type": "section",
70 | "text": {
71 | "type": "mrkdwn",
72 | "text": "Please check the related workflow (${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) and fix it before it blocks the upcoming release!\n \\cc @camunda-ex-medic"
73 | }
74 | }
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------