Skip to content

test(flagd): use newest testbed launchpad #1168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[submodule "providers/flagd/test-harness"]
path = providers/flagd/test-harness
url = https://github.com/open-feature/test-harness.git
branch = v1.1.1
branch = v1.3.3
[submodule "providers/flagd/spec"]
path = providers/flagd/spec
url = https://github.com/open-feature/spec.git
11 changes: 5 additions & 6 deletions providers/flagd/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>toxiproxy</artifactId>
<version>1.20.4</version>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<!-- uncomment for logoutput during test runs -->

<dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
Expand Down Expand Up @@ -254,7 +253,7 @@
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.68.2:exe:${os.detected.classifier}</pluginArtifact>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.69.1:exe:${os.detected.classifier}</pluginArtifact>
<protoSourceRoot>${project.basedir}/schemas/protobuf/</protoSourceRoot>
</configuration>
<executions>
Expand Down
2 changes: 1 addition & 1 deletion providers/flagd/schemas
2 changes: 1 addition & 1 deletion providers/flagd/spec
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ EvaluationContext getEnrichedContext() {
private void onProviderEvent(FlagdProviderEvent flagdProviderEvent) {

synchronized (eventsLock) {
log.info("FlagdProviderEvent: {}", flagdProviderEvent);
log.info("FlagdProviderEvent: {}", flagdProviderEvent.getEvent());
eventsLock.syncMetadata = flagdProviderEvent.getSyncMetadata();
if (flagdProviderEvent.getSyncMetadata() != null) {
eventsLock.enrichedContext = contextEnricher.apply(flagdProviderEvent.getSyncMetadata());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ public static void monitorChannelState(
log.debug("onConnectionLost is null");
}
}
// Re-register the state monitor to watch for the next state transition.
monitorChannelState(currentState, channel, onConnectionReady, onConnectionLost);
if (currentState != ConnectivityState.SHUTDOWN) {
log.debug("shutting down grpc channel");
// Re-register the state monitor to watch for the next state transition.
monitorChannelState(currentState, channel, onConnectionReady, onConnectionLost);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public void onCompleted() {}
* @param value the event stream response containing configuration change data
*/
private void handleConfigurationChangeEvent(EventStreamResponse value) {
log.debug("Received provider change event");
List<String> changedFlags = new ArrayList<>();

Map<String, Value> data = value.getData().getFieldsMap();
Expand All @@ -80,7 +81,7 @@ private void handleConfigurationChangeEvent(EventStreamResponse value) {
* Handles provider readiness events by clearing the cache (if enabled) and notifying listeners of readiness.
*/
private void handleProviderReadyEvent() {
log.info("Received provider ready event");
log.debug("Received provider ready event");
onReady.accept(new FlagdProviderEvent(ProviderEvent.PROVIDER_READY));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ void observeEventStream(final BlockingQueue<QueuePayload> writeTo, final AtomicB
metadataException = e;
}

log.info("stream");
while (!shutdown.get()) {
final GrpcResponseModel response = streamReceiver.take();
if (response.isComplete()) {
Expand Down
3 changes: 3 additions & 0 deletions providers/flagd/src/main/resources/simplelogger.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
org.org.slf4j.simpleLogger.defaultLogLevel=debug

io.grpc.level=trace
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.openfeature.contrib.providers.flagd.e2e;
package dev.openfeature.contrib.providers.flagd;

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;
Expand All @@ -18,5 +18,5 @@
@IncludeEngines("cucumber")
@SelectFile("test-harness/gherkin/config.feature")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps")
public class RunConfigCucumberTest {}
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps.config")
public class ConfigCucumberTest {}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import dev.openfeature.sdk.Reason;
import dev.openfeature.sdk.Structure;
import dev.openfeature.sdk.Value;
import io.cucumber.java.AfterAll;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
Expand All @@ -60,7 +59,8 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;

Expand Down Expand Up @@ -90,15 +90,15 @@ class FlagdProviderTest {
.build();
private static final String STRING_VALUE = "hi!";

private static OpenFeatureAPI api;
private OpenFeatureAPI api;

@BeforeAll
public static void init() {
@BeforeEach
public void init() {
api = OpenFeatureAPI.getInstance();
}

@AfterAll
public static void cleanUp() {
@AfterEach
public void cleanUp() {
api.shutdown();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package dev.openfeature.contrib.providers.flagd.e2e;

import dev.openfeature.contrib.providers.flagd.Config;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.NotNull;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
Expand All @@ -25,19 +25,25 @@ public class FlagdContainer extends GenericContainer<FlagdContainer> {
}
}

private String feature;

public FlagdContainer() {
this("");
super(generateContainerName());
this.addExposedPorts(8013, 8014, 8015, 8080);
}

public FlagdContainer(String feature) {
super(generateContainerName(feature));
this.withReuse(true);
this.feature = feature;
if (!"socket".equals(this.feature)) this.addExposedPorts(8013, 8014, 8015, 8016);
public int getPort(Config.Resolver resolver) {
switch (resolver) {
case RPC:
return getMappedPort(8013);
case IN_PROCESS:
return getMappedPort(8015);
default:
return 0;
}
}

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

public static @NotNull String generateContainerName(String feature) {
public static @NotNull String generateContainerName() {
String container = "ghcr.io/open-feature/flagd-testbed";
if (!Strings.isBlank(feature)) {
container += "-" + feature;
}
container += ":v" + version;
return container;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import dev.openfeature.contrib.providers.flagd.Config;
import org.apache.logging.log4j.core.config.Order;
import org.junit.jupiter.api.parallel.Isolated;
import org.junit.platform.suite.api.BeforeSuite;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.ExcludeTags;
Expand All @@ -30,6 +31,7 @@
@IncludeTags("in-process")
@ExcludeTags({"unixsocket", "targetURI"})
@Testcontainers
@Isolated
public class RunInProcessTest {

@BeforeSuite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import dev.openfeature.contrib.providers.flagd.e2e.steps.FlagSteps;
import dev.openfeature.contrib.providers.flagd.e2e.steps.ProviderType;
import dev.openfeature.sdk.Client;
import dev.openfeature.sdk.FeatureProvider;
import dev.openfeature.sdk.FlagEvaluationDetails;
import dev.openfeature.sdk.MutableContext;
import java.util.LinkedList;
Expand All @@ -15,6 +16,7 @@
public class State {
public ProviderType providerType;
public Client client;
public FeatureProvider provider;
public List<Event> events = new LinkedList<>();
public Optional<Event> lastEvent;
public FlagSteps.Flag flag;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

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

abstract class AbstractSteps {
State state;
public abstract class AbstractSteps {
protected State state;

public AbstractSteps(State state) {
protected AbstractSteps(State state) {
this.state = state;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* This class modifies the internals of the environment variables map with reflection. Warning: If
* your {@link SecurityManager} does not allow modifications, it fails.
*/
class EnvironmentVariableUtils {
public class EnvironmentVariableUtils {

private EnvironmentVariableUtils() {
// private constructor to prevent instantiation of utility class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public EventSteps(State state) {
@Given("a {} event handler")
public void a_stale_event_handler(String eventType) {
state.client.on(mapEventType(eventType), eventDetails -> {
log.info("event tracked for {} ", eventType);
log.info("event tracked for {} at {} ms ", eventType, System.currentTimeMillis() % 100_000);
state.events.add(new Event(eventType, eventDetails));
});
}
Expand All @@ -47,24 +47,24 @@ public void a_stale_event_handler(String eventType) {

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

@Then("the {} event handler should have been executed")
public void eventHandlerShouldBeExecuted(String eventType) {
eventHandlerShouldBeExecutedWithin(eventType, 30000);
eventHandlerShouldBeExecutedWithin(eventType, 10000);
}

@Then("the {} event handler should have been executed within {int}ms")
public void eventHandlerShouldBeExecutedWithin(String eventType, int ms) {
log.info("waiting for eventtype: {}", eventType);
await().atMost(ms, MILLISECONDS)
await().alias("waiting for eventtype " + eventType)
.atMost(ms, MILLISECONDS)
.pollInterval(10, MILLISECONDS)
.until(() -> state.events.stream().anyMatch(event -> event.type.equals(eventType)));
state.lastEvent = state.events.stream()
.filter(event -> event.type.equals(eventType))
.findFirst();
state.events.removeIf(event -> event.type.equals(eventType));
state.events.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package dev.openfeature.contrib.providers.flagd.e2e.steps;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

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

@Then("the flag should be part of the event payload")
@Then("the flag was modified")
public void the_flag_was_modified() {
await().atMost(5000, MILLISECONDS).until(() -> state.events.stream()
.anyMatch(event -> event.type.equals("change")
&& event.details.getFlagsChanged().contains(state.flag.name)));
state.lastEvent = state.events.stream()
.filter(event -> event.type.equals("change")
&& event.details.getFlagsChanged().contains(state.flag.name))
.findFirst();
Event event = state.lastEvent.orElseThrow(AssertionError::new);
assertThat(event.details.getFlagsChanged()).contains(state.flag.name);
}

public class Flag {
Expand Down
Loading