diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml
index 3149c89dd..742bf1af4 100644
--- a/.github/workflows/pullrequest.yml
+++ b/.github/workflows/pullrequest.yml
@@ -21,7 +21,7 @@ jobs:
- name: Check out the code
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493
- - name: Set up JDK 11
+ - name: Set up JDK ${{ matrix.build.java }}
uses: actions/setup-java@a7ab372554b6eb1a8eb25e7d9aec1cc9f3ea1a76
with:
java-version: ${{ matrix.build.java }}
diff --git a/pom.xml b/pom.xml
index 516a241f0..67b031257 100644
--- a/pom.xml
+++ b/pom.xml
@@ -193,6 +193,13 @@
test
+
+ com.vmlens
+ api
+ 1.2.13
+ test
+
+
@@ -239,7 +246,6 @@
pom
import
-
@@ -331,7 +337,6 @@
-
@@ -343,6 +348,22 @@
+
+ com.vmlens
+ vmlens-maven-plugin
+ 1.2.13
+
+
+ test
+
+ test
+
+
+ true
+
+
+
+
maven-dependency-plugin
3.8.1
diff --git a/src/test/java/dev/openfeature/sdk/vmlens/VmLensTest.java b/src/test/java/dev/openfeature/sdk/vmlens/VmLensTest.java
new file mode 100644
index 000000000..136c35965
--- /dev/null
+++ b/src/test/java/dev/openfeature/sdk/vmlens/VmLensTest.java
@@ -0,0 +1,77 @@
+package dev.openfeature.sdk.vmlens;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.vmlens.api.AllInterleavings;
+import com.vmlens.api.Runner;
+import dev.openfeature.sdk.ImmutableContext;
+import dev.openfeature.sdk.OpenFeatureAPI;
+import dev.openfeature.sdk.OpenFeatureAPITestUtil;
+import dev.openfeature.sdk.Value;
+import dev.openfeature.sdk.providers.memory.Flag;
+import dev.openfeature.sdk.providers.memory.InMemoryProvider;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class VmLensTest {
+ final OpenFeatureAPI api = OpenFeatureAPITestUtil.createAPI();
+
+ @BeforeEach
+ void setUp() {
+ var flags = new HashMap>();
+ flags.put("a", Flag.builder().variant("a", "def").defaultVariant("a").build());
+ flags.put("b", Flag.builder().variant("a", "as").defaultVariant("a").build());
+ api.setProviderAndWait(new InMemoryProvider(flags));
+ }
+
+ @AfterEach
+ void tearDown() {
+ api.clearHooks();
+ api.shutdown();
+ }
+
+ @Test
+ void concurrentClientCreations() {
+ try (AllInterleavings allInterleavings = new AllInterleavings("Concurrent creations of the Client")) {
+ while (allInterleavings.hasNext()) {
+ Runner.runParallel(api::getClient, api::getClient);
+ }
+ }
+ // keep the linter happy
+ assertTrue(true);
+ }
+
+ @Test
+ void concurrentFlagEvaluations() {
+ var client = api.getClient();
+ try (AllInterleavings allInterleavings = new AllInterleavings("Concurrent evaluations")) {
+ while (allInterleavings.hasNext()) {
+ Runner.runParallel(
+ () -> assertEquals("def", client.getStringValue("a", "a")),
+ () -> assertEquals("as", client.getStringValue("b", "b")));
+ }
+ }
+ }
+
+ @Test
+ void concurrentContextSetting() {
+ var client = api.getClient();
+ var contextA = new ImmutableContext(Map.of("a", new Value("b")));
+ var contextB = new ImmutableContext(Map.of("c", new Value("d")));
+ try (AllInterleavings allInterleavings =
+ new AllInterleavings("Concurrently setting the context and evaluating a flag")) {
+ while (allInterleavings.hasNext()) {
+ Runner.runParallel(
+ () -> assertEquals("def", client.getStringValue("a", "a")),
+ () -> client.setEvaluationContext(contextA),
+ () -> client.setEvaluationContext(contextB));
+ assertThat(client.getEvaluationContext()).isIn(contextA, contextB);
+ }
+ }
+ }
+}