001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client.trace.hamcrest;
019
020import static org.hamcrest.Matchers.allOf;
021import static org.hamcrest.Matchers.equalTo;
022import static org.hamcrest.Matchers.hasProperty;
023import static org.hamcrest.Matchers.is;
024
025import io.opentelemetry.api.common.AttributeKey;
026import io.opentelemetry.api.common.Attributes;
027import java.util.Arrays;
028import org.hamcrest.Description;
029import org.hamcrest.Matcher;
030import org.hamcrest.TypeSafeMatcher;
031
032/**
033 * Helper methods for matching against instances of {@link io.opentelemetry.api.common.Attributes}.
034 */
035public final class AttributesMatchers {
036
037  private AttributesMatchers() {
038  }
039
040  public static <T> Matcher<Attributes> containsEntry(Matcher<AttributeKey<? super T>> keyMatcher,
041    Matcher<? super T> valueMatcher) {
042    return new IsAttributesContaining<>(keyMatcher, valueMatcher);
043  }
044
045  public static <T> Matcher<Attributes> containsEntry(AttributeKey<T> key, T value) {
046    return containsEntry(equalTo(key), equalTo(value));
047  }
048
049  public static <T> Matcher<Attributes> containsEntry(AttributeKey<T> key,
050    Matcher<? super T> matcher) {
051    return containsEntry(equalTo(key), matcher);
052  }
053
054  public static Matcher<Attributes> containsEntry(String key, String value) {
055    return containsEntry(AttributeKey.stringKey(key), value);
056  }
057
058  public static Matcher<Attributes> containsEntry(String key, long value) {
059    return containsEntry(AttributeKey.longKey(key), value);
060  }
061
062  public static Matcher<Attributes> containsEntryWithStringValuesOf(String key, String... values) {
063    return containsEntry(AttributeKey.stringArrayKey(key), Arrays.asList(values));
064  }
065
066  public static Matcher<Attributes> containsEntryWithStringValuesOf(String key,
067    Matcher<Iterable<? extends String>> matcher) {
068    return new IsAttributesContaining<>(equalTo(AttributeKey.stringArrayKey(key)), matcher);
069  }
070
071  public static Matcher<Attributes> isEmpty() {
072    return hasProperty("empty", is(true));
073  }
074
075  private static final class IsAttributesContaining<T> extends TypeSafeMatcher<Attributes> {
076    private final Matcher<AttributeKey<? super T>> keyMatcher;
077    private final Matcher<? super T> valueMatcher;
078
079    private IsAttributesContaining(final Matcher<AttributeKey<? super T>> keyMatcher,
080      final Matcher<? super T> valueMatcher) {
081      this.keyMatcher = keyMatcher;
082      this.valueMatcher = valueMatcher;
083    }
084
085    @Override
086    protected boolean matchesSafely(Attributes item) {
087      return item.asMap().entrySet().stream().anyMatch(
088        e -> allOf(hasProperty("key", keyMatcher), hasProperty("value", valueMatcher)).matches(e));
089    }
090
091    @Override
092    public void describeMismatchSafely(Attributes item, Description mismatchDescription) {
093      mismatchDescription.appendText("Attributes was ").appendValueList("[", ", ", "]",
094        item.asMap().entrySet());
095    }
096
097    @Override
098    public void describeTo(Description description) {
099      description.appendText("Attributes containing [").appendDescriptionOf(keyMatcher)
100        .appendText("->").appendDescriptionOf(valueMatcher).appendText("]");
101    }
102  }
103}