io.opencensus.stats.StatsTestUtil.java Source code

Java tutorial

Introduction

Here is the source code for io.opencensus.stats.StatsTestUtil.java

Source

/*
 * Copyright 2017, Google Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.opencensus.stats;

import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.truth.Truth;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/** Stats test utilities. */
final class StatsTestUtil {

    private StatsTestUtil() {
    }

    static StatsContextImpl createContext(StatsContextFactoryImpl factory, TagKey key, TagValue value) {
        return createContext(factory, Tag.create(key, value));
    }

    static StatsContextImpl createContext(StatsContextFactoryImpl factory, TagKey key1, TagValue value1,
            TagKey key2, TagValue value2) {
        return createContext(factory, Tag.create(key1, value1), Tag.create(key2, value2));
    }

    /**
     * Creates a {@code StatsContextImpl} from a factory and a list tags.
     *
     * @param factory the factory used to produce the {@code StatsContextImpl}.
     * @param tags a list of tags to add to the {@code StatsContextImpl}.
     * @return a {@code StatsContextImpl} with the given tags.
     */
    private static StatsContextImpl createContext(StatsContextFactoryImpl factory, Tag... tags) {
        StatsContextImpl.Builder builder = factory.getDefault().builder();
        for (Tag tag : tags) {
            builder.set(tag.getKey(), tag.getValue());
        }
        return builder.build();
    }

    /**
     * Creates a {@code DistributionAggregate} by adding the given values to a new {@link
     * MutableDistribution} that has {@code BucketBoundaries}.
     *
     * @param tags the {@code DistributionAggregate}'s tags.
     * @param bucketBoundaries the bucket boundaries.
     * @param values the values to add to the distribution.
     * @return the new {@code DistributionAggregate}
     */
    static DistributionAggregate createDistributionAggregate(List<Tag> tags, BucketBoundaries bucketBoundaries,
            List<Double> values) {
        MutableDistribution mdist = MutableDistribution.create(bucketBoundaries);
        for (double value : values) {
            mdist.add(value);
        }
        MutableDistribution.Range range = mdist.getRange();
        return DistributionAggregate.create(mdist.getCount(), mdist.getMean(), mdist.getSum(),
                DistributionAggregate.Range.create(range.getMin(), range.getMax()), tags, mdist.getBucketCounts());
    }

    /**
     * Creates a {@code DistributionAggregate} by adding the given values to a new {@link
     * MutableDistribution} that does not have {@code BucketBoundaries}.
     *
     * @param tags the {@code DistributionAggregate}'s tags.
     * @param values the values to add to the distribution.
     * @return the new {@code DistributionAggregate}
     */
    static DistributionAggregate createDistributionAggregate(List<Tag> tags, List<Double> values) {
        MutableDistribution mdist = MutableDistribution.create();
        for (double value : values) {
            mdist.add(value);
        }
        MutableDistribution.Range range = mdist.getRange();
        return DistributionAggregate.create(mdist.getCount(), mdist.getMean(), mdist.getSum(),
                DistributionAggregate.Range.create(range.getMin(), range.getMax()), tags);
    }

    /**
     * Asserts that the two sets of {@code DistributionAggregate}s are equivalent, with a given
     * tolerance. The tolerance is used when comparing the mean and sum of values. The order of the
     * {@code DistributionAggregate}s has no effect. The expected parameter is last, because it is
     * likely to be a larger expression.
     *
     * @param tolerance the tolerance used for {@code double} comparison.
     * @param actual the actual test result.
     * @param expected the expected value.
     * @throws AssertionError if the {@code DistributionAggregate}s don't match.
     */
    static void assertDistributionAggregatesEquivalent(double tolerance, Collection<DistributionAggregate> actual,
            Collection<DistributionAggregate> expected) {
        Function<DistributionAggregate, List<Tag>> getTagsFunction = new Function<DistributionAggregate, List<Tag>>() {
            @Override
            public List<Tag> apply(DistributionAggregate agg) {
                return agg.getTags();
            }
        };
        Iterable<List<Tag>> expectedTags = Iterables.transform(expected, getTagsFunction);
        Iterable<List<Tag>> actualTags = Iterables.transform(actual, getTagsFunction);
        Truth.assertThat(actualTags).containsExactlyElementsIn(expectedTags);
        for (DistributionAggregate expectedAgg : expected) {
            DistributionAggregate actualAgg = Iterables.find(actual,
                    Predicates.compose(Predicates.equalTo(expectedAgg.getTags()), getTagsFunction));
            assertDistributionAggregateValuesEquivalent("DistributionAggregate tags=" + expectedAgg.getTags(),
                    tolerance, expectedAgg, actualAgg);
        }
    }

    private static void assertDistributionAggregateValuesEquivalent(String msg, double tolerance,
            DistributionAggregate agg1, DistributionAggregate agg2) {
        Truth.assertWithMessage(msg + " count").that(agg1.getCount()).isEqualTo(agg2.getCount());
        Truth.assertWithMessage(msg + " mean").that(agg1.getMean()).isWithin(tolerance).of(agg2.getMean());
        Truth.assertWithMessage(msg + " sum").that(agg1.getSum()).isWithin(tolerance).of(agg2.getSum());
        Truth.assertWithMessage(msg + " range").that(agg1.getRange()).isEqualTo(agg2.getRange());

        if (agg1.getBucketCounts() == null && agg2.getBucketCounts() == null) {
            return;
        } else {
            Truth.assertWithMessage(msg + " bucket counts").that(removeTrailingZeros(agg1.getBucketCounts()))
                    .isEqualTo(removeTrailingZeros(agg2.getBucketCounts()));
        }
    }

    private static List<Long> removeTrailingZeros(List<Long> longs) {
        if (longs == null) {
            return null;
        }
        List<Long> truncated = new ArrayList<Long>(longs);
        while (!truncated.isEmpty() && Iterables.getLast(truncated) == 0) {
            truncated.remove(truncated.size() - 1);
        }
        return truncated;
    }
}