Skip to content
Open
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
3 changes: 3 additions & 0 deletions src/main/java/dev/openfeature/sdk/ImmutableContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public String getTargetingKey() {
@Override
public EvaluationContext merge(EvaluationContext overridingContext) {
if (overridingContext == null || overridingContext.isEmpty()) {
if (this.isEmpty()) {
return ImmutableContext.EMPTY;
}
return new ImmutableContext(this.asUnmodifiableMap());
}
if (this.isEmpty()) {
Expand Down
64 changes: 64 additions & 0 deletions src/test/java/dev/openfeature/sdk/ImmutableContextTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.openfeature.sdk;

import static dev.openfeature.sdk.EvaluationContext.TARGETING_KEY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
Expand Down Expand Up @@ -216,6 +217,69 @@ void immutableContextHashCodeIsStable() {
assertEquals(first, second);
}

@Nested
@DisplayName("ImmutableContext(String, Map) branch logic")
class ConstructorBranches {

@Test
@DisplayName("non-null targeting key with empty attributes is preserved")
void nonNullTargetingKeyWithEmptyAttributesIsPreserved() {
ImmutableContext ctx = new ImmutableContext("key", Collections.emptyMap());
assertThat(ctx.getTargetingKey()).isEqualTo("key");
assertThat(ctx.keySet()).contains(TARGETING_KEY);
}

@Test
@DisplayName("non-null targeting key with null attributes is preserved")
void nonNullTargetingKeyWithNullAttributesIsPreserved() {
ImmutableContext ctx = new ImmutableContext("key", null);
assertThat(ctx.getTargetingKey()).isEqualTo("key");
}

@Test
@DisplayName("null targeting key with empty attributes yields empty context")
void nullTargetingKeyWithEmptyAttributesYieldsEmptyContext() {
ImmutableContext ctx = new ImmutableContext((String) null, Collections.emptyMap());
assertThat(ctx.getTargetingKey()).isNull();
assertThat(ctx.isEmpty()).isTrue();
}
}

@Nested
@DisplayName("ImmutableContext.merge() empty short-circuit")
class MergeEmpty {

@Test
@DisplayName("merging two empty contexts returns the EMPTY singleton")
void mergingTwoEmptyContextsReturnsEmptySingleton() {
EvaluationContext result = new ImmutableContext().merge(new ImmutableContext());
assertThat(result).isSameAs(ImmutableContext.EMPTY);
}

@Test
@DisplayName("merging empty context with null returns the EMPTY singleton")
void mergingEmptyContextWithNullReturnsEmptySingleton() {
EvaluationContext result = new ImmutableContext().merge(null);
assertThat(result).isSameAs(ImmutableContext.EMPTY);
}

@Test
@DisplayName("merging non-empty context with null does not return EMPTY")
void mergingNonEmptyContextWithNullDoesNotReturnEmpty() {
EvaluationContext result = new ImmutableContext("key").merge(null);
assertThat(result).isNotSameAs(ImmutableContext.EMPTY);
assertThat(result.getTargetingKey()).isEqualTo("key");
}

@Test
@DisplayName("merging non-empty context with empty override does not return EMPTY")
void mergingNonEmptyContextWithEmptyOverrideDoesNotReturnEmpty() {
EvaluationContext result = new ImmutableContext("key").merge(new ImmutableContext());
assertThat(result).isNotSameAs(ImmutableContext.EMPTY);
assertThat(result.getTargetingKey()).isEqualTo("key");
}
}

@Nested
class Equals {
ImmutableContext ctx = new ImmutableContext("c", Map.of("a", new Value("b")));
Expand Down
Loading