Skip to content

Commit 3c8ca74

Browse files
aepflichrfwow
andauthored
test(flagd): use newest testbed launchpad (#1168)
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com> Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com> Co-authored-by: christian.lutnik <christian.lutnik@dynatrace.com>
1 parent d38e013 commit 3c8ca74

File tree

22 files changed

+121
-174
lines changed

22 files changed

+121
-174
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[submodule "providers/flagd/test-harness"]
55
path = providers/flagd/test-harness
66
url = https://github.com/open-feature/test-harness.git
7-
branch = v1.1.1
7+
branch = v1.3.3
88
[submodule "providers/flagd/spec"]
99
path = providers/flagd/spec
1010
url = https://github.com/open-feature/spec.git

providers/flagd/pom.xml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,13 @@
150150
<scope>test</scope>
151151
</dependency>
152152
<dependency>
153-
<groupId>org.testcontainers</groupId>
154-
<artifactId>toxiproxy</artifactId>
155-
<version>1.20.4</version>
153+
<groupId>io.rest-assured</groupId>
154+
<artifactId>rest-assured</artifactId>
155+
<version>5.5.0</version>
156156
<scope>test</scope>
157157
</dependency>
158158
<!-- uncomment for logoutput during test runs -->
159-
160-
<dependency>
159+
<dependency>
161160
<groupId>org.slf4j</groupId>
162161
<artifactId>slf4j-simple</artifactId>
163162
<version>2.0.16</version>
@@ -254,7 +253,7 @@
254253
<configuration>
255254
<protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact>
256255
<pluginId>grpc-java</pluginId>
257-
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.68.2:exe:${os.detected.classifier}</pluginArtifact>
256+
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.69.1:exe:${os.detected.classifier}</pluginArtifact>
258257
<protoSourceRoot>${project.basedir}/schemas/protobuf/</protoSourceRoot>
259258
</configuration>
260259
<executions>

providers/flagd/schemas

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ EvaluationContext getEnrichedContext() {
209209
private void onProviderEvent(FlagdProviderEvent flagdProviderEvent) {
210210

211211
synchronized (eventsLock) {
212-
log.info("FlagdProviderEvent: {}", flagdProviderEvent);
212+
log.info("FlagdProviderEvent: {}", flagdProviderEvent.getEvent());
213213
eventsLock.syncMetadata = flagdProviderEvent.getSyncMetadata();
214214
if (flagdProviderEvent.getSyncMetadata() != null) {
215215
eventsLock.enrichedContext = contextEnricher.apply(flagdProviderEvent.getSyncMetadata());

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelMonitor.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ public static void monitorChannelState(
4747
log.debug("onConnectionLost is null");
4848
}
4949
}
50-
// Re-register the state monitor to watch for the next state transition.
51-
monitorChannelState(currentState, channel, onConnectionReady, onConnectionLost);
50+
if (currentState != ConnectivityState.SHUTDOWN) {
51+
log.debug("shutting down grpc channel");
52+
// Re-register the state monitor to watch for the next state transition.
53+
monitorChannelState(currentState, channel, onConnectionReady, onConnectionLost);
54+
}
5255
});
5356
}
5457

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/EventStreamObserver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public void onCompleted() {}
6464
* @param value the event stream response containing configuration change data
6565
*/
6666
private void handleConfigurationChangeEvent(EventStreamResponse value) {
67+
log.debug("Received provider change event");
6768
List<String> changedFlags = new ArrayList<>();
6869

6970
Map<String, Value> data = value.getData().getFieldsMap();
@@ -80,7 +81,7 @@ private void handleConfigurationChangeEvent(EventStreamResponse value) {
8081
* Handles provider readiness events by clearing the cache (if enabled) and notifying listeners of readiness.
8182
*/
8283
private void handleProviderReadyEvent() {
83-
log.info("Received provider ready event");
84+
log.debug("Received provider ready event");
8485
onReady.accept(new FlagdProviderEvent(ProviderEvent.PROVIDER_READY));
8586
}
8687
}

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/storage/connector/grpc/GrpcStreamConnector.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ void observeEventStream(final BlockingQueue<QueuePayload> writeTo, final AtomicB
118118
metadataException = e;
119119
}
120120

121-
log.info("stream");
122121
while (!shutdown.get()) {
123122
final GrpcResponseModel response = streamReceiver.take();
124123
if (response.isComplete()) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
org.org.slf4j.simpleLogger.defaultLogLevel=debug
2+
3+
io.grpc.level=trace
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.openfeature.contrib.providers.flagd.e2e;
1+
package dev.openfeature.contrib.providers.flagd;
22

33
import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
44
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;
@@ -18,5 +18,5 @@
1818
@IncludeEngines("cucumber")
1919
@SelectFile("test-harness/gherkin/config.feature")
2020
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
21-
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps")
22-
public class RunConfigCucumberTest {}
21+
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps.config")
22+
public class ConfigCucumberTest {}

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdProviderTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import dev.openfeature.sdk.Reason;
4747
import dev.openfeature.sdk.Structure;
4848
import dev.openfeature.sdk.Value;
49-
import io.cucumber.java.AfterAll;
5049
import java.lang.reflect.Field;
5150
import java.lang.reflect.Method;
5251
import java.util.ArrayList;
@@ -60,7 +59,8 @@
6059
import java.util.concurrent.TimeUnit;
6160
import java.util.function.Consumer;
6261
import java.util.function.Function;
63-
import org.junit.jupiter.api.BeforeAll;
62+
import org.junit.jupiter.api.AfterEach;
63+
import org.junit.jupiter.api.BeforeEach;
6464
import org.junit.jupiter.api.Test;
6565
import org.mockito.MockedConstruction;
6666

@@ -90,15 +90,15 @@ class FlagdProviderTest {
9090
.build();
9191
private static final String STRING_VALUE = "hi!";
9292

93-
private static OpenFeatureAPI api;
93+
private OpenFeatureAPI api;
9494

95-
@BeforeAll
96-
public static void init() {
95+
@BeforeEach
96+
public void init() {
9797
api = OpenFeatureAPI.getInstance();
9898
}
9999

100-
@AfterAll
101-
public static void cleanUp() {
100+
@AfterEach
101+
public void cleanUp() {
102102
api.shutdown();
103103
}
104104

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/FlagdContainer.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package dev.openfeature.contrib.providers.flagd.e2e;
22

3+
import dev.openfeature.contrib.providers.flagd.Config;
34
import java.io.File;
45
import java.nio.file.Files;
56
import java.util.List;
6-
import org.apache.logging.log4j.util.Strings;
77
import org.jetbrains.annotations.NotNull;
88
import org.testcontainers.containers.GenericContainer;
99
import org.testcontainers.containers.Network;
@@ -25,19 +25,25 @@ public class FlagdContainer extends GenericContainer<FlagdContainer> {
2525
}
2626
}
2727

28-
private String feature;
29-
3028
public FlagdContainer() {
31-
this("");
29+
super(generateContainerName());
30+
this.addExposedPorts(8013, 8014, 8015, 8080);
3231
}
3332

34-
public FlagdContainer(String feature) {
35-
super(generateContainerName(feature));
36-
this.withReuse(true);
37-
this.feature = feature;
38-
if (!"socket".equals(this.feature)) this.addExposedPorts(8013, 8014, 8015, 8016);
33+
public int getPort(Config.Resolver resolver) {
34+
switch (resolver) {
35+
case RPC:
36+
return getMappedPort(8013);
37+
case IN_PROCESS:
38+
return getMappedPort(8015);
39+
default:
40+
return 0;
41+
}
3942
}
4043

44+
public String getLaunchpadUrl() {
45+
return this.getHost() + ":" + this.getMappedPort(8080);
46+
}
4147
/**
4248
* @return a {@link org.testcontainers.containers.GenericContainer} instance of envoy container using
4349
* flagd sync service as backend expose on port 9211
@@ -52,11 +58,8 @@ public static GenericContainer envoy() {
5258
.withNetworkAliases("envoy");
5359
}
5460

55-
public static @NotNull String generateContainerName(String feature) {
61+
public static @NotNull String generateContainerName() {
5662
String container = "ghcr.io/open-feature/flagd-testbed";
57-
if (!Strings.isBlank(feature)) {
58-
container += "-" + feature;
59-
}
6063
container += ":v" + version;
6164
return container;
6265
}

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/RunInProcessTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import dev.openfeature.contrib.providers.flagd.Config;
88
import org.apache.logging.log4j.core.config.Order;
9+
import org.junit.jupiter.api.parallel.Isolated;
910
import org.junit.platform.suite.api.BeforeSuite;
1011
import org.junit.platform.suite.api.ConfigurationParameter;
1112
import org.junit.platform.suite.api.ExcludeTags;
@@ -30,6 +31,7 @@
3031
@IncludeTags("in-process")
3132
@ExcludeTags({"unixsocket", "targetURI"})
3233
@Testcontainers
34+
@Isolated
3335
public class RunInProcessTest {
3436

3537
@BeforeSuite

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/State.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import dev.openfeature.contrib.providers.flagd.e2e.steps.FlagSteps;
77
import dev.openfeature.contrib.providers.flagd.e2e.steps.ProviderType;
88
import dev.openfeature.sdk.Client;
9+
import dev.openfeature.sdk.FeatureProvider;
910
import dev.openfeature.sdk.FlagEvaluationDetails;
1011
import dev.openfeature.sdk.MutableContext;
1112
import java.util.LinkedList;
@@ -15,6 +16,7 @@
1516
public class State {
1617
public ProviderType providerType;
1718
public Client client;
19+
public FeatureProvider provider;
1820
public List<Event> events = new LinkedList<>();
1921
public Optional<Event> lastEvent;
2022
public FlagSteps.Flag flag;

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/steps/AbstractSteps.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import dev.openfeature.contrib.providers.flagd.e2e.State;
44

5-
abstract class AbstractSteps {
6-
State state;
5+
public abstract class AbstractSteps {
6+
protected State state;
77

8-
public AbstractSteps(State state) {
8+
protected AbstractSteps(State state) {
99
this.state = state;
1010
}
1111
}

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/steps/EnvironmentVariableUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* This class modifies the internals of the environment variables map with reflection. Warning: If
1515
* your {@link SecurityManager} does not allow modifications, it fails.
1616
*/
17-
class EnvironmentVariableUtils {
17+
public class EnvironmentVariableUtils {
1818

1919
private EnvironmentVariableUtils() {
2020
// private constructor to prevent instantiation of utility class

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/steps/EventSteps.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public EventSteps(State state) {
2525
@Given("a {} event handler")
2626
public void a_stale_event_handler(String eventType) {
2727
state.client.on(mapEventType(eventType), eventDetails -> {
28-
log.info("event tracked for {} ", eventType);
28+
log.info("event tracked for {} at {} ms ", eventType, System.currentTimeMillis() % 100_000);
2929
state.events.add(new Event(eventType, eventDetails));
3030
});
3131
}
@@ -47,24 +47,24 @@ public void a_stale_event_handler(String eventType) {
4747

4848
@When("a {} event was fired")
4949
public void eventWasFired(String eventType) throws InterruptedException {
50-
eventHandlerShouldBeExecutedWithin(eventType, 10000);
51-
// we might be too fast in the execution
52-
Thread.sleep(500);
50+
eventHandlerShouldBeExecutedWithin(eventType, 8000);
5351
}
5452

5553
@Then("the {} event handler should have been executed")
5654
public void eventHandlerShouldBeExecuted(String eventType) {
57-
eventHandlerShouldBeExecutedWithin(eventType, 30000);
55+
eventHandlerShouldBeExecutedWithin(eventType, 10000);
5856
}
5957

6058
@Then("the {} event handler should have been executed within {int}ms")
6159
public void eventHandlerShouldBeExecutedWithin(String eventType, int ms) {
6260
log.info("waiting for eventtype: {}", eventType);
63-
await().atMost(ms, MILLISECONDS)
61+
await().alias("waiting for eventtype " + eventType)
62+
.atMost(ms, MILLISECONDS)
63+
.pollInterval(10, MILLISECONDS)
6464
.until(() -> state.events.stream().anyMatch(event -> event.type.equals(eventType)));
6565
state.lastEvent = state.events.stream()
6666
.filter(event -> event.type.equals(eventType))
6767
.findFirst();
68-
state.events.removeIf(event -> event.type.equals(eventType));
68+
state.events.clear();
6969
}
7070
}

providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/e2e/steps/FlagSteps.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package dev.openfeature.contrib.providers.flagd.e2e.steps;
22

3-
import static java.util.concurrent.TimeUnit.MILLISECONDS;
43
import static org.assertj.core.api.Assertions.assertThat;
5-
import static org.awaitility.Awaitility.await;
64

75
import dev.openfeature.contrib.providers.flagd.e2e.State;
86
import dev.openfeature.sdk.FlagEvaluationDetails;
@@ -70,15 +68,9 @@ public void the_variant_should_be(String variant) {
7068
}
7169

7270
@Then("the flag should be part of the event payload")
73-
@Then("the flag was modified")
7471
public void the_flag_was_modified() {
75-
await().atMost(5000, MILLISECONDS).until(() -> state.events.stream()
76-
.anyMatch(event -> event.type.equals("change")
77-
&& event.details.getFlagsChanged().contains(state.flag.name)));
78-
state.lastEvent = state.events.stream()
79-
.filter(event -> event.type.equals("change")
80-
&& event.details.getFlagsChanged().contains(state.flag.name))
81-
.findFirst();
72+
Event event = state.lastEvent.orElseThrow(AssertionError::new);
73+
assertThat(event.details.getFlagsChanged()).contains(state.flag.name);
8274
}
8375

8476
public class Flag {

0 commit comments

Comments
 (0)