Skip to content

Commit a66711a

Browse files
committed
Set variants on noop provider & add provider tests.
1 parent 60114b7 commit a66711a

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

lib/src/main/java/javasdk/NoOpProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class NoOpProvider implements FeatureProvider {
1010
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
1111
return ProviderEvaluation.<Boolean>builder()
1212
.value(defaultValue)
13+
.variant("Passed in default")
1314
.reason(Reason.DEFAULT)
1415
.build();
1516
}
@@ -18,6 +19,7 @@ public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defa
1819
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
1920
return ProviderEvaluation.<String>builder()
2021
.value(defaultValue)
22+
.variant("Passed in default")
2123
.reason(Reason.DEFAULT)
2224
.build();
2325
}
@@ -26,6 +28,7 @@ public ProviderEvaluation<String> getStringEvaluation(String key, String default
2628
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx, FlagEvaluationOptions options) {
2729
return ProviderEvaluation.<Integer>builder()
2830
.value(defaultValue)
31+
.variant("Passed in default")
2932
.reason(Reason.DEFAULT)
3033
.build();
3134
}

lib/src/test/java/javasdk/HookSpecTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ void finallyAfter(HookContext<Boolean> ctx, ImmutableMap<String, Object> hints)
389389
verify(hook, times(1)).error(any(), any(), any());
390390
verify(hook2, times(1)).error(any(), any(), any());
391391
}
392+
392393
@Specification(spec="hooks", number="1.4", text="The evaluation context MUST be mutable only within the before hook.")
393394
@Specification(spec="hooks", number="3.1", text="Hooks MUST specify at least one stage.")
394395
@Specification(spec="hooks", number="5.3", text="HookHints MUST be passed to each hook through a parameter. It is merged into the object in the precedence order API -> Client -> Invocation (last wins).")

lib/src/test/java/javasdk/ProviderSpecTests.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,88 @@
33
import org.junit.jupiter.api.Disabled;
44
import org.junit.jupiter.api.Test;
55

6+
import static org.junit.jupiter.api.Assertions.*;
7+
68
public class ProviderSpecTests {
9+
NoOpProvider p = new NoOpProvider();
10+
11+
@Specification(spec="provider", number="2.1", text="The provider interface MUST define a name field or accessor, " +
12+
"which identifies the provider implementation.")
13+
@Test void name_accessor() {
14+
assertNotNull(p.getName());
15+
}
16+
17+
@Specification(spec="provider", number="2.4", text="In cases of normal execution, the provider MUST populate the " +
18+
"flag resolution structure's value field with the resolved flag value.")
19+
@Specification(spec="provider", number="2.2", text="The feature provider interface MUST define methods to resolve " +
20+
"flag values, with parameters flag key (string, required), default value " +
21+
"(boolean | number | string | structure, required), evaluation context (optional), and " +
22+
"evaluation options (optional), which returns a flag resolution structure.")
23+
@Specification(spec="provider", number="2.9.1", text="The flag resolution structure SHOULD accept a generic " +
24+
"argument (or use an equivalent language feature) which indicates the type of the wrapped value field.")
25+
@Test void flag_value_set() {
26+
ProviderEvaluation<Integer> int_result = p.getIntegerEvaluation("key", 4, new EvaluationContext(), FlagEvaluationOptions.builder().build());
27+
assertNotNull(int_result.getValue());
28+
29+
ProviderEvaluation<String> string_result = p.getStringEvaluation("key", "works", new EvaluationContext(), FlagEvaluationOptions.builder().build());
30+
assertNotNull(string_result.getValue());
31+
32+
ProviderEvaluation<Boolean> boolean_result = p.getBooleanEvaluation("key", false, new EvaluationContext(), FlagEvaluationOptions.builder().build());
33+
assertNotNull(boolean_result.getValue());
34+
}
35+
36+
@Specification(spec="provider", number="2.6", text="The provider SHOULD populate the flag resolution structure's " +
37+
"reason field with a string indicating the semantic reason for the returned flag value.")
38+
@Test void has_reason() {
39+
ProviderEvaluation<Boolean> result = p.getBooleanEvaluation("key", false, new EvaluationContext(), FlagEvaluationOptions.builder().build());
40+
assertEquals(Reason.DEFAULT, result.getReason());
41+
}
42+
43+
@Specification(spec="provider", number="2.7", text="In cases of normal execution, the provider MUST NOT populate " +
44+
"the flag resolution structure's error code field, or otherwise must populate it with a null or falsy value.")
45+
@Test void no_error_code_by_default() {
46+
ProviderEvaluation<Boolean> result = p.getBooleanEvaluation("key", false, new EvaluationContext(), FlagEvaluationOptions.builder().build());
47+
assertNull(result.getErrorCode());
48+
}
49+
50+
@Specification(spec="provider", number="2.3.1", text="The feature provider interface MUST define methods for typed " +
51+
"flag resolution, including boolean, numeric, string, and structure.")
52+
@Disabled("Don't yet support structures") @Test void structure_validation() {
53+
54+
}
55+
56+
@Specification(spec="provider", number="2.8", text="In cases of abnormal execution, the provider MUST indicate an " +
57+
"error using the idioms of the implementation language, with an associated error code having possible " +
58+
"values PROVIDER_NOT_READY, FLAG_NOT_FOUND, PARSE_ERROR, TYPE_MISMATCH, or GENERAL.")
59+
@Disabled("I don't think we expect the provider to do all the exception catching.. right?")
60+
@Test void error_populates_error_code() {
61+
AlwaysBrokenProvider broken = new AlwaysBrokenProvider();
62+
ProviderEvaluation<Boolean> result = broken.getBooleanEvaluation("key", false, new EvaluationContext(), FlagEvaluationOptions.builder().build());
63+
assertEquals(ErrorCode.GENERAL, result.getErrorCode());
64+
}
65+
66+
@Specification(spec="provider", number="2.5", text="In cases of normal execution, the provider SHOULD populate the " +
67+
"flag resolution structure's variant field with a string identifier corresponding to the returned flag value.")
68+
@Test void variant_set() {
69+
ProviderEvaluation<Integer> int_result = p.getIntegerEvaluation("key", 4, new EvaluationContext(), FlagEvaluationOptions.builder().build());
70+
assertNotNull(int_result.getReason());
71+
72+
ProviderEvaluation<String> string_result = p.getStringEvaluation("key", "works", new EvaluationContext(), FlagEvaluationOptions.builder().build());
73+
assertNotNull(string_result.getReason());
74+
75+
ProviderEvaluation<Boolean> boolean_result = p.getBooleanEvaluation("key", false, new EvaluationContext(), FlagEvaluationOptions.builder().build());
76+
assertNotNull(boolean_result.getReason());
77+
}
78+
79+
@Specification(spec="provider", number="2.11.1", text="If the implementation includes a context transformer, the " +
80+
"provider SHOULD accept a generic argument (or use an equivalent language feature) indicating the type of " +
81+
"the transformed context. If such type information is supplied, more accurate type information can be " +
82+
"supplied in the flag resolution methods.")
83+
@Specification(spec="provider", number="2.10", text="The provider interface MAY define a context transformer method " +
84+
"or function, which can be optionally implemented in order to transform the evaluation context prior to " +
85+
"flag value resolution.")
86+
@Disabled("I don't think we should do that until we figure out the call signature differences")
87+
@Test void not_doing() {}
788
@Specification(spec="provider", number="2.1", text="The provider interface MUST define a name field or accessor, which identifies the provider implementation.")
889
@Specification(spec="provider", number="2.2", text="The feature provider interface MUST define methods to resolve flag values, with parameters flag key (string, required), default value (boolean | number | string | structure, required), evaluation context (optional), and evaluation options (optional), which returns a flag resolution structure.")
990
@Specification(spec="provider", number="2.3.1", text="The feature provider interface MUST define methods for typed flag resolution, including boolean, numeric, string, and structure.")

0 commit comments

Comments
 (0)