Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assertions refactoring #6

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
package io.opentelemetry.contrib.jmxscraper.assertions;

import java.util.Objects;
import javax.annotation.Nullable;

/** Implements functionality of matching data point attributes. */
public class AttributeMatcher {
private final String attributeName;
@Nullable
private final String attributeValue;
@Nullable private final String attributeValue;

/**
* Create instance used to match data point attribute with any value.
Expand All @@ -29,7 +29,7 @@ public class AttributeMatcher {
* @param attributeName attribute name
* @param attributeValue attribute value
*/
AttributeMatcher(String attributeName, String attributeValue) {
AttributeMatcher(String attributeName, @Nullable String attributeValue) {
this.attributeName = attributeName;
this.attributeValue = attributeValue;
}
Expand All @@ -43,24 +43,6 @@ public String getAttributeName() {
return attributeName;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AttributeMatcher)) {
return false;
}
AttributeMatcher other = (AttributeMatcher) o;
return Objects.equals(attributeName, other.attributeName);
}

@Override
public int hashCode() {
// Do not use value matcher here to support value wildcards
return Objects.hash(attributeName);
}

@Override
public String toString() {
return attributeValue == null
Expand All @@ -76,7 +58,7 @@ public String toString() {
* @return true if this matcher is matching provided value, false otherwise.
*/
boolean matchesValue(String value) {
if ((attributeValue == null) || (value == null)) {
if (attributeValue == null) {
SylvainJuge marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
return Objects.equals(attributeValue, value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxscraper.assertions;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;

/** Holder class for a set of attribute matchers */
public class AttributeMatcherSet {

// stored as a Map for easy lookup by name
private final Map<String, AttributeMatcher> matchers;

/**
* Constructor for a set of attribute matchers
*
* @param matchers collection of matchers to build a set from
* @throws IllegalStateException if there is any duplicate key
*/
AttributeMatcherSet(Collection<AttributeMatcher> matchers) {
this.matchers =
matchers.stream().collect(Collectors.toMap(AttributeMatcher::getAttributeName, m -> m));
}

Map<String, AttributeMatcher> getMatchers() {
return matchers;
}

@Override
public String toString() {
return matchers.values().toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
package io.opentelemetry.contrib.jmxscraper.assertions;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Utility class implementing convenience static methods to construct data point attribute matchers
Expand Down Expand Up @@ -46,15 +44,10 @@ public static AttributeMatcher attributeWithAnyValue(String name) {
* @return set of unique attribute matchers
* @throws IllegalArgumentException if provided list contains two or more matchers with the same
* name.
* @see MetricAssert#hasDataPointsWithAttributes(Set[]) for detailed description of the algorithm
* used for matching
* @see MetricAssert#hasDataPointsWithAttributes(AttributeMatcherSet...) for detailed description
* off the algorithm used for matching
*/
public static Set<AttributeMatcher> attributeSet(AttributeMatcher... attributes) {
Set<AttributeMatcher> matcherSet = Arrays.stream(attributes).collect(Collectors.toSet());
if (matcherSet.size() < attributes.length) {
throw new IllegalArgumentException(
"Duplicated matchers found in " + Arrays.toString(attributes));
}
return matcherSet;
public static AttributeMatcherSet attributeSet(AttributeMatcher... attributes) {
return new AttributeMatcherSet(Arrays.asList(attributes));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,9 @@ public final MetricAssert hasDataPointsWithOneAttribute(AttributeMatcher expecte
* @param attributeMatchers array of attribute matcher sets
* @return this
*/
@SafeVarargs
@CanIgnoreReturnValue
@SuppressWarnings("varargs") // required to avoid warning
public final MetricAssert hasDataPointsWithAttributes(
Set<AttributeMatcher>... attributeMatchers) {
public final MetricAssert hasDataPointsWithAttributes(AttributeMatcherSet... attributeMatchers) {
return checkDataPoints(
dataPoints -> {
dataPointsCommonCheck(dataPoints);
Expand Down Expand Up @@ -293,16 +291,37 @@ public final MetricAssert hasDataPointsWithAttributes(
}

private static boolean matchAttributes(
Set<AttributeMatcher> attributeMatchers, Map<String, String> dataPointAttributes) {
if (attributeMatchers.size() != dataPointAttributes.size()) {
return false;
}
for (AttributeMatcher matcher : attributeMatchers) {
String attributeValue = dataPointAttributes.get(matcher.getAttributeName());
if (!matcher.matchesValue(attributeValue)) {
AttributeMatcherSet attributeMatcherSet, Map<String, String> dataPointAttributes) {

Map<String, AttributeMatcher> matchers = attributeMatcherSet.getMatchers();

Set<String> toMatch = new HashSet<>(dataPointAttributes.keySet());
Set<String> matched = new HashSet<>();
for (Map.Entry<String, String> entry : dataPointAttributes.entrySet()) {
AttributeMatcher matcher = matchers.get(entry.getKey());
if (matcher == null) {
// no matcher for this key: unexpected key
return false;
}

String value = entry.getValue();
if (!matcher.matchesValue(value)) {
// value does not match: unexpected value
return false;
}
toMatch.remove(entry.getKey());
matched.add(entry.getKey());
}

if (!toMatch.isEmpty()) {
// unexpected entries in attributes
return false;
}
if (!matched.containsAll(matchers.keySet())) {
// some matchers were not match
return false;
}

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
import static io.opentelemetry.contrib.jmxscraper.assertions.DataPointAttributes.attributeSet;

import io.opentelemetry.contrib.jmxscraper.JmxScraperContainer;
import io.opentelemetry.contrib.jmxscraper.assertions.AttributeMatcher;
import io.opentelemetry.contrib.jmxscraper.assertions.AttributeMatcherSet;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Set;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;

Expand Down Expand Up @@ -184,7 +183,7 @@ protected MetricsVerifier createMetricsVerifier() {
errorCountAttributes("Write", "Unavailable")));
}

private static Set<AttributeMatcher> errorCountAttributes(String operation, String status) {
private static AttributeMatcherSet errorCountAttributes(String operation, String status) {
return attributeSet(attribute("operation", operation), attribute("status", status));
}
}