Info depends on the storage type, not the other way around. Change-Id: Ie3deca17b859a217c0c7bd833c017d9436eee4b0 Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27083 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com>
1217 lines
39 KiB
C++
1217 lines
39 KiB
C++
/*
|
|
* Copyright (c) 2021 Daniel R. Carvalho
|
|
* All rights reserved
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <gtest/gtest-spi.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <cmath>
|
|
|
|
#include "base/gtest/cur_tick_fake.hh"
|
|
#include "base/gtest/logging.hh"
|
|
#include "base/stats/storage.hh"
|
|
|
|
using namespace gem5;
|
|
|
|
// Instantiate the fake class to have a valid curTick of 0
|
|
GTestTickHandler tickHandler;
|
|
|
|
/** Increases the current tick by one. */
|
|
void increaseTick() { tickHandler.setCurTick(curTick() + 1); }
|
|
|
|
/** A pair of value and its number of samples, used for sampling. */
|
|
struct ValueSamples
|
|
{
|
|
statistics::Counter value;
|
|
statistics::Counter numSamples;
|
|
|
|
ValueSamples(statistics::Counter value, statistics::Counter num_samples)
|
|
: value(value), numSamples(num_samples)
|
|
{
|
|
}
|
|
};
|
|
|
|
/** Test setting and getting a value to the storage. */
|
|
TEST(StatsStatStorTest, SetValueResult)
|
|
{
|
|
statistics::StatStor stor(nullptr);
|
|
statistics::Counter val;
|
|
|
|
val = 10;
|
|
stor.set(val);
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(val));
|
|
|
|
val = 1234;
|
|
stor.set(val);
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(val));
|
|
}
|
|
|
|
/** Test if prepare does not change the value. */
|
|
TEST(StatsStatStorTest, Prepare)
|
|
{
|
|
statistics::StatStor stor(nullptr);
|
|
statistics::Counter val;
|
|
|
|
val = 10;
|
|
stor.set(val);
|
|
stor.prepare(nullptr);
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(val));
|
|
}
|
|
|
|
/** Test whether incrementing and decrementing work as expected. */
|
|
TEST(StatsStatStorTest, IncDec)
|
|
{
|
|
statistics::StatStor stor(nullptr);
|
|
statistics::Counter diff_val = 10;
|
|
statistics::Counter val = 0;
|
|
|
|
stor.inc(diff_val);
|
|
val += diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.inc(diff_val);
|
|
val += diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.dec(diff_val);
|
|
val -= diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.dec(diff_val);
|
|
val -= diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
}
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsStatStorTest, ZeroReset)
|
|
{
|
|
statistics::StatStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
stor.inc(val);
|
|
ASSERT_FALSE(stor.zero());
|
|
}
|
|
|
|
/** Test setting and getting a value to the storage. */
|
|
TEST(StatsAvgStorTest, SetValueResult)
|
|
{
|
|
statistics::AvgStor stor(nullptr);
|
|
statistics::Counter val;
|
|
statistics::Result total = 0;
|
|
Tick last_reset = 0;
|
|
Tick last_tick = 0;
|
|
|
|
val = 10;
|
|
stor.set(val);
|
|
last_tick = curTick();
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(total + val) /
|
|
statistics::Result(curTick() - last_reset + 1));
|
|
increaseTick();
|
|
|
|
total += val * (curTick() - last_tick);
|
|
val = 1234;
|
|
stor.set(val);
|
|
last_tick = curTick();
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(total + val) /
|
|
statistics::Result(curTick() - last_reset + 1));
|
|
increaseTick();
|
|
}
|
|
|
|
#if TRACING_ON
|
|
/**
|
|
* Test whether getting the result in a different tick triggers an assertion.
|
|
*/
|
|
TEST(StatsAvgStorDeathTest, Result)
|
|
{
|
|
statistics::AvgStor stor(nullptr);
|
|
increaseTick();
|
|
ASSERT_DEATH(stor.result(), ".+");
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Test whether getting the result in a different tick does not trigger an
|
|
* assertion if storage is prepared.
|
|
*/
|
|
TEST(StatsAvgStorTest, Prepare)
|
|
{
|
|
statistics::AvgStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Result total = 0;
|
|
Tick last_reset = 0;
|
|
Tick last_tick = 0;
|
|
|
|
val = 10;
|
|
stor.set(val);
|
|
last_tick = curTick();
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(total + val) /
|
|
statistics::Result(curTick() - last_reset + 1));
|
|
increaseTick();
|
|
|
|
total += val * (curTick() - last_tick);
|
|
stor.prepare(nullptr);
|
|
last_tick = curTick();
|
|
ASSERT_EQ(stor.value(), val);
|
|
ASSERT_EQ(stor.result(), statistics::Result(total + val) /
|
|
statistics::Result(curTick() - last_reset + 1));
|
|
increaseTick();
|
|
}
|
|
|
|
/** Test whether incrementing and decrementing work as expected. */
|
|
TEST(StatsAvgStorTest, IncDec)
|
|
{
|
|
statistics::AvgStor stor(nullptr);
|
|
statistics::Counter diff_val = 10;
|
|
statistics::Counter val = 0;
|
|
|
|
stor.set(diff_val);
|
|
val += diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.inc(diff_val);
|
|
val += diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.inc(diff_val);
|
|
val += diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.dec(diff_val);
|
|
val -= diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
|
|
stor.dec(diff_val);
|
|
val -= diff_val;
|
|
ASSERT_EQ(stor.value(), val);
|
|
}
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsAvgStorTest, ZeroReset)
|
|
{
|
|
statistics::AvgStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
// Set current value to val, reset total and increase tick, so that the
|
|
// next call to set will update the total to be different from zero
|
|
stor.inc(val);
|
|
stor.reset(nullptr);
|
|
increaseTick();
|
|
stor.inc(val);
|
|
ASSERT_FALSE(stor.zero());
|
|
}
|
|
|
|
#if TRACING_ON
|
|
/** Test that an assertion is thrown when bucket size is 0. */
|
|
TEST(StatsDistStorDeathTest, BucketSize0)
|
|
{
|
|
EXPECT_ANY_THROW(statistics::DistStor::Params params(0, 5, 0));
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsDistStorTest, ZeroReset)
|
|
{
|
|
statistics::DistStor::Params params(0, 99, 10);
|
|
statistics::DistStor stor(¶ms);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(¶ms);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_FALSE(stor.zero());
|
|
|
|
stor.reset(¶ms);
|
|
ASSERT_TRUE(stor.zero());
|
|
}
|
|
|
|
/**
|
|
* Test that the size of this storage is equal to its counters vector's size,
|
|
* and that after it has been set, nothing can modify it.
|
|
*/
|
|
TEST(StatsDistStorTest, Size)
|
|
{
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
statistics::Counter size = 20;
|
|
statistics::DistData data;
|
|
|
|
statistics::DistStor::Params params(0, 19, 1);
|
|
statistics::DistStor stor(¶ms);
|
|
|
|
ASSERT_EQ(stor.size(), size);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_EQ(stor.size(), size);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(stor.size(), size);
|
|
stor.reset(¶ms);
|
|
ASSERT_EQ(stor.size(), size);
|
|
stor.zero();
|
|
ASSERT_EQ(stor.size(), size);
|
|
}
|
|
|
|
/**
|
|
* Compare both dist datas to see if their contents match.
|
|
*
|
|
* @param data The data being tested.
|
|
* @param expected_data The ground truth.
|
|
* @param no_log Whether log should not be compared.
|
|
*/
|
|
void
|
|
checkExpectedDistData(const statistics::DistData& data,
|
|
const statistics::DistData& expected_data, bool no_log = true)
|
|
{
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.min, expected_data.min);
|
|
ASSERT_EQ(data.max, expected_data.max);
|
|
ASSERT_EQ(data.bucket_size, expected_data.bucket_size);
|
|
ASSERT_EQ(data.min_val, expected_data.min_val);
|
|
ASSERT_EQ(data.max_val, expected_data.max_val);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
if (!no_log) {
|
|
ASSERT_EQ(data.logs, expected_data.logs);
|
|
}
|
|
ASSERT_EQ(data.samples, expected_data.samples);
|
|
ASSERT_EQ(data.cvec.size(), expected_data.cvec.size());
|
|
for (int i = 0; i < expected_data.cvec.size(); i++) {
|
|
ASSERT_EQ(data.cvec[i], expected_data.cvec[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Auxiliary function that finishes preparing the DistStor's expected values,
|
|
* perform the calls to the storage's sample, and compares the expected data.
|
|
*
|
|
* @param params The params containing the number of buckets.
|
|
* @param values The value-num_sample pairs to be sampled.
|
|
* @param num_values Number of values in the values array.
|
|
* @param expected_data Expected data after sampling, with the following values
|
|
* setup to the expected values: bucket_size, min, max_val, and cvec.
|
|
*/
|
|
void
|
|
prepareCheckDistStor(statistics::DistStor::Params& params,
|
|
ValueSamples* values, int num_values, statistics::DistData& expected_data)
|
|
{
|
|
statistics::DistStor stor(¶ms);
|
|
|
|
statistics::Counter val;
|
|
statistics::DistData data;
|
|
|
|
expected_data.min = params.min;
|
|
expected_data.max = params.max;
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
expected_data.logs = 0;
|
|
expected_data.samples = 0;
|
|
|
|
// Populate storage with more data
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
|
|
val = values[i].value * values[i].numSamples;
|
|
expected_data.sum += val;
|
|
expected_data.squares += values[i].value * val;
|
|
expected_data.samples += values[i].numSamples;
|
|
}
|
|
stor.prepare(¶ms, data);
|
|
|
|
// DistStor does not use log
|
|
checkExpectedDistData(data, expected_data, true);
|
|
}
|
|
|
|
/** Test setting and getting value from storage. */
|
|
TEST(StatsDistStorTest, SamplePrepareSingle)
|
|
{
|
|
statistics::DistStor::Params params(0, 99, 5);
|
|
|
|
ValueSamples values[] = {{10, 5}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
|
|
// Setup expected data
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Dist;
|
|
expected_data.bucket_size = params.bucket_size;
|
|
expected_data.underflow = 0;
|
|
expected_data.overflow = 0;
|
|
expected_data.min_val = 10;
|
|
expected_data.max_val = 10;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[2] = 5;
|
|
|
|
prepareCheckDistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/** Test setting and getting value from storage with multiple values. */
|
|
TEST(StatsDistStorTest, SamplePrepareMultiple)
|
|
{
|
|
statistics::DistStor::Params params(0, 99, 5);
|
|
|
|
// There are 20 buckets: [0,5[, [5,10[, [10,15[, ..., [95,100[.
|
|
// We test that values that pass the maximum bucket value (1234, 12345678,
|
|
// 100) are added to the overflow counter, and that the ones below the
|
|
// minimum bucket value (-10, -1) are added to the underflow counter.
|
|
// The extremes (0 and 99) are added to check if they go to the first and
|
|
// last buckets.
|
|
ValueSamples values[] = {{10, 5}, {1234, 2}, {12345678, 99}, {-10, 4},
|
|
{17, 17}, {52, 63}, {18, 11}, {0, 1}, {99, 15}, {-1, 200}, {100, 50}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
|
|
// Setup variables that should always match params' values
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Dist;
|
|
expected_data.min_val = -10;
|
|
expected_data.max_val = 12345678;
|
|
expected_data.bucket_size = params.bucket_size;
|
|
expected_data.underflow = 204;
|
|
expected_data.overflow = 151;
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
expected_data.samples = 0;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 1;
|
|
expected_data.cvec[2] = 5;
|
|
expected_data.cvec[3] = 17+11;
|
|
expected_data.cvec[10] = 63;
|
|
expected_data.cvec[19] = 15;
|
|
|
|
prepareCheckDistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/** Test resetting storage. */
|
|
TEST(StatsDistStorTest, Reset)
|
|
{
|
|
statistics::DistStor::Params params(0, 99, 5);
|
|
statistics::DistStor stor(¶ms);
|
|
|
|
// Populate storage with random samples
|
|
ValueSamples values[] = {{10, 5}, {1234, 2}, {12345678, 99}, {-10, 4},
|
|
{17, 17}, {52, 63}, {18, 11}, {0, 1}, {99, 15}, {-1, 200}, {100, 50}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
}
|
|
|
|
// Reset storage, and make sure all data has been cleared
|
|
stor.reset(¶ms);
|
|
statistics::DistData data;
|
|
stor.prepare(¶ms, data);
|
|
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Dist;
|
|
expected_data.bucket_size = params.bucket_size;
|
|
expected_data.underflow = 0;
|
|
expected_data.overflow = 0;
|
|
expected_data.min = params.min;
|
|
expected_data.max = params.max;
|
|
expected_data.min_val = 0;
|
|
expected_data.max_val = 0;
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
expected_data.samples = 0;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
|
|
checkExpectedDistData(data, expected_data, true);
|
|
}
|
|
|
|
#if TRACING_ON
|
|
/** Test that an assertion is thrown when not enough buckets are provided. */
|
|
TEST(StatsHistStorDeathTest, NotEnoughBuckets0)
|
|
{
|
|
EXPECT_ANY_THROW(statistics::HistStor::Params params(0));
|
|
}
|
|
|
|
/** Test that an assertion is thrown when not enough buckets are provided. */
|
|
TEST(StatsHistStorDeathTest, NotEnoughBuckets1)
|
|
{
|
|
EXPECT_ANY_THROW(statistics::HistStor::Params params(1));
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsHistStorTest, ZeroReset)
|
|
{
|
|
statistics::HistStor::Params params(10);
|
|
statistics::HistStor stor(¶ms);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(¶ms);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_FALSE(stor.zero());
|
|
|
|
stor.reset(¶ms);
|
|
ASSERT_TRUE(stor.zero());
|
|
}
|
|
|
|
/**
|
|
* Test that the size of this storage is equal to its counters vector's size,
|
|
* and that after it has been set, nothing can modify it.
|
|
*/
|
|
TEST(StatsHistStorTest, Size)
|
|
{
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
statistics::DistData data;
|
|
statistics::size_type sizes[] = {2, 10, 1234};
|
|
|
|
for (int i = 0; i < (sizeof(sizes) / sizeof(statistics::size_type)); i++) {
|
|
statistics::HistStor::Params params(sizes[i]);
|
|
statistics::HistStor stor(¶ms);
|
|
|
|
ASSERT_EQ(stor.size(), sizes[i]);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_EQ(stor.size(), sizes[i]);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(stor.size(), sizes[i]);
|
|
stor.reset(¶ms);
|
|
ASSERT_EQ(stor.size(), sizes[i]);
|
|
stor.zero();
|
|
ASSERT_EQ(stor.size(), sizes[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Auxiliary function that finishes preparing the HistStor's expected values,
|
|
* perform the calls to the storage's sample, and compares the expected data.
|
|
*
|
|
* @param params The params containing the number of buckets.
|
|
* @param values The value-num_sample pairs to be sampled.
|
|
* @param num_values Number of values in the values array.
|
|
* @param expected_data Expected data after sampling, with the following values
|
|
* setup to the expected values: bucket_size, min, max_val, and cvec.
|
|
*/
|
|
void
|
|
prepareCheckHistStor(statistics::HistStor::Params& params,
|
|
ValueSamples* values, int num_values, statistics::DistData& expected_data)
|
|
{
|
|
statistics::HistStor stor(¶ms);
|
|
|
|
statistics::Counter val;
|
|
statistics::DistData data;
|
|
bool no_log = false;
|
|
|
|
expected_data.min_val = expected_data.min;
|
|
expected_data.max = expected_data.max_val + expected_data.bucket_size - 1;
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
expected_data.logs = 0;
|
|
expected_data.samples = 0;
|
|
|
|
// Populate storage with more data
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
|
|
val = values[i].value * values[i].numSamples;
|
|
expected_data.sum += val;
|
|
expected_data.squares += values[i].value * val;
|
|
if (values[i].value < 0) {
|
|
// Negative values don't have log, so mark log check to be skipped
|
|
no_log = true;
|
|
} else {
|
|
expected_data.logs +=
|
|
std::log(values[i].value) * values[i].numSamples;
|
|
}
|
|
expected_data.samples += values[i].numSamples;
|
|
}
|
|
stor.prepare(¶ms, data);
|
|
checkExpectedDistData(data, expected_data, no_log);
|
|
}
|
|
|
|
/**
|
|
* Test samples that fit in the initial buckets, and therefore do not need
|
|
* to grow up.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareFit)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. The final buckets
|
|
// will be divided at:
|
|
// Bkt0=[0,1[ , Bkt1=[1,2[, Bkt2=[2,3[, Bkt3=[3,4[
|
|
ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {3, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 1;
|
|
expected_data.min = 0;
|
|
expected_data.max_val = 3;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 5;
|
|
expected_data.cvec[1] = 2;
|
|
expected_data.cvec[2] = 99;
|
|
expected_data.cvec[3] = 4;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that do not fit in the initial buckets, and therefore have
|
|
* to grow up once.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareSingleGrowUp)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// are four buckets, and the highest value is 4, the bucket size will
|
|
// grow to be 2. The final buckets will be divided at:
|
|
// Bkt0=[0,2[ , Bkt1=[2,4[, Bkt2=[4,6[, Bkt3=[6,8[
|
|
ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {4, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 2;
|
|
expected_data.min = 0;
|
|
expected_data.max_val = 6;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 5+2;
|
|
expected_data.cvec[1] = 99;
|
|
expected_data.cvec[2] = 4;
|
|
expected_data.cvec[3] = 0;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that do not fit in the initial buckets, and therefore have
|
|
* to grow up a few times.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareMultipleGrowUp)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// are four buckets, and the highest value is 4, the bucket size will
|
|
// grow thrice to become 8. The final buckets will be divided at:
|
|
// Bkt0=[0,8[ , Bkt1=[8,16[, Bkt2=[16,24[, Bkt3=[24,32[
|
|
ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {16, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 8;
|
|
expected_data.min = 0;
|
|
expected_data.max_val = 24;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 5+2+99;
|
|
expected_data.cvec[1] = 0;
|
|
expected_data.cvec[2] = 4;
|
|
expected_data.cvec[3] = 0;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that have a negative value, and therefore do not fit in the
|
|
* initial buckets. Since this involves using negative values, the logs
|
|
* become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareGrowDownOddBuckets)
|
|
{
|
|
statistics::HistStor::Params params(5);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// is a negative value, the min bucket will change, and the bucket size
|
|
// will grow to be 2. The final buckets will be divided at:
|
|
// Bkt0=[-4,-2[ , Bkt1=[-2,-0[, Bkt2=[0,2[, Bkt3=[2,4[, Bkt4=[4,6[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {1, 2}, {2, 99}, {3, 12}, {4, 33}, {-1, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 2;
|
|
expected_data.min = -4;
|
|
expected_data.max_val = 4;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 0;
|
|
expected_data.cvec[1] = 4;
|
|
expected_data.cvec[2] = 5+2;
|
|
expected_data.cvec[3] = 99+12;
|
|
expected_data.cvec[4] = 33;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that have a negative value, and therefore do not fit in the
|
|
* initial buckets. Since this involves using negative values, the logs
|
|
* become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareGrowDownEvenBuckets)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// is a negative value, the min bucket will change, and the bucket size
|
|
// will grow to be 2. The final buckets will be divided at:
|
|
// Bkt0=[-4,-2[ , Bkt1=[-2,0[, Bkt2=[0,2[, Bkt3=[2,4[
|
|
ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {-1, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 2;
|
|
expected_data.min = -4;
|
|
expected_data.max_val = 2;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 0;
|
|
expected_data.cvec[1] = 4;
|
|
expected_data.cvec[2] = 5+2;
|
|
expected_data.cvec[3] = 99;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that have one low negative value, and therefore do not fit
|
|
* in the initial buckets and have to grow down a few times. Since this
|
|
* involves using negative values, the logs become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareGrowDownGrowOutOddBuckets)
|
|
{
|
|
statistics::HistStor::Params params(5);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// is a negative value, the min bucket will change, and the bucket size
|
|
// will grow to be 8. The final buckets will be divided at:
|
|
// Bkt0=[-16,-8[ , Bkt1=[-8,0[, Bkt2=[0,8[, Bkt3=[8,16[, Bkt4=[16,24[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {1, 2}, {2, 99}, {3, 12}, {4, 33}, {-12, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 8;
|
|
expected_data.min = -16;
|
|
expected_data.max_val = 16;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 4;
|
|
expected_data.cvec[1] = 0;
|
|
expected_data.cvec[2] = 5+2+99+12+33;
|
|
expected_data.cvec[3] = 0;
|
|
expected_data.cvec[4] = 0;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test samples that have one low negative value, and therefore do not fit
|
|
* in the initial buckets and have to grow down a few times. Since this
|
|
* involves using negative values, the logs become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareGrowDownGrowOutEvenBuckets)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. Since there
|
|
// is a negative value, the min bucket will change, and the bucket size
|
|
// will grow to be 8. The final buckets will be divided at:
|
|
// Bkt0=[-16,-8[ , Bkt1=[-8,0[, Bkt2=[0,8[, Bkt3=[8,16[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {1, 2}, {2, 99}, {3, 12}, {-12, 4}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 8;
|
|
expected_data.min = -16;
|
|
expected_data.max_val = 8;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 4;
|
|
expected_data.cvec[1] = 0;
|
|
expected_data.cvec[2] = 5+2+99+12;
|
|
expected_data.cvec[3] = 0;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test a complex sample set with negative values, and therefore multiple
|
|
* grows will happen. Since this involves using negative values, the logs
|
|
* become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareMultipleGrowOddBuckets)
|
|
{
|
|
statistics::HistStor::Params params(5);
|
|
|
|
// Setup expected data for the hand-carved values given. This adds quite
|
|
// a few positive and negative samples, and the bucket size will grow to
|
|
// be 64. The final buckets will be divided at:
|
|
// Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[,
|
|
// Bkt4=[128,192[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 64;
|
|
expected_data.min = -128;
|
|
expected_data.max_val = 128;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 53;
|
|
expected_data.cvec[1] = 12+1;
|
|
expected_data.cvec[2] = 5+2+99;
|
|
expected_data.cvec[3] = 4;
|
|
expected_data.cvec[4] = 0;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/**
|
|
* Test a complex sample set with negative values, and therefore multiple
|
|
* grows will happen. Since this involves using negative values, the logs
|
|
* become irrelevant.
|
|
*/
|
|
TEST(StatsHistStorTest, SamplePrepareMultipleGrowEvenBuckets)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup expected data for the hand-carved values given. This adds quite
|
|
// a few positive and negative samples, and the bucket size will grow to
|
|
// be 64. The final buckets will be divided at:
|
|
// Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 64;
|
|
expected_data.min = -128;
|
|
expected_data.max_val = 64;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 53;
|
|
expected_data.cvec[1] = 12+1;
|
|
expected_data.cvec[2] = 5+2+99;
|
|
expected_data.cvec[3] = 4;
|
|
|
|
prepareCheckHistStor(params, values, num_values, expected_data);
|
|
}
|
|
|
|
/** Test resetting storage. */
|
|
TEST(StatsHistStorTest, Reset)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
statistics::HistStor stor(¶ms);
|
|
|
|
// Setup expected data for the hand-carved values given. This adds quite
|
|
// a few positive and negative samples, and the bucket size will grow to
|
|
// be 64. The final buckets will be divided at:
|
|
// Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[
|
|
ValueSamples values[] =
|
|
{{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
|
|
const int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
}
|
|
|
|
// Reset storage, and make sure all data has been cleared:
|
|
// Bkt0=[0,1[ , Bkt1=[1,2[, Bkt2=[2,3[, Bkt3=[3,4[
|
|
stor.reset(¶ms);
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 1;
|
|
expected_data.min = 0;
|
|
expected_data.max_val = 3;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
prepareCheckHistStor(params, values, 0, expected_data);
|
|
}
|
|
|
|
#if TRACING_ON
|
|
/** Test whether adding storages with different sizes triggers an assertion. */
|
|
TEST(StatsHistStorDeathTest, AddDifferentSize)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
statistics::HistStor stor(¶ms);
|
|
|
|
statistics::HistStor::Params params2(5);
|
|
statistics::HistStor stor2(¶ms2);
|
|
|
|
ASSERT_DEATH(stor.add(&stor2), ".+");
|
|
}
|
|
|
|
/** Test whether adding storages with different min triggers an assertion. */
|
|
TEST(StatsHistStorDeathTest, AddDifferentMin)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
statistics::HistStor stor(¶ms);
|
|
stor.sample(-1, 3);
|
|
|
|
// On creation, the storage's min is zero
|
|
statistics::HistStor::Params params2(4);
|
|
statistics::HistStor stor2(¶ms2);
|
|
|
|
ASSERT_DEATH(stor.add(&stor2), ".+");
|
|
}
|
|
#endif
|
|
|
|
/** Test merging two histograms. */
|
|
TEST(StatsHistStorTest, Add)
|
|
{
|
|
statistics::HistStor::Params params(4);
|
|
|
|
// Setup first storage. Buckets are:
|
|
// Bkt0=[0,16[, Bkt1=[16,32[, Bkt2=[32,48[, Bkt3=[58,64[
|
|
statistics::HistStor stor(¶ms);
|
|
ValueSamples values[] = {{0, 5}, {3, 2}, {20, 37}, {32, 18}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
}
|
|
statistics::DistData data;
|
|
stor.prepare(¶ms, data);
|
|
|
|
// Setup second storage. Buckets are:
|
|
// Bkt0=[0,32[, Bkt1=[32,64[, Bkt2=[64,96[, Bkt3=[96,128[
|
|
statistics::HistStor stor2(¶ms);
|
|
ValueSamples values2[] = {{10, 10}, {0, 1}, {80, 4}, {17, 100}, {95, 79}};
|
|
int num_values2 = sizeof(values2) / sizeof(ValueSamples);
|
|
for (int i = 0; i < num_values2; i++) {
|
|
stor2.sample(values2[i].value, values2[i].numSamples);
|
|
}
|
|
statistics::DistData data2;
|
|
stor2.prepare(¶ms, data2);
|
|
|
|
// Perform the merge
|
|
stor.add(&stor2);
|
|
statistics::DistData merge_data;
|
|
stor.prepare(¶ms, merge_data);
|
|
|
|
// Setup expected data. Buckets are:
|
|
// Bkt0=[0,32[, Bkt1=[32,64[, Bkt2=[64,96[, Bkt3=[96,128[
|
|
statistics::DistData expected_data;
|
|
expected_data.type = statistics::Hist;
|
|
expected_data.bucket_size = 32;
|
|
expected_data.min = 0;
|
|
expected_data.max = 127;
|
|
expected_data.min_val = 0;
|
|
expected_data.max_val = 96;
|
|
expected_data.cvec.clear();
|
|
expected_data.cvec.resize(params.buckets);
|
|
expected_data.cvec[0] = 5+2+37+10+1+100;
|
|
expected_data.cvec[1] = 18;
|
|
expected_data.cvec[2] = 4+79;
|
|
expected_data.cvec[3] = 0;
|
|
expected_data.sum = data.sum + data2.sum;
|
|
expected_data.squares = data.squares + data2.squares;
|
|
expected_data.logs = data.squares + data2.logs;
|
|
expected_data.samples = data.samples + data2.samples;
|
|
|
|
// Compare results
|
|
checkExpectedDistData(merge_data, expected_data, false);
|
|
}
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsSampleStorTest, ZeroReset)
|
|
{
|
|
statistics::SampleStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_FALSE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
ASSERT_TRUE(stor.zero());
|
|
}
|
|
|
|
/** Test setting and getting value from storage. */
|
|
TEST(StatsSampleStorTest, SamplePrepare)
|
|
{
|
|
statistics::SampleStor stor(nullptr);
|
|
ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::Counter val;
|
|
statistics::DistData data;
|
|
statistics::DistData expected_data;
|
|
statistics::SampleStor::Params params;
|
|
|
|
// Simple test with one value being sampled
|
|
stor.sample(values[0].value, values[0].numSamples);
|
|
stor.prepare(¶ms, data);
|
|
val = values[0].value * values[0].numSamples;
|
|
expected_data.type = statistics::Deviation;
|
|
expected_data.sum = val;
|
|
expected_data.squares = values[0].value * val;
|
|
expected_data.samples = values[0].numSamples;
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, expected_data.samples);
|
|
|
|
// Reset storage, and make sure all data has been cleared
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
expected_data.samples = 0;
|
|
stor.reset(nullptr);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, expected_data.samples);
|
|
|
|
// Populate storage with more data
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
|
|
val = values[i].value * values[i].numSamples;
|
|
expected_data.sum += val;
|
|
expected_data.squares += values[i].value * val;
|
|
expected_data.samples += values[i].numSamples;
|
|
}
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, expected_data.samples);
|
|
}
|
|
|
|
/** The size is always 1, no matter which functions have been called. */
|
|
TEST(StatsSampleStorTest, Size)
|
|
{
|
|
statistics::SampleStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
statistics::DistData data;
|
|
statistics::SampleStor::Params params;
|
|
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.reset(nullptr);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.zero();
|
|
ASSERT_EQ(stor.size(), 1);
|
|
}
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsAvgSampleStorTest, ZeroReset)
|
|
{
|
|
statistics::AvgSampleStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_FALSE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
ASSERT_TRUE(stor.zero());
|
|
}
|
|
|
|
/** Test setting and getting value from storage. */
|
|
TEST(StatsAvgSampleStorTest, SamplePrepare)
|
|
{
|
|
statistics::AvgSampleStor stor(nullptr);
|
|
ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::Counter val;
|
|
statistics::DistData data;
|
|
statistics::DistData expected_data;
|
|
statistics::AvgSampleStor::Params params;
|
|
|
|
// Simple test with one value being sampled
|
|
stor.sample(values[0].value, values[0].numSamples);
|
|
stor.prepare(¶ms, data);
|
|
val = values[0].value * values[0].numSamples;
|
|
expected_data.type = statistics::Deviation;
|
|
expected_data.sum = val;
|
|
expected_data.squares = values[0].value * val;
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, curTick());
|
|
|
|
increaseTick();
|
|
|
|
// Reset storage, and make sure all data has been cleared
|
|
expected_data.sum = 0;
|
|
expected_data.squares = 0;
|
|
stor.reset(nullptr);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, curTick());
|
|
|
|
increaseTick();
|
|
|
|
// Populate storage with more data
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
|
|
val = values[i].value * values[i].numSamples;
|
|
expected_data.sum += val;
|
|
expected_data.squares += values[i].value * val;
|
|
}
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(data.type, expected_data.type);
|
|
ASSERT_EQ(data.sum, expected_data.sum);
|
|
ASSERT_EQ(data.squares, expected_data.squares);
|
|
ASSERT_EQ(data.samples, curTick());
|
|
}
|
|
|
|
/** The size is always 1, no matter which functions have been called. */
|
|
TEST(StatsAvgSampleStorTest, Size)
|
|
{
|
|
statistics::AvgSampleStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
statistics::DistData data;
|
|
statistics::AvgSampleStor::Params params;
|
|
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.prepare(¶ms, data);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.reset(nullptr);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
stor.zero();
|
|
ASSERT_EQ(stor.size(), 1);
|
|
}
|
|
|
|
/**
|
|
* Test whether zero is correctly set as the reset value. The test order is
|
|
* to check if it is initially zero on creation, then it is made non zero,
|
|
* and finally reset to zero.
|
|
*/
|
|
TEST(StatsSparseHistStorTest, ZeroReset)
|
|
{
|
|
statistics::SparseHistStor stor(nullptr);
|
|
statistics::Counter val = 10;
|
|
statistics::Counter num_samples = 5;
|
|
|
|
ASSERT_TRUE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
stor.sample(val, num_samples);
|
|
ASSERT_FALSE(stor.zero());
|
|
|
|
stor.reset(nullptr);
|
|
ASSERT_TRUE(stor.zero());
|
|
}
|
|
|
|
/** Test setting and getting value from storage. */
|
|
TEST(StatsSparseHistStorTest, SamplePrepare)
|
|
{
|
|
statistics::SparseHistStor stor(nullptr);
|
|
ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
|
|
int num_values = sizeof(values) / sizeof(ValueSamples);
|
|
statistics::Counter total_samples;
|
|
statistics::SparseHistData data;
|
|
|
|
// Simple test with one value being sampled
|
|
stor.sample(values[0].value, values[0].numSamples);
|
|
stor.prepare(nullptr, data);
|
|
ASSERT_EQ(stor.size(), 1);
|
|
ASSERT_EQ(data.cmap.size(), 1);
|
|
ASSERT_EQ(data.cmap[values[0].value], values[0].numSamples);
|
|
ASSERT_EQ(data.samples, values[0].numSamples);
|
|
|
|
// Reset storage, and make sure all data has been cleared
|
|
stor.reset(nullptr);
|
|
stor.prepare(nullptr, data);
|
|
ASSERT_EQ(stor.size(), 0);
|
|
ASSERT_EQ(data.cmap.size(), 0);
|
|
ASSERT_EQ(data.samples, 0);
|
|
|
|
// Populate storage with more data
|
|
for (int i = 0; i < num_values; i++) {
|
|
stor.sample(values[i].value, values[i].numSamples);
|
|
}
|
|
stor.prepare(nullptr, data);
|
|
total_samples = 0;
|
|
ASSERT_EQ(stor.size(), num_values);
|
|
ASSERT_EQ(data.cmap.size(), num_values);
|
|
for (int i = 0; i < num_values; i++) {
|
|
ASSERT_EQ(data.cmap[values[i].value], values[i].numSamples);
|
|
total_samples += values[i].numSamples;
|
|
}
|
|
ASSERT_EQ(data.samples, total_samples);
|
|
}
|