Skip to content

Commit 9d48d28

Browse files
committed
Add test case for OF.7: empty targeting key is valid
OF.7 specifies that empty string shall be accepted as a targeting key and evaluation should proceed as normal. Changes: - Added test case in DDEvaluatorTest for empty targeting key - Modified TestCase utility to use a custom EvaluationContext wrapper that preserves empty targeting keys (OpenFeature SDK's MutableContext converts empty string to null, which breaks OF.7 compliance)
1 parent ebf18b1 commit 9d48d28

2 files changed

Lines changed: 47 additions & 8 deletions

File tree

products/feature-flagging/api/src/test/java/datadog/trace/api/openfeature/DDEvaluatorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ private static List<TestCase<?>> evaluateTestCases() {
213213
new TestCase<>("default")
214214
.flag("simple-string")
215215
.result(new Result<>("default").reason(ERROR.name()).errorCode(TARGETING_KEY_MISSING)),
216+
// OF.7: Empty string is a valid targeting key - evaluation should proceed as normal
217+
new TestCase<>("default")
218+
.flag("simple-string")
219+
.targetingKey("")
220+
.result(new Result<>("test-value").reason(TARGETING_MATCH.name()).variant("on")),
216221
new TestCase<>("default")
217222
.flag("non-existent-flag")
218223
.targetingKey("user-123")

products/feature-flagging/api/src/test/java/datadog/trace/api/openfeature/util/TestCase.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,53 @@
11
package datadog.trace.api.openfeature.util;
22

33
import dev.openfeature.sdk.ErrorCode;
4+
import dev.openfeature.sdk.EvaluationContext;
45
import dev.openfeature.sdk.MutableContext;
56
import dev.openfeature.sdk.Structure;
67
import dev.openfeature.sdk.Value;
78
import java.util.HashMap;
89
import java.util.List;
910
import java.util.Map;
11+
import java.util.Set;
1012

1113
public class TestCase<E> {
1214

1315
public Class<E> type;
1416
public String flag;
1517
public E defaultValue;
16-
public final MutableContext context = new MutableContext();
18+
private final MutableContext baseContext = new MutableContext();
19+
private String targetingKeyOverride;
20+
private boolean hasTargetingKeyOverride = false;
1721
public Result<E> result;
1822

23+
// Custom context wrapper that preserves empty targeting key (OF.7 compliance)
24+
public final EvaluationContext context = new EvaluationContext() {
25+
@Override
26+
public String getTargetingKey() {
27+
return hasTargetingKeyOverride ? targetingKeyOverride : baseContext.getTargetingKey();
28+
}
29+
30+
@Override
31+
public Value getValue(String key) {
32+
return baseContext.getValue(key);
33+
}
34+
35+
@Override
36+
public Set<String> keySet() {
37+
return baseContext.keySet();
38+
}
39+
40+
@Override
41+
public Map<String, Value> asMap() {
42+
return baseContext.asMap();
43+
}
44+
45+
@Override
46+
public Map<String, Object> asObjectMap() {
47+
return baseContext.asObjectMap();
48+
}
49+
};
50+
1951
@SuppressWarnings("unchecked")
2052
public TestCase(final E defaultValue) {
2153
this.type = (Class<E>) defaultValue.getClass();
@@ -28,37 +60,39 @@ public TestCase<E> flag(String flag) {
2860
}
2961

3062
public TestCase<E> targetingKey(final String targetingKey) {
31-
context.setTargetingKey(targetingKey);
63+
// Preserve the targeting key directly to support empty string (OF.7)
64+
this.targetingKeyOverride = targetingKey;
65+
this.hasTargetingKeyOverride = true;
3266
return this;
3367
}
3468

3569
public TestCase<E> context(final String key, final String value) {
36-
context.add(key, value);
70+
baseContext.add(key, value);
3771
return this;
3872
}
3973

4074
public TestCase<E> context(final String key, final Integer value) {
41-
context.add(key, value);
75+
baseContext.add(key, value);
4276
return this;
4377
}
4478

4579
public TestCase<E> context(final String key, final Double value) {
46-
context.add(key, value);
80+
baseContext.add(key, value);
4781
return this;
4882
}
4983

5084
public TestCase<E> context(final String key, final Boolean value) {
51-
context.add(key, value);
85+
baseContext.add(key, value);
5286
return this;
5387
}
5488

5589
public TestCase<E> context(final String key, final Structure value) {
56-
context.add(key, value);
90+
baseContext.add(key, value);
5791
return this;
5892
}
5993

6094
public TestCase<E> context(final String key, final List<Value> value) {
61-
context.add(key, value);
95+
baseContext.add(key, value);
6296
return this;
6397
}
6498

0 commit comments

Comments
 (0)