Skip to content

Commit e66c02a

Browse files
authored
test(flagd): add envoy test (#1582)
Signed-off-by: Simon Schrottner <[email protected]>
1 parent 641576d commit e66c02a

File tree

10 files changed

+74
-146
lines changed

10 files changed

+74
-146
lines changed

providers/flagd/docker-compose.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Map;
2929
import java.util.function.Consumer;
3030
import lombok.extern.slf4j.Slf4j;
31+
import org.apache.commons.lang3.StringUtils;
3132

3233
/**
3334
* Resolves flag values using
@@ -204,7 +205,7 @@ private <T> ProviderEvaluation<T> resolve(Class<T> type, String key, EvaluationC
204205
// check variant existence
205206
Object value = flag.getVariants().get(resolvedVariant);
206207
if (value == null) {
207-
if (resolvedVariant.isEmpty() && flag.getDefaultVariant().isEmpty()) {
208+
if (StringUtils.isEmpty(resolvedVariant) && StringUtils.isEmpty(flag.getDefaultVariant())) {
208209
return ProviderEvaluation.<T>builder()
209210
.reason(Reason.ERROR.toString())
210211
.errorCode(ErrorCode.FLAG_NOT_FOUND)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package dev.openfeature.contrib.providers.flagd.e2e;
2+
3+
import dev.openfeature.contrib.providers.flagd.Config;
4+
import java.util.Optional;
5+
import org.testcontainers.containers.ComposeContainer;
6+
import org.testcontainers.containers.ContainerState;
7+
8+
public class ContainerUtil {
9+
public static int getPort(ComposeContainer container, Config.Resolver resolver) {
10+
Optional<ContainerState> flagd = container.getContainerByServiceName("flagd");
11+
12+
return flagd.map(containerState -> {
13+
switch (resolver) {
14+
case RPC:
15+
return containerState.getMappedPort(8013);
16+
case IN_PROCESS:
17+
return containerState.getMappedPort(8015);
18+
default:
19+
return 0;
20+
}
21+
})
22+
.orElseThrow(() -> new RuntimeException("Could not map port"));
23+
}
24+
25+
public static String getLaunchpadUrl(ComposeContainer container) {
26+
Optional<ContainerState> flagd = container.getContainerByServiceName("flagd");
27+
return flagd.map(containerState -> {
28+
return containerState.getHost() + ":" + containerState.getMappedPort(8080);
29+
})
30+
.orElseThrow(() -> new RuntimeException("Could not find launchpad url"));
31+
}
32+
}

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

Lines changed: 0 additions & 66 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps")
3030
@ConfigurationParameter(key = OBJECT_FACTORY_PROPERTY_NAME, value = "io.cucumber.picocontainer.PicoFactory")
3131
@IncludeTags("in-process")
32-
@ExcludeTags({"unixsocket", "targetURI"})
32+
@ExcludeTags({"unixsocket"})
3333
@Testcontainers
3434
@Isolated
3535
public class RunInProcessTest {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.contrib.providers.flagd.e2e.steps")
2929
@ConfigurationParameter(key = OBJECT_FACTORY_PROPERTY_NAME, value = "io.cucumber.picocontainer.PicoFactory")
3030
@IncludeTags({"rpc"})
31-
@ExcludeTags({"targetURI", "unixsocket"})
31+
@ExcludeTags({"unixsocket"})
3232
@Testcontainers
3333
public class RunRpcTest {
3434

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

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
import dev.openfeature.contrib.providers.flagd.Config;
66
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
77
import dev.openfeature.contrib.providers.flagd.FlagdProvider;
8-
import dev.openfeature.contrib.providers.flagd.e2e.FlagdContainer;
8+
import dev.openfeature.contrib.providers.flagd.e2e.ContainerUtil;
99
import dev.openfeature.contrib.providers.flagd.e2e.State;
1010
import dev.openfeature.sdk.FeatureProvider;
1111
import dev.openfeature.sdk.OpenFeatureAPI;
1212
import io.cucumber.java.After;
1313
import io.cucumber.java.AfterAll;
14-
import io.cucumber.java.Before;
1514
import io.cucumber.java.BeforeAll;
1615
import io.cucumber.java.en.Given;
1716
import io.cucumber.java.en.When;
@@ -20,18 +19,21 @@
2019
import java.nio.file.Files;
2120
import java.nio.file.Path;
2221
import java.nio.file.Paths;
22+
import java.time.Duration;
2323
import lombok.extern.slf4j.Slf4j;
2424
import org.apache.commons.lang3.RandomStringUtils;
25+
import org.apache.commons.lang3.StringUtils;
2526
import org.junit.jupiter.api.parallel.Isolated;
26-
import org.testcontainers.containers.BindMode;
27+
import org.testcontainers.containers.ComposeContainer;
28+
import org.testcontainers.containers.wait.strategy.Wait;
2729
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
2830

2931
@Isolated()
3032
@Slf4j
3133
public class ProviderSteps extends AbstractSteps {
3234

3335
public static final int UNAVAILABLE_PORT = 9999;
34-
static FlagdContainer container;
36+
static ComposeContainer container;
3537

3638
static Path sharedTempDir;
3739

@@ -43,8 +45,14 @@ public ProviderSteps(State state) {
4345
public static void beforeAll() throws IOException {
4446
sharedTempDir = Files.createDirectories(
4547
Paths.get("tmp/" + RandomStringUtils.randomAlphanumeric(8).toLowerCase() + "/"));
46-
container = new FlagdContainer()
47-
.withFileSystemBind(sharedTempDir.toAbsolutePath().toString(), "/flags", BindMode.READ_WRITE);
48+
container = new ComposeContainer(new File("test-harness/docker-compose.yaml"))
49+
.withEnv("FLAGS_DIR", sharedTempDir.toAbsolutePath().toString())
50+
.withExposedService("flagd", 8013, Wait.forListeningPort())
51+
.withExposedService("flagd", 8015, Wait.forListeningPort())
52+
.withExposedService("flagd", 8080, Wait.forListeningPort())
53+
.withExposedService("envoy", 9211, Wait.forListeningPort())
54+
.withStartupTimeout(Duration.ofSeconds(45));
55+
container.start();
4856
}
4957

5058
@AfterAll
@@ -53,17 +61,10 @@ public static void afterAll() throws IOException {
5361
FileUtils.deleteDirectory(sharedTempDir.toFile());
5462
}
5563

56-
@Before
57-
public void before() {
58-
if (!container.isRunning()) {
59-
container.start();
60-
}
61-
}
62-
6364
@After
6465
public void tearDown() {
6566
if (state.client != null) {
66-
when().post("http://" + container.getLaunchpadUrl() + "/stop")
67+
when().post("http://" + ContainerUtil.getLaunchpadUrl(container) + "/stop")
6768
.then()
6869
.statusCode(200);
6970
}
@@ -100,7 +101,7 @@ public void setupProvider(String providerType) throws InterruptedException {
100101
String absolutePath = file.getAbsolutePath();
101102
this.state.providerType = ProviderType.SSL;
102103
state.builder
103-
.port(container.getPort(State.resolverType))
104+
.port(ContainerUtil.getPort(container, State.resolverType))
104105
.tls(true)
105106
.certPath(absolutePath);
106107
flagdConfig = "ssl";
@@ -117,12 +118,12 @@ public void setupProvider(String providerType) throws InterruptedException {
117118
.port(UNAVAILABLE_PORT)
118119
.offlineFlagSourcePath(new File("test-harness/flags/" + replace).getAbsolutePath());
119120
} else {
120-
state.builder.port(container.getPort(State.resolverType));
121+
state.builder.port(ContainerUtil.getPort(container, State.resolverType));
121122
}
122123
break;
123124
case "syncpayload":
124125
flagdConfig = "sync-payload";
125-
state.builder.port(container.getPort(State.resolverType));
126+
state.builder.port(ContainerUtil.getPort(container, State.resolverType));
126127
break;
127128
case "stable":
128129
this.state.providerType = ProviderType.DEFAULT;
@@ -135,13 +136,22 @@ public void setupProvider(String providerType) throws InterruptedException {
135136
.toAbsolutePath()
136137
.toString());
137138
} else {
138-
state.builder.port(container.getPort(State.resolverType));
139+
state.builder.port(ContainerUtil.getPort(container, State.resolverType));
139140
}
140141
break;
141142
default:
142143
throw new IllegalStateException();
143144
}
144-
when().post("http://" + container.getLaunchpadUrl() + "/start?config={config}", flagdConfig)
145+
146+
// Setting TargetUri if this setting is set
147+
FlagdOptions tempBuild = state.builder.build();
148+
if (!StringUtils.isEmpty(tempBuild.getTargetUri())) {
149+
String replace = tempBuild.getTargetUri().replace("<port>", "" + container.getServicePort("envoy", 9211));
150+
state.builder.targetUri(replace);
151+
state.builder.port(UNAVAILABLE_PORT);
152+
}
153+
154+
when().post("http://" + ContainerUtil.getLaunchpadUrl(container) + "/start?config={config}", flagdConfig)
145155
.then()
146156
.statusCode(200);
147157

@@ -162,18 +172,22 @@ public void setupProvider(String providerType) throws InterruptedException {
162172

163173
@When("the connection is lost")
164174
public void the_connection_is_lost() {
165-
when().post("http://" + container.getLaunchpadUrl() + "/stop").then().statusCode(200);
175+
when().post("http://" + ContainerUtil.getLaunchpadUrl(container) + "/stop")
176+
.then()
177+
.statusCode(200);
166178
}
167179

168180
@When("the connection is lost for {int}s")
169181
public void the_connection_is_lost_for(int seconds) {
170-
when().post("http://" + container.getLaunchpadUrl() + "/restart?seconds={seconds}", seconds)
182+
when().post("http://" + ContainerUtil.getLaunchpadUrl(container) + "/restart?seconds={seconds}", seconds)
171183
.then()
172184
.statusCode(200);
173185
}
174186

175187
@When("the flag was modified")
176188
public void the_flag_was_modded() {
177-
when().post("http://" + container.getLaunchpadUrl() + "/change").then().statusCode(200);
189+
when().post("http://" + ContainerUtil.getLaunchpadUrl(container) + "/change")
190+
.then()
191+
.statusCode(200);
178192
}
179193
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public void we_have_an_option_of_type_with_value(String option, String type, Str
7171
.filter(method1 -> method1.getName().equals(mapOptionNames(option)))
7272
.findFirst()
7373
.orElseThrow(RuntimeException::new);
74+
7475
method.invoke(state.builder, converted);
7576
}
7677

providers/flagd/src/test/resources/envoy-config/envoy-custom.yaml

Lines changed: 0 additions & 49 deletions
This file was deleted.

providers/flagd/test-harness

0 commit comments

Comments
 (0)