Skip to content

Commit

Permalink
Adjustment of behaviour of hasXAttributesSatisfying and hasXAttribute… (
Browse files Browse the repository at this point in the history
#4882)

* Adjustment of behaviour of hasXAttributesSatisfying and hasXAttributesSatisfyingExactly assertions

* Cleanup

* Additional test coverage for new assertion method

* Added javadoc on assertions

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
  • Loading branch information
lmonkiewicz and trask committed Nov 29, 2022
1 parent e79aad8 commit ac2ba4a
Show file tree
Hide file tree
Showing 12 changed files with 460 additions and 37 deletions.
23 changes: 22 additions & 1 deletion docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt
@@ -1,2 +1,23 @@
Comparing source compatibility of against
No changes.
*** MODIFIED CLASS: PUBLIC ABSTRACT io.opentelemetry.sdk.testing.assertj.AbstractPointAssert (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.AbstractPointAssert hasAttributesSatisfyingExactly(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.AbstractPointAssert hasAttributesSatisfyingExactly(java.lang.Iterable)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.DoubleExemplarAssert (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.DoubleExemplarAssert hasFilteredAttributesSatisfyingExactly(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.DoubleExemplarAssert hasFilteredAttributesSatisfyingExactly(java.lang.Iterable)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.EventDataAssert (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EventDataAssert hasAttributesSatisfying(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EventDataAssert hasAttributesSatisfying(java.lang.Iterable)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EventDataAssert hasAttributesSatisfyingExactly(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.EventDataAssert hasAttributesSatisfyingExactly(java.lang.Iterable)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.LongExemplarAssert (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.LongExemplarAssert hasFilteredAttributesSatisfyingExactly(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.LongExemplarAssert hasFilteredAttributesSatisfyingExactly(java.lang.Iterable)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.SpanDataAssert (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.SpanDataAssert hasAttributesSatisfying(io.opentelemetry.sdk.testing.assertj.AttributeAssertion[])
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.SpanDataAssert hasAttributesSatisfying(java.lang.Iterable)
Expand Up @@ -15,6 +15,7 @@
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Consumer;
import org.assertj.core.api.AbstractAssert;
Expand Down Expand Up @@ -160,6 +161,45 @@ public LogRecordDataAssert hasAttributesSatisfying(Consumer<Attributes> attribut
return this;
}

/**
* Asserts the log has attributes matching all {@code assertions}. Assertions can be created using
* methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LogRecordDataAssert hasAttributesSatisfying(AttributeAssertion... assertions) {
return hasAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the log has attributes matching all {@code assertions}. Assertions can be created using
* methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LogRecordDataAssert hasAttributesSatisfying(Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getAttributes(), assertions);
return myself;
}

/**
* Asserts the log has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LogRecordDataAssert hasAttributesSatisfyingExactly(AttributeAssertion... assertions) {
return hasAttributesSatisfyingExactly(Arrays.asList(assertions));
}

/**
* Asserts the log has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LogRecordDataAssert hasAttributesSatisfyingExactly(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributesExactly(actual.getAttributes(), assertions);
return myself;
}

private boolean attributesAreEqual(Attributes attributes) {
// compare as maps, since implementations do not have equals that work correctly across
// implementations.
Expand Down
Expand Up @@ -8,6 +8,7 @@
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.sdk.testing.assertj.LogAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import io.opentelemetry.api.common.AttributeKey;
Expand Down Expand Up @@ -111,6 +112,18 @@ void passing() {
attributeEntry("conditions", false, true),
attributeEntry("scores", 0L, 1L),
attributeEntry("coins", 0.01, 0.05, 0.1)))
.hasAttributesSatisfying(
equalTo(AttributeKey.stringKey("bear"), "mya"),
equalTo(AttributeKey.booleanArrayKey("conditions"), Arrays.asList(false, true)))
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("bear"), "mya"),
equalTo(AttributeKey.booleanKey("warm"), true),
equalTo(AttributeKey.longKey("temperature"), 30L),
equalTo(AttributeKey.doubleKey("length"), 1.2),
equalTo(AttributeKey.stringArrayKey("colors"), Arrays.asList("red", "blue")),
equalTo(AttributeKey.booleanArrayKey("conditions"), Arrays.asList(false, true)),
equalTo(AttributeKey.longArrayKey("scores"), Arrays.asList(0L, 1L)),
equalTo(AttributeKey.doubleArrayKey("coins"), Arrays.asList(0.01, 0.05, 0.1)))
.hasTotalAttributeCount(999);
}

Expand Down Expand Up @@ -181,6 +194,20 @@ void failure() {
AttributeKey.stringKey("bear"),
value -> assertThat(value).hasSize(2))))
.isInstanceOf(AssertionError.class);
assertThatThrownBy(
() ->
assertThat(LOG_DATA)
.hasAttributesSatisfying(equalTo(AttributeKey.stringKey("bear"), "moo")))
.isInstanceOf(AssertionError.class);
assertThatThrownBy(
() ->
assertThat(LOG_DATA)
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("bear"), "mya"),
equalTo(AttributeKey.booleanKey("warm"), true),
equalTo(AttributeKey.longKey("temperature"), 30L),
equalTo(AttributeKey.doubleKey("length"), 1.2)))
.isInstanceOf(AssertionError.class);
assertThatThrownBy(() -> assertThat(LOG_DATA).hasTotalAttributeCount(11))
.isInstanceOf(AssertionError.class);
}
Expand Down
Expand Up @@ -93,21 +93,41 @@ public final PointAssertT hasAttributes(Map.Entry<? extends AttributeKey<?>, ?>.
}

/**
* Asserts the point has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* Asserts the point has attributes matching all {@code assertions}. Assertions can be created
* using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public final PointAssertT hasAttributesSatisfying(AttributeAssertion... assertions) {
return hasAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the point has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* Asserts the point has attributes matching all {@code assertions}. Assertions can be created
* using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public final PointAssertT hasAttributesSatisfying(Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getAttributes(), assertions);
return myself;
}

/**
* Asserts the point has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public final PointAssertT hasAttributesSatisfyingExactly(AttributeAssertion... assertions) {
return hasAttributesSatisfyingExactly(Arrays.asList(assertions));
}

/**
* Asserts the point has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public final PointAssertT hasAttributesSatisfyingExactly(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributesExactly(actual.getAttributes(), assertions);
return myself;
}
}
Expand Up @@ -34,6 +34,32 @@ static <T, U extends AbstractAssert<U, T>> Consumer<T>[] toConsumers(
}

static void assertAttributes(Attributes actual, Iterable<AttributeAssertion> assertions) {
assertAttributes(actual, assertions, "attribute keys");
}

static void assertAttributes(
Attributes actual, Iterable<AttributeAssertion> assertions, String name) {
Set<AttributeKey<?>> actualKeys = actual.asMap().keySet();
Set<AttributeKey<?>> checkedKeys = new HashSet<>();
for (AttributeAssertion attributeAssertion : assertions) {
AttributeKey<?> key = attributeAssertion.getKey();
Object value = actual.get(key);
if (value != null) {
checkedKeys.add(key);
}
AbstractAssert<?, ?> assertion = AttributeAssertion.attributeValueAssertion(key, value);
attributeAssertion.getAssertion().accept(assertion);
}

assertThat(actualKeys).as(name).containsAll(checkedKeys);
}

static void assertAttributesExactly(Attributes actual, Iterable<AttributeAssertion> assertions) {
assertAttributesExactly(actual, assertions, "attribute keys");
}

static void assertAttributesExactly(
Attributes actual, Iterable<AttributeAssertion> assertions, String name) {
Set<AttributeKey<?>> actualKeys = actual.asMap().keySet();
Set<AttributeKey<?>> checkedKeys = new HashSet<>();
for (AttributeAssertion attributeAssertion : assertions) {
Expand All @@ -46,7 +72,7 @@ static void assertAttributes(Attributes actual, Iterable<AttributeAssertion> ass
attributeAssertion.getAssertion().accept(assertion);
}

assertThat(actualKeys).as("attribute keys").containsExactlyInAnyOrderElementsOf(checkedKeys);
assertThat(actualKeys).as(name).containsExactlyInAnyOrderElementsOf(checkedKeys);
}

/**
Expand Down
Expand Up @@ -97,19 +97,44 @@ public final DoubleExemplarAssert hasFilteredAttributes(
return hasFilteredAttributes(attributes);
}

/** Asserts the exemplar has filtered attributes matching all {@code assertions} and no more. */
/**
* Asserts the exemplar has filtered attributes matching all {@code assertions}. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public DoubleExemplarAssert hasFilteredAttributesSatisfying(AttributeAssertion... assertions) {
return hasFilteredAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions}. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public DoubleExemplarAssert hasFilteredAttributesSatisfying(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getFilteredAttributes(), assertions);
return myself;
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions} and no more.
* Assertions can be created using methods like {@link
* OpenTelemetryAssertions#satisfies(AttributeKey, OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public DoubleExemplarAssert hasFilteredAttributesSatisfying(
public DoubleExemplarAssert hasFilteredAttributesSatisfyingExactly(
AttributeAssertion... assertions) {
return hasFilteredAttributesSatisfyingExactly(Arrays.asList(assertions));
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions} and no more.
* Assertions can be created using methods like {@link
* OpenTelemetryAssertions#satisfies(AttributeKey, OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public DoubleExemplarAssert hasFilteredAttributesSatisfyingExactly(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getFilteredAttributes(), assertions);
AssertUtil.assertAttributesExactly(actual.getFilteredAttributes(), assertions);
return myself;
}
}
Expand Up @@ -7,9 +7,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.trace.data.EventData;
import java.time.Instant;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -82,4 +84,42 @@ public EventDataAssert hasAttributesSatisfying(Consumer<Attributes> attributes)
assertThat(actual.getAttributes()).as("attributes").satisfies(attributes);
return this;
}

/**
* Asserts the event has attributes matching all {@code assertions}. Assertions can be created
* using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public EventDataAssert hasAttributesSatisfying(AttributeAssertion... assertions) {
return hasAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the event has attributes matching all {@code assertions}. Assertions can be created
* using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public EventDataAssert hasAttributesSatisfying(Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getAttributes(), assertions);
return this;
}

/**
* Asserts the event has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public EventDataAssert hasAttributesSatisfyingExactly(AttributeAssertion... assertions) {
return hasAttributesSatisfyingExactly(Arrays.asList(assertions));
}

/**
* Asserts the event has attributes matching all {@code assertions} and no more. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public EventDataAssert hasAttributesSatisfyingExactly(Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributesExactly(actual.getAttributes(), assertions);
return this;
}
}
Expand Up @@ -96,19 +96,44 @@ public final LongExemplarAssert hasFilteredAttributes(
return hasFilteredAttributes(attributes);
}

/** Asserts the exemplar has filtered attributes matching all {@code assertions} and no more. */
/**
* Asserts the exemplar has filtered attributes matching all {@code assertions}. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LongExemplarAssert hasFilteredAttributesSatisfying(AttributeAssertion... assertions) {
return hasFilteredAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions}. Assertions can be
* created using methods like {@link OpenTelemetryAssertions#satisfies(AttributeKey,
* OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LongExemplarAssert hasFilteredAttributesSatisfying(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getFilteredAttributes(), assertions);
return myself;
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions} and no more.
* Assertions can be created using methods like {@link
* OpenTelemetryAssertions#satisfies(AttributeKey, OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LongExemplarAssert hasFilteredAttributesSatisfyingExactly(
AttributeAssertion... assertions) {
return hasFilteredAttributesSatisfying(Arrays.asList(assertions));
}

/**
* Asserts the exemplar has filtered attributes matching all {@code assertions} and no more.
* Assertions can be created using methods like {@link
* OpenTelemetryAssertions#satisfies(AttributeKey, OpenTelemetryAssertions.LongAssertConsumer)}.
*/
public LongExemplarAssert hasFilteredAttributesSatisfying(
public LongExemplarAssert hasFilteredAttributesSatisfyingExactly(
Iterable<AttributeAssertion> assertions) {
AssertUtil.assertAttributes(actual.getFilteredAttributes(), assertions);
AssertUtil.assertAttributesExactly(actual.getFilteredAttributes(), assertions);
return myself;
}
}

0 comments on commit ac2ba4a

Please sign in to comment.