Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AbstractThrowableAssert;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -153,6 +151,48 @@ public SELF hasAnyKeyValues() {
return (SELF) this;
}

public SELF hasKeyValuesCount(int size) {
isNotNull();
long actualSize = this.actual.getAllKeyValues().stream().count();
if (actualSize != size) {
failWithMessage("Observation expected to have <%s> keys but has <%s>.", size, actualSize);
}
return (SELF) this;
}

private List<String> allKeys() {
List<String> result = lowCardinalityKeys();
result.addAll(highCardinalityKeys());
return result;
}

public SELF hasOnlyKeys(String... keys) {
isNotNull();
Set<String> actualKeys = new LinkedHashSet<>(allKeys());
List<String> expectedKeys = Arrays.asList(keys);
boolean sameContent = actualKeys.containsAll(expectedKeys) && actualKeys.size() == expectedKeys.size();

if (!sameContent) {
Set<String> extraKeys = new LinkedHashSet<>(actualKeys);
extraKeys.removeAll(expectedKeys);

Set<String> missingKeys = new LinkedHashSet<>(expectedKeys);
missingKeys.removeAll(actualKeys);

if (!extraKeys.isEmpty() && !missingKeys.isEmpty()) {
failWithMessage("Observation has unexpected keys %s and misses expected keys %s.", extraKeys,
missingKeys);
}
else if (!extraKeys.isEmpty()) {
failWithMessage("Observation has unexpected keys %s.", extraKeys);
}
else {
failWithMessage("Observation is missing expected keys %s.", missingKeys);
}
}
return (SELF) this;
}

private List<String> lowCardinalityKeys() {
return this.actual.getLowCardinalityKeyValues().stream().map(KeyValue::getKey).collect(Collectors.toList());
}
Expand Down Expand Up @@ -194,7 +234,6 @@ public SELF doesNotHaveLowCardinalityKeyValueWithKey(String key) {

public SELF doesNotHaveLowCardinalityKeyValue(String key, String value) {
isNotNull();
doesNotHaveLowCardinalityKeyValueWithKey(key);
Optional<KeyValue> optional = this.actual.getLowCardinalityKeyValues().stream()
.filter(tag -> tag.getKey().equals(key)).findFirst();
if (!optional.isPresent()) {
Expand Down Expand Up @@ -241,7 +280,6 @@ public SELF doesNotHaveHighCardinalityKeyValueWithKey(String key) {

public SELF doesNotHaveHighCardinalityKeyValue(String key, String value) {
isNotNull();
doesNotHaveHighCardinalityKeyValueWithKey(key);
Optional<KeyValue> optional = this.actual.getHighCardinalityKeyValues().stream()
.filter(tag -> tag.getKey().equals(key)).findFirst();
if (!optional.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,75 @@ void should_throw_exception_when_contextual_name_ignore_case_correct() {
.isInstanceOf(AssertionError.class);
}

@Test
void should_not_throw_exception_when_key_count_matches() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("low", "foo");
observation.highCardinalityKeyValue("high", "bar");

thenNoException().isThrownBy(() -> assertThat(context).hasKeyValuesCount(2));
}

@Test
void should_throw_exception_when_key_count_differs() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("low", "foo");
observation.highCardinalityKeyValue("high", "bar");

thenThrownBy(() -> assertThat(context).hasKeyValuesCount(1)).isInstanceOf(AssertionError.class)
.hasMessage("Observation expected to have <1> keys but has <2>.");

thenThrownBy(() -> assertThat(context).hasKeyValuesCount(3)).isInstanceOf(AssertionError.class)
.hasMessage("Observation expected to have <3> keys but has <2>.");
}

@Test
void should_not_throw_exception_when_keys_match() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("low", "foo");
observation.highCardinalityKeyValue("high", "bar");

thenNoException().isThrownBy(() -> ObservationContextAssert.assertThat(context).hasOnlyKeys("low", "high"));
}

@Test
void should_throw_exception_when_keys_missing() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("found", "foo");

thenThrownBy(() -> ObservationContextAssert.assertThat(context).hasOnlyKeys("found", "low", "high"))
.isInstanceOf(AssertionError.class).hasMessage("Observation is missing expected keys [low, high].");
}

@Test
void should_throw_exception_when_keys_extras() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("found", "foo");
observation.lowCardinalityKeyValue("low", "foo");
observation.highCardinalityKeyValue("high", "foo");

thenThrownBy(() -> ObservationContextAssert.assertThat(context).hasOnlyKeys("found"))
.isInstanceOf(AssertionError.class).hasMessage("Observation has unexpected keys [low, high].");
}

@Test
void should_throw_exception_when_keys_both_missing_and_extras() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("found", "foo");
observation.lowCardinalityKeyValue("low", "foo");
observation.highCardinalityKeyValue("high", "foo");

thenThrownBy(() -> ObservationContextAssert.assertThat(context).hasOnlyKeys("notfound", "found"))
.isInstanceOf(AssertionError.class)
.hasMessage("Observation has unexpected keys [low, high] and misses expected keys [notfound].");
}

@Test
void should_not_throw_exception_when_low_cardinality_tag_exists() {
registry.observationConfig().observationHandler(c -> true);
Expand Down Expand Up @@ -202,11 +271,35 @@ void should_throw_exception_when_high_cardinality_tag_present() {
.isInstanceOf(AssertionError.class);
}

@Test
void should_not_throw_exception_when_high_cardinality_tag_present_with_other_value() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.highCardinalityKeyValue("foo", "other");

thenNoException().isThrownBy(() -> assertThat(context).doesNotHaveHighCardinalityKeyValue("foo", "bar"));

thenThrownBy(() -> assertThat(context).doesNotHaveHighCardinalityKeyValueWithKey("foo"))
.isInstanceOf(AssertionError.class);
}

@Test
void should_not_throw_exception_when_low_cardinality_tag_missing() {
thenNoException().isThrownBy(() -> assertThat(context).doesNotHaveLowCardinalityKeyValue("foo", "bar"));
}

@Test
void should_not_throw_exception_when_low_cardinality_tag_present_with_other_value() {
registry.observationConfig().observationHandler(c -> true);
Observation observation = Observation.start("foo", context, registry);
observation.lowCardinalityKeyValue("foo", "other");

thenNoException().isThrownBy(() -> assertThat(context).doesNotHaveLowCardinalityKeyValue("foo", "bar"));

thenThrownBy(() -> assertThat(context).doesNotHaveLowCardinalityKeyValueWithKey("foo"))
.isInstanceOf(AssertionError.class);
}

@Test
void should_throw_exception_when_low_cardinality_tag_present() {
registry.observationConfig().observationHandler(c -> true);
Expand Down