diff --git a/README.md b/README.md
index ae7a9fa..a12058b 100644
--- a/README.md
+++ b/README.md
@@ -86,7 +86,7 @@ Add the Featurevisor Java SDK as a dependency with your desired version:
com.featurevisor
featurevisor-java
- 4.0.0
+ 4.1.0
```
@@ -901,7 +901,7 @@ Add the provider with the same version as the Featurevisor Java SDK:
com.featurevisor
featurevisor-openfeature
- 4.0.0
+ 4.1.0
```
@@ -973,7 +973,7 @@ $ make verify-artifacts
### Releasing
1. Merge the release changes into `main`.
-2. Tag the release with a `v` prefix, such as `v4.0.0`, and push the tag.
+2. Tag the release with a `v` prefix, such as `v4.1.0`, and push the tag.
3. GitHub Actions verifies and publishes the parent POM, Java SDK, and OpenFeature provider to [GitHub Packages](https://github.com/orgs/featurevisor/packages?repo_name=featurevisor-java).
4. Create the corresponding [GitHub release](https://github.com/featurevisor/featurevisor-java/releases).
diff --git a/featurevisor-sdk/src/main/java/com/featurevisor/cli/CLI.java b/featurevisor-sdk/src/main/java/com/featurevisor/cli/CLI.java
index 73b594a..6209184 100644
--- a/featurevisor-sdk/src/main/java/com/featurevisor/cli/CLI.java
+++ b/featurevisor-sdk/src/main/java/com/featurevisor/cli/CLI.java
@@ -34,7 +34,7 @@
@Command(
name = "featurevisor",
mixinStandardHelpOptions = true,
- version = "4.0.0",
+ version = "4.1.0",
description = "Featurevisor Java Library CLI - Test runner, benchmark, and distribution assessment"
)
public class CLI implements Runnable {
@@ -209,14 +209,13 @@ String selectDatafileKeyForAssertion(Map assertion, Map assertion, String featureKey,
@SuppressWarnings("unchecked")
Map childContext = (Map) child.getOrDefault("context", new HashMap<>());
com.featurevisor.sdk.ChildInstance childF = spawn(f, childContext);
- TestResult childResult = testFeature(child, featureKey, childF, level);
+ TestResult childResult;
+ try {
+ childResult = testFeature(child, featureKey, childF, level);
+ } finally {
+ childF.close();
+ }
duration += childResult.duration;
hasError = hasError || childResult.hasError;
@@ -538,19 +542,17 @@ private TestResult testFeature(Map assertion, String featureKey,
private TestResult testGlobalVariable(Map assertion, String variableKey, Featurevisor f) {
@SuppressWarnings("unchecked") Map context = (Map) assertion.getOrDefault("context", new HashMap<>());
- @SuppressWarnings("unchecked") Map stickyVariables = (Map) assertion.getOrDefault("stickyVariables", new HashMap<>());
f.setContext(context, true);
- f.setStickyVariables(stickyVariables, true);
Featurevisor.OverrideOptions options = new Featurevisor.OverrideOptions();
if (assertion.containsKey("defaultVariableValue")) options.setDefaultVariableValue(assertion.get("defaultVariableValue"));
long startTime = System.nanoTime();
- Evaluation evaluation = f.evaluateVariable(variableKey, context, options);
+ Evaluation evaluation = f.evaluateVariable(variableKey, new HashMap<>(), options);
boolean hasError = false;
StringBuilder errors = new StringBuilder();
if (assertion.containsKey("expectedValue") && !Objects.equals(assertion.get("expectedValue"), evaluation.getVariableValue())) {
hasError = true;
- errors.append(" ✘ expectedValue: expected ").append(assertion.get("expectedValue"))
- .append(" but received ").append(evaluation.getVariableValue()).append("\n");
+ errors.append(" ✘ expectedValue: expected ").append(formatTestValue(assertion.get("expectedValue")))
+ .append(" but received ").append(formatTestValue(evaluation.getVariableValue())).append("\n");
}
if (assertion.containsKey("expectedEvaluation")) {
@SuppressWarnings("unchecked") Map expected = (Map) assertion.get("expectedEvaluation");
@@ -559,13 +561,94 @@ private TestResult testGlobalVariable(Map assertion, String vari
if (!Objects.equals(entry.getValue(), actual)) {
hasError = true;
errors.append(" ✘ expectedEvaluation.").append(entry.getKey()).append(": expected ")
- .append(entry.getValue()).append(" but received ").append(actual).append("\n");
+ .append(formatTestValue(entry.getValue())).append(" but received ").append(formatTestValue(actual)).append("\n");
+ }
+ }
+ }
+ if (assertion.containsKey("children")) {
+ @SuppressWarnings("unchecked") List