io.opencensus.implcore.stats.StatsTestUtil.java Source code

Java tutorial

Introduction

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

Source

/*
 * Copyright 2017, OpenCensus Authors
 *
 * 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.implcore.stats;

import static com.google.common.truth.Truth.assertThat;
import static io.opencensus.implcore.stats.MutableViewData.ZERO_TIMESTAMP;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import io.opencensus.common.Function;
import io.opencensus.common.Functions;
import io.opencensus.common.Timestamp;
import io.opencensus.metrics.data.AttachmentValue;
import io.opencensus.stats.Aggregation;
import io.opencensus.stats.AggregationData;
import io.opencensus.stats.AggregationData.CountData;
import io.opencensus.stats.AggregationData.DistributionData;
import io.opencensus.stats.AggregationData.LastValueDataDouble;
import io.opencensus.stats.AggregationData.LastValueDataLong;
import io.opencensus.stats.AggregationData.MeanData;
import io.opencensus.stats.AggregationData.SumDataDouble;
import io.opencensus.stats.AggregationData.SumDataLong;
import io.opencensus.stats.Measure;
import io.opencensus.stats.View;
import io.opencensus.stats.ViewData;
import io.opencensus.stats.ViewData.AggregationWindowData;
import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData;
import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData;
import io.opencensus.tags.Tag;
import io.opencensus.tags.TagContext;
import io.opencensus.tags.TagValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;

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

    private static final Timestamp EMPTY = Timestamp.create(0, 0);

    private StatsTestUtil() {
    }

    /**
     * Creates an {@link AggregationData} by adding the given sequence of values, based on the
     * definition of the given {@link Aggregation}.
     *
     * @param aggregation the {@code Aggregation} to apply the values to.
     * @param values the values to add to the {@code MutableAggregation}s.
     * @return an {@code AggregationData}.
     */
    static AggregationData createAggregationData(Aggregation aggregation, Measure measure, double... values) {
        MutableAggregation mutableAggregation = RecordUtils.createMutableAggregation(aggregation, measure);
        for (double value : values) {
            mutableAggregation.add(value, Collections.<String, AttachmentValue>emptyMap(), EMPTY);
        }
        return mutableAggregation.toAggregationData();
    }

    /**
     * Compare the actual and expected AggregationMap within the given tolerance.
     *
     * @param expected the expected map.
     * @param actual the actual mapping from {@code List<TagValue>} to {@code AggregationData}.
     * @param tolerance the tolerance used for {@code double} comparison.
     */
    static void assertAggregationMapEquals(
            Map<? extends List<? extends TagValue>, ? extends AggregationData> actual,
            Map<? extends List<? extends TagValue>, ? extends AggregationData> expected, double tolerance) {
        assertThat(actual.keySet()).containsExactlyElementsIn(expected.keySet());
        for (Entry<? extends List<? extends TagValue>, ? extends AggregationData> entry : actual.entrySet()) {
            assertAggregationDataEquals(expected.get(entry.getKey()), entry.getValue(), tolerance);
        }
    }

    /**
     * Compare the expected and actual {@code AggregationData} within the given tolerance.
     *
     * @param expected the expected {@code AggregationData}.
     * @param actual the actual {@code AggregationData}.
     * @param tolerance the tolerance used for {@code double} comparison.
     */
    static void assertAggregationDataEquals(AggregationData expected, final AggregationData actual,
            final double tolerance) {
        expected.match(new Function<SumDataDouble, Void>() {
            @Override
            public Void apply(SumDataDouble arg) {
                assertThat(actual).isInstanceOf(SumDataDouble.class);
                assertThat(((SumDataDouble) actual).getSum()).isWithin(tolerance).of(arg.getSum());
                return null;
            }
        }, new Function<SumDataLong, Void>() {
            @Override
            public Void apply(SumDataLong arg) {
                assertThat(actual).isInstanceOf(SumDataLong.class);
                assertThat(((SumDataLong) actual).getSum()).isEqualTo(arg.getSum());
                return null;
            }
        }, new Function<CountData, Void>() {
            @Override
            public Void apply(CountData arg) {
                assertThat(actual).isInstanceOf(CountData.class);
                assertThat(((CountData) actual).getCount()).isEqualTo(arg.getCount());
                return null;
            }
        }, new Function<DistributionData, Void>() {
            @Override
            public Void apply(DistributionData arg) {
                assertThat(actual).isInstanceOf(DistributionData.class);
                assertDistributionDataEquals(arg, (DistributionData) actual, tolerance);
                return null;
            }
        }, new Function<LastValueDataDouble, Void>() {
            @Override
            public Void apply(LastValueDataDouble arg) {
                assertThat(actual).isInstanceOf(LastValueDataDouble.class);
                assertThat(((LastValueDataDouble) actual).getLastValue()).isWithin(tolerance)
                        .of(arg.getLastValue());
                return null;
            }
        }, new Function<LastValueDataLong, Void>() {
            @Override
            public Void apply(LastValueDataLong arg) {
                assertThat(actual).isInstanceOf(LastValueDataLong.class);
                assertThat(((LastValueDataLong) actual).getLastValue()).isEqualTo(arg.getLastValue());
                return null;
            }
        }, new Function<AggregationData, Void>() {
            @Override
            public Void apply(AggregationData arg) {
                if (arg instanceof MeanData) {
                    assertThat(actual).isInstanceOf(MeanData.class);
                    assertThat(((MeanData) actual).getMean()).isWithin(tolerance).of(((MeanData) arg).getMean());
                    return null;
                }
                throw new IllegalArgumentException("Unknown Aggregation.");
            }
        });
    }

    // Create an empty ViewData with the given View.
    static ViewData createEmptyViewData(View view) {
        return ViewData.create(view, Collections.<List<TagValue>, AggregationData>emptyMap(),
                view.getWindow().match(
                        Functions.<AggregationWindowData>returnConstant(
                                CumulativeData.create(ZERO_TIMESTAMP, ZERO_TIMESTAMP)),
                        Functions.<AggregationWindowData>returnConstant(IntervalData.create(ZERO_TIMESTAMP)),
                        Functions.<AggregationWindowData>throwAssertionError()));
    }

    // Compare the expected and actual DistributionData within the given tolerance.
    private static void assertDistributionDataEquals(DistributionData expected, DistributionData actual,
            double tolerance) {
        assertThat(actual.getMean()).isWithin(tolerance).of(expected.getMean());
        assertThat(actual.getCount()).isEqualTo(expected.getCount());
        assertThat(actual.getMean()).isWithin(tolerance).of(expected.getMean());
        assertThat(actual.getSumOfSquaredDeviations()).isWithin(tolerance).of(expected.getSumOfSquaredDeviations());

        assertThat(removeTrailingZeros(actual.getBucketCounts()))
                .isEqualTo(removeTrailingZeros(expected.getBucketCounts()));
    }

    @Nullable
    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;
    }

    static final class SimpleTagContext extends TagContext {
        private final List<Tag> tags;

        SimpleTagContext(Tag... tags) {
            this.tags = Collections.unmodifiableList(Lists.newArrayList(tags));
        }

        @Override
        protected Iterator<Tag> getIterator() {
            return tags.iterator();
        }
    }
}