Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ jobs:
${{ runner.os }}${{ matrix.build.java }}-maven-

- name: Verify with Maven
run: mvn --batch-mode --update-snapshots --activate-profiles e2e,${{ matrix.build.profile }} verify
run: mvn --batch-mode --update-snapshots --activate-profiles e2e,${{ matrix.build.profile }} install

- name: Verify no breaking changes
run: mvn verify

- if: matrix.build.java == '17'
name: Upload coverage to Codecov
Expand Down
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>dev.openfeature.contrib.providers</groupId>
<artifactId>flagd</artifactId>
<version>0.11.18</version>
<scope>test</scope>
</dependency>

</dependencies>

<dependencyManagement>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/openfeature/sdk/EventProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public Awaitable emit(final ProviderEvent event, final ProviderEventDetails deta
*
* @param details The details of the event
*/
public Awaitable emitProviderReady(ProviderEventDetails details) {
/*public*/ Awaitable emitProviderReady(ProviderEventDetails details) {
Copy link
Contributor Author

@chrfwow chrfwow Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/*public*/ Awaitable emitProviderReady(ProviderEventDetails details) {
public Awaitable emitProviderReady(ProviderEventDetails details) {

Revert. This is my breaking change which I want to catch with this test

return emit(ProviderEvent.PROVIDER_READY, details);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
text =
"If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
@Test
void shouldPutTheProviderInStateReadyAfterEmittingReadyEvent() {

Check warning on line 179 in src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Update this method so that its implementation is not identical to "shouldPutTheProviderInStateStaleAfterEmittingStaleEvent" on line 164.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn-COMul3jc-Pq6Xr&open=AZrEn-COMul3jc-Pq6Xr&pullRequest=1749
String domain = "domain";
var provider = TestProvider.builder().initsToReady();
api.setProviderAndWait(domain, provider);
Expand All @@ -184,7 +184,7 @@
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
provider.emitProviderStale(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
provider.emitProviderReady(ProviderEventDetails.builder().build()).await();
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
// provider.emitProviderReady(ProviderEventDetails.builder().build()).await();

Check warning on line 187 in src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn-COMul3jc-Pq6Xs&open=AZrEn-COMul3jc-Pq6Xs&pullRequest=1749
// assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
}
}
88 changes: 88 additions & 0 deletions src/test/java/dev/openfeature/sdk/NoBreakingChangesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package dev.openfeature.sdk;

import dev.openfeature.contrib.providers.flagd.Config;
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
import dev.openfeature.contrib.providers.flagd.FlagdProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.HashSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.assertj.core.api.Assertions.assertThat;

class NoBreakingChangesTest {

private AtomicBoolean isTestRunning;
private ConcurrentLinkedQueue<Throwable> uncaughtExceptions;
private Thread threadWatcher;

@BeforeEach
void setup() {
final var isRunning = new AtomicBoolean(true);
final var uncaught = new ConcurrentLinkedQueue<Throwable>();
uncaughtExceptions = uncaught;
isTestRunning = isRunning;

threadWatcher = new Thread(() -> {
var seenThreads = new HashSet<Thread>();
while (isRunning.get()) {
var stacks = Thread.getAllStackTraces();
for (var entry : stacks.entrySet()) {
var thread = entry.getKey();
if (seenThreads.add(thread)) {
thread.setUncaughtExceptionHandler((thread1, throwable) -> {
uncaught.add(throwable);
});
}
}
}
});
threadWatcher.setDaemon(true);
threadWatcher.start();
}

@AfterEach
void teardown() throws InterruptedException {
try {
Thread.sleep(1000); // wait a bit for any uncaught exceptions to be reported

Check warning on line 50 in src/test/java/dev/openfeature/sdk/NoBreakingChangesTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "Thread.sleep()".

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn-DFMul3jc-Pq6Xt&open=AZrEn-DFMul3jc-Pq6Xt&pullRequest=1749

isTestRunning.set(false);
threadWatcher.join(1000);
} finally {
assertThat(uncaughtExceptions).isEmpty();
}
}

@Test
void noBreakingChanges() {
var testProvider = new FlagdProvider(FlagdOptions.builder()
.resolverType(Config.Resolver.FILE)
.offlineFlagSourcePath(NoBreakingChangesTest.class
.getResource("/testFlags.json")
.getPath()
.replaceFirst("/", ""))
.build());
var api = new OpenFeatureAPI();
api.setProviderAndWait(testProvider);

var client = api.getClient();
var flagFound = client.getBooleanDetails("basic-boolean", false);
assertThat(flagFound).isNotNull();
assertThat(flagFound.getValue()).isTrue();
assertThat(flagFound.getVariant()).isEqualTo("true");
assertThat(flagFound.getReason()).isEqualTo(Reason.STATIC.toString());

var flagNotFound = client.getStringDetails("unknown", "asd");
assertThat(flagNotFound).isNotNull();
assertThat(flagNotFound.getValue()).isEqualTo("asd");
assertThat(flagNotFound.getVariant()).isNull();
assertThat(flagNotFound.getReason()).isEqualTo(Reason.ERROR.toString());
assertThat(flagNotFound.getErrorCode()).isEqualTo(ErrorCode.FLAG_NOT_FOUND);

testProvider.shutdown();
api.shutdown();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@
switch (providerState) {
case FATAL:
case ERROR:
mockProvider.emitProviderReady(details).await();
// mockProvider.emitProviderReady(details).await();

Check warning on line 115 in src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn99mMul3jc-Pq6Xo&open=AZrEn99mMul3jc-Pq6Xo&pullRequest=1749
mockProvider.emitProviderError(details).await();
break;
case STALE:
mockProvider.emitProviderReady(details).await();
// mockProvider.emitProviderReady(details).await();

Check warning on line 119 in src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn99mMul3jc-Pq6Xp&open=AZrEn99mMul3jc-Pq6Xp&pullRequest=1749
mockProvider.emitProviderStale(details).await();
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import dev.openfeature.sdk.Metadata;
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.ProviderEvent;
import dev.openfeature.sdk.ProviderEventDetails;
import dev.openfeature.sdk.Value;
import java.util.function.Consumer;

Expand Down Expand Up @@ -38,7 +37,7 @@
* This line deadlocked in the original implementation without the emitterExecutor see
* https://github.com/open-feature/java-sdk/issues/1299
*/
emitProviderReady(ProviderEventDetails.builder().build());
// emitProviderReady(ProviderEventDetails.builder().build());

Check warning on line 40 in src/test/java/dev/openfeature/sdk/testutils/TestStackedEmitCallsProvider.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=open-feature_java-sdk&issues=AZrEn-B0Mul3jc-Pq6Xq&open=AZrEn-B0Mul3jc-Pq6Xq&pullRequest=1749
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/test/resources/testFlags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://flagd.dev/schema/v0/flags.json",
"flags": {
"basic-boolean": {
"state": "ENABLED",
"defaultVariant": "true",
"variants": {
"true": true,
"false": false
},
"targeting": {}
}
}
}
Loading