lib/model/unittest/CSampleQueueTest.cc (953 lines of code) (raw):
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the following additional limitation. Functionality enabled by the
* files subject to the Elastic License 2.0 may only be used in production when
* invoked by an Elasticsearch process with a license key installed that permits
* use of machine learning features. You may not use this file except in
* compliance with the Elastic License 2.0 and the foregoing additional
* limitation.
*/
#include <core/CJsonStatePersistInserter.h>
#include <core/CJsonStateRestoreTraverser.h>
#include <core/CLogger.h>
#include <core/CoreTypes.h>
#include <maths/common/CBasicStatistics.h>
#include <maths/common/CBasicStatisticsPersist.h>
#include <maths/common/CIntegerTools.h>
#include <model/CSampleQueue.h>
#include <model/ModelTypes.h>
#include <test/BoostTestCloseAbsolute.h>
#include <test/CRandomNumbers.h>
#include <boost/math/constants/constants.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(CSampleQueueTest)
using namespace ml;
using namespace model;
using TDoubleVec = std::vector<double>;
using TSampleVec = std::vector<CSample>;
using TMeanAccumulator = maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator;
using TTestSampleQueue = CSampleQueue<TMeanAccumulator>;
BOOST_AUTO_TEST_CASE(testSampleToString) {
CSample sample(10, {3.0}, 0.8, 1.0);
BOOST_REQUIRE_EQUAL(std::string("10;0.800000012;1;3"), CSample::SToString()(sample));
}
BOOST_AUTO_TEST_CASE(testSampleFromString) {
CSample sample;
BOOST_TEST_REQUIRE(CSample::SFromString()("15;7e-1;3;2.0", sample));
BOOST_REQUIRE_EQUAL(core_t::TTime(15), sample.time());
BOOST_REQUIRE_EQUAL(2.0, sample.value()[0]);
BOOST_REQUIRE_EQUAL(0.7, sample.varianceScale());
BOOST_REQUIRE_EQUAL(3.0, sample.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenQueueIsEmptyShouldCreateNewSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(1, {1.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(1), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(1), queue[0].s_End);
BOOST_REQUIRE_EQUAL(core_t::TTime(1), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenQueueIsFullShouldResize) {
std::size_t sampleCountFactor(1);
std::size_t latencyBuckets(1);
double growthFactor(0.5);
core_t::TTime bucketLength(10);
unsigned int sampleCount(1);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(1, {1.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(1, queue.capacity());
queue.add(2, {2.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(2, queue.capacity());
queue.add(3, {3.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(3, queue.capacity());
queue.add(4, {4.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(4, queue.size());
BOOST_REQUIRE_EQUAL(4, queue.capacity());
queue.add(5, {5.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(5, queue.size());
BOOST_REQUIRE_EQUAL(6, queue.capacity());
queue.add(6, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(6, queue.size());
BOOST_REQUIRE_EQUAL(6, queue.capacity());
queue.add(7, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(7, queue.size());
BOOST_REQUIRE_EQUAL(9, queue.capacity());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsInOrderAndCloseToNonFullLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(3, {2.5}, 2, sampleCount);
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[0].s_End);
BOOST_REQUIRE_EQUAL(2.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(2), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(3.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsInOrderAndCloseToNonFullLatestSubSampleButDifferentBucket) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue.latestEnd());
queue.add(9, {1.0}, 1, sampleCount);
queue.add(10, {2.5}, 2, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[0].s_End);
BOOST_REQUIRE_EQUAL(2.5, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[0].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_End);
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue.latestEnd());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsInOrderAndCloseToFullLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 5, sampleCount);
queue.add(3, {2.5}, 2, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[0].s_End);
BOOST_REQUIRE_EQUAL(2.5, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[0].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_End);
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(5.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsInOrderAndFarFromLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(5, {2.5}, 2, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[0].s_End);
BOOST_REQUIRE_EQUAL(2.5, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[0].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_End);
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsWithinFullLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 2, sampleCount);
queue.add(4, {1.0}, 3, sampleCount);
queue.add(3, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(4), queue[0].s_End);
BOOST_REQUIRE_EQUAL(2.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(6.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndFarBeforeEarliestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(8, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 3, sampleCount);
queue.add(3, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_End);
BOOST_REQUIRE_EQUAL(7.0, queue[2].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[2].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloseBeforeFullEarliestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(8, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 3, sampleCount);
queue.add(5, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[2].s_End);
BOOST_REQUIRE_EQUAL(7.0, queue[2].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[2].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[2].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloseBeforeNonFullEarliestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(9, {1.0}, 4, sampleCount);
queue.add(15, {1.0}, 3, sampleCount);
queue.add(6, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_End);
BOOST_REQUIRE_EQUAL(2.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(5.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloseBeforeNonFullEarliestSubSampleButDifferentBucket) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(11, {1.0}, 4, sampleCount);
queue.add(9, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(11), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(11), queue[0].s_End);
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(11), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(4.0, queue[0].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_End);
BOOST_REQUIRE_EQUAL(6.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndWithinSomeSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(6, {2.0}, 1, sampleCount);
queue.add(8, {4.0}, 1, sampleCount);
queue.add(12, {1.0}, 1, sampleCount);
queue.add(7, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_End);
BOOST_REQUIRE_EQUAL(4.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(7), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(3.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToSubSampleBeforeLatest) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(5, {1.0}, 1, sampleCount);
queue.add(10, {4.0}, 1, sampleCount);
queue.add(15, {1.0}, 1, sampleCount);
queue.add(12, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(4, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(12), queue[1].s_End);
BOOST_REQUIRE_EQUAL(5.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(11), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToSubSampleBeforeLatestButDifferentBucket) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(8, {4.0}, 1, sampleCount);
queue.add(15, {1.0}, 1, sampleCount);
queue.add(10, {6.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(4, queue.size());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToPreviousOfNonFullSubSamples) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(8, {2.0}, 1, sampleCount);
queue.add(15, {3.0}, 1, sampleCount);
queue.add(3, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_End);
BOOST_REQUIRE_EQUAL(4.0, queue[2].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(2), queue[2].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[2].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToNextOfNonFullSubSamples) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(8, {2.0}, 1, sampleCount);
queue.add(15, {3.0}, 1, sampleCount);
queue.add(5, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_End);
BOOST_REQUIRE_EQUAL(4.5, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(7), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToPreviousOfFullSubSamples) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 5, sampleCount);
queue.add(8, {2.0}, 5, sampleCount);
queue.add(15, {3.0}, 1, sampleCount);
queue.add(3, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_End);
BOOST_REQUIRE_EQUAL(2.0, queue[2].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(1), queue[2].s_Statistic.time());
BOOST_REQUIRE_EQUAL(6.0, queue[2].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToNextOfFullSubSamples) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 5, sampleCount);
queue.add(8, {2.0}, 5, sampleCount);
queue.add(15, {3.0}, 5, sampleCount);
queue.add(5, {8.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_End);
BOOST_REQUIRE_EQUAL(3.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(6.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToPreviousSubSampleButOnlyNextHasSpace) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 5, sampleCount);
queue.add(5, {2.0}, 1, sampleCount);
queue.add(10, {3.0}, 1, sampleCount);
queue.add(2, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(2), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(5), queue[1].s_End);
BOOST_REQUIRE_EQUAL(4.5, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(4), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndCloserToNextSubSampleButOnlyPreviousHasSpace) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(5, {2.0}, 5, sampleCount);
queue.add(10, {3.0}, 5, sampleCount);
queue.add(3, {8.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[2].s_End);
BOOST_REQUIRE_EQUAL(4.5, queue[2].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(2), queue[2].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[2].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndFallsInBigEnoughGap) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(15, {2.0}, 1, sampleCount);
queue.add(6, {8.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_End);
BOOST_REQUIRE_EQUAL(8.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testAddGivenTimeIsHistoricalAndFallsInTooSmallGap) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(5);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 1, sampleCount);
queue.add(4, {1.0}, 1, sampleCount);
queue.add(9, {2.0}, 1, sampleCount);
queue.add(6, {7.0}, 1, sampleCount);
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(6), queue[1].s_End);
BOOST_REQUIRE_EQUAL(3.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(3), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(3.0, queue[1].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testCanSampleGivenEmptyQueue) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
BOOST_TEST_REQUIRE(queue.canSample(42) == false);
}
BOOST_AUTO_TEST_CASE(testCanSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(24, {1.0}, 1, sampleCount);
queue.add(26, {1.0}, 1, sampleCount);
queue.add(45, {1.0}, 5, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0) == false);
BOOST_TEST_REQUIRE(queue.canSample(16) == false);
BOOST_TEST_REQUIRE(queue.canSample(17));
BOOST_TEST_REQUIRE(queue.canSample(40));
}
BOOST_AUTO_TEST_CASE(testSampleGivenExactlyOneSampleOfExactCountToBeCreated) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {1.0}, 5, sampleCount);
queue.add(6, {3.0}, 5, sampleCount);
queue.add(30, {5.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_REQUIRE_EQUAL(1, samples.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(3), samples[0].time());
BOOST_REQUIRE_EQUAL(2.0, samples[0].value()[0]);
BOOST_REQUIRE_EQUAL(1.0, samples[0].varianceScale());
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_End);
BOOST_REQUIRE_EQUAL(5.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testSampleGivenExactlyOneSampleOfOverCountToBeCreated) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {0.0}, 3, sampleCount);
queue.add(1, {1.0}, 1, sampleCount);
queue.add(6, {3.0}, 7, sampleCount);
queue.add(30, {5.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_REQUIRE_EQUAL(1, samples.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(4), samples[0].time());
BOOST_REQUIRE_EQUAL(2.0, samples[0].value()[0]);
BOOST_TEST_REQUIRE(samples[0].varianceScale() < 1.0);
BOOST_REQUIRE_EQUAL(1, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_End);
BOOST_REQUIRE_EQUAL(5.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testSampleGivenOneSampleToBeCreatedAndRemainder) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {1.0}, 5, sampleCount);
queue.add(6, {3.0}, 5, sampleCount);
queue.add(7, {3.0}, 1, sampleCount);
queue.add(8, {5.0}, 1, sampleCount);
queue.add(40, {8.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_REQUIRE_EQUAL(1, samples.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(3), samples[0].time());
BOOST_REQUIRE_EQUAL(2.0, samples[0].value()[0]);
BOOST_REQUIRE_EQUAL(1.0, samples[0].varianceScale());
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(7), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_End);
BOOST_REQUIRE_EQUAL(4.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(8), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(2.0, queue[1].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(40), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(40), queue[0].s_End);
BOOST_REQUIRE_EQUAL(8.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(40), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testSampleGivenTwoSamplesToBeCreatedAndRemainder) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {1.0}, 5, sampleCount);
queue.add(2, {4.0}, 5, sampleCount);
queue.add(7, {2.0}, 5, sampleCount);
queue.add(8, {5.0}, 5, sampleCount);
queue.add(9, {0.0}, 1, sampleCount);
queue.add(30, {8.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_REQUIRE_EQUAL(2, samples.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(1), samples[0].time());
BOOST_REQUIRE_EQUAL(2.5, samples[0].value()[0]);
BOOST_REQUIRE_EQUAL(1.0, samples[0].varianceScale());
BOOST_REQUIRE_EQUAL(core_t::TTime(8), samples[1].time());
BOOST_REQUIRE_EQUAL(3.5, samples[1].value()[0]);
BOOST_REQUIRE_EQUAL(1.0, samples[1].varianceScale());
BOOST_REQUIRE_EQUAL(2, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_End);
BOOST_REQUIRE_EQUAL(0.0, queue[1].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(9), queue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[1].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_End);
BOOST_REQUIRE_EQUAL(8.0, queue[0].s_Statistic.value()[0]);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, queue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testSampleGivenNoSampleToBeCreated) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {1.0}, 4, sampleCount);
queue.add(30, {5.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_TEST_REQUIRE(samples.empty());
BOOST_REQUIRE_EQUAL(2, queue.size());
}
BOOST_AUTO_TEST_CASE(testSampleGivenUsingSubSamplesUpToCountExceedItMoreThanUsingOneLess) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
TTestSampleQueue::TSampleVec samples;
queue.add(0, {2.0}, 5, sampleCount);
queue.add(2, {2.0}, 3, sampleCount);
queue.add(10, {6.0}, 6, sampleCount);
queue.add(30, {8.0}, 1, sampleCount);
BOOST_TEST_REQUIRE(queue.canSample(0));
queue.sample(0, sampleCount, model_t::E_IndividualMeanByPerson, samples);
BOOST_REQUIRE_EQUAL(1, samples.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(1), samples[0].time());
BOOST_REQUIRE_EQUAL(2.0, samples[0].value()[0]);
BOOST_REQUIRE_EQUAL(1.25, samples[0].varianceScale());
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenEmptyQueue) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.resetBucket(10);
BOOST_TEST_REQUIRE(queue.empty());
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketBeforeEarliestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(20, {1.0}, 5, sampleCount);
queue.add(24, {1.0}, 5, sampleCount);
queue.add(29, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(0);
BOOST_REQUIRE_EQUAL(6, queue.size());
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketAtEarliestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 3, sampleCount);
queue.add(11, {1.0}, 2, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(20, {1.0}, 5, sampleCount);
queue.add(24, {1.0}, 5, sampleCount);
queue.add(29, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(10);
BOOST_REQUIRE_EQUAL(4, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(29), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(24), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(20), queue[3].s_Start);
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketInBetweenWithoutAnySubSamples) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(20);
BOOST_REQUIRE_EQUAL(3, queue.size());
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketAtInBetweenSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(20, {1.0}, 5, sampleCount);
queue.add(24, {1.0}, 5, sampleCount);
queue.add(29, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(20);
BOOST_REQUIRE_EQUAL(3, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(15), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[2].s_Start);
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketAtLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(20, {1.0}, 5, sampleCount);
queue.add(24, {1.0}, 5, sampleCount);
queue.add(29, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(30);
BOOST_REQUIRE_EQUAL(5, queue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(29), queue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(24), queue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(20), queue[2].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(15), queue[3].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(10), queue[4].s_Start);
}
BOOST_AUTO_TEST_CASE(testResetBucketGivenBucketAfterLatestSubSample) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(10, {1.0}, 5, sampleCount);
queue.add(15, {1.0}, 5, sampleCount);
queue.add(20, {1.0}, 5, sampleCount);
queue.add(24, {1.0}, 5, sampleCount);
queue.add(29, {1.0}, 5, sampleCount);
queue.add(30, {1.0}, 5, sampleCount);
queue.resetBucket(40);
BOOST_REQUIRE_EQUAL(6, queue.size());
}
BOOST_AUTO_TEST_CASE(testSubSamplesNeverSpanOverDifferentBuckets) {
std::size_t sampleCountFactor(10);
std::size_t latencyBuckets(3);
double growthFactor(0.1);
core_t::TTime bucketLength(600);
unsigned int sampleCount(45);
core_t::TTime latency = (latencyBuckets + 1) * bucketLength;
std::size_t numberOfMeasurements = 5000;
test::CRandomNumbers rng;
core_t::TTime latestTime = bucketLength * (latencyBuckets + 1);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
for (std::size_t measurementId = 0; measurementId < numberOfMeasurements; ++measurementId) {
TDoubleVec testData;
rng.generateUniformSamples(static_cast<double>(latestTime - latency),
static_cast<double>(latestTime), 1, testData);
latestTime +=
60 + static_cast<core_t::TTime>(
40.0 * std::sin(boost::math::constants::two_pi<double>() *
static_cast<double>(latestTime % 86400) / 86400.0));
core_t::TTime measurementTime = static_cast<core_t::TTime>(testData[0]);
queue.add(measurementTime, {1.0}, 1u, sampleCount);
}
for (std::size_t i = 0; i < queue.size(); ++i) {
core_t::TTime startBucket =
maths::common::CIntegerTools::floor(queue[i].s_Start, bucketLength);
core_t::TTime endBucket =
maths::common::CIntegerTools::floor(queue[i].s_End, bucketLength);
BOOST_REQUIRE_EQUAL(startBucket, endBucket);
}
}
BOOST_AUTO_TEST_CASE(testPersistence) {
std::size_t sampleCountFactor(2);
std::size_t latencyBuckets(2);
double growthFactor(0.1);
core_t::TTime bucketLength(10);
unsigned int sampleCount(10);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
queue.add(0, {1.0}, 3, sampleCount);
queue.add(2, {3.5}, 2, sampleCount);
queue.add(30, {8.0}, 1, sampleCount);
std::ostringstream origJson;
core::CJsonStatePersistInserter::persist(
origJson, std::bind_front(&TTestSampleQueue::acceptPersistInserter, &queue));
LOG_DEBUG(<< "JSON:\n" << origJson.str());
std::istringstream origJsonStrm{"{\"topLevel\":" + origJson.str() + "}"};
core::CJsonStateRestoreTraverser traverser(origJsonStrm);
TTestSampleQueue restoredQueue(1, sampleCountFactor, latencyBuckets,
growthFactor, bucketLength);
traverser.traverseSubLevel(
std::bind_front(&TTestSampleQueue::acceptRestoreTraverser, &restoredQueue));
BOOST_REQUIRE_EQUAL(2, restoredQueue.size());
BOOST_REQUIRE_EQUAL(core_t::TTime(0), restoredQueue[1].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(2), restoredQueue[1].s_End);
BOOST_REQUIRE_CLOSE_ABSOLUTE(2.0, restoredQueue[1].s_Statistic.value()[0], 0.0001);
BOOST_REQUIRE_EQUAL(core_t::TTime(1), restoredQueue[1].s_Statistic.time());
BOOST_REQUIRE_EQUAL(5.0, restoredQueue[1].s_Statistic.count());
BOOST_REQUIRE_EQUAL(core_t::TTime(30), restoredQueue[0].s_Start);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), restoredQueue[0].s_End);
BOOST_REQUIRE_CLOSE_ABSOLUTE(8.0, restoredQueue[0].s_Statistic.value()[0], 0.0001);
BOOST_REQUIRE_EQUAL(core_t::TTime(30), restoredQueue[0].s_Statistic.time());
BOOST_REQUIRE_EQUAL(1.0, restoredQueue[0].s_Statistic.count());
}
BOOST_AUTO_TEST_CASE(testQualityOfSamplesGivenConstantRate) {
std::size_t sampleCountFactor(5);
std::size_t latencyBuckets(3);
double growthFactor(0.1);
core_t::TTime bucketLength(600);
unsigned int sampleCount(30);
core_t::TTime latency = (latencyBuckets + 1) * bucketLength;
std::size_t numberOfMeasurements = 5000;
std::size_t numberOfRuns = 100;
test::CRandomNumbers rng;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanQueueSize;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanMinVariance;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanMaxVariance;
for (std::size_t runId = 0; runId < numberOfRuns; ++runId) {
TSampleVec samples;
core_t::TTime latestTime = bucketLength * (latencyBuckets + 1);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
for (std::size_t measurementId = 0;
measurementId < numberOfMeasurements; ++measurementId) {
TDoubleVec testData;
rng.generateUniformSamples(static_cast<double>(latestTime - latency),
static_cast<double>(latestTime), 1, testData);
latestTime += 60;
core_t::TTime measurementTime = static_cast<core_t::TTime>(testData[0]);
queue.add(measurementTime, {1.0}, 1u, sampleCount);
}
meanQueueSize.add(static_cast<double>(queue.size()));
queue.sample(latestTime, sampleCount, model_t::E_IndividualMeanByPerson, samples);
maths::common::CBasicStatistics::SSampleMeanVar<double>::TAccumulator varianceStat;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 5u> varianceMin;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 5u, std::greater<double>> varianceMax;
for (std::size_t i = 0; i < samples.size(); ++i) {
varianceStat.add(samples[i].varianceScale());
varianceMin.add(samples[i].varianceScale());
varianceMax.add(samples[i].varianceScale());
}
varianceMin.sort();
varianceMax.sort();
meanMinVariance.add(varianceMin[0]);
meanMaxVariance.add(varianceMax[0]);
LOG_TRACE(<< "Results for run: " << runId);
LOG_TRACE(<< "Mean variance scale = "
<< maths::common::CBasicStatistics::mean(varianceStat));
LOG_TRACE(<< "Variance of variance scale = "
<< maths::common::CBasicStatistics::variance(varianceStat));
LOG_TRACE(<< "Top min variance scale = " << varianceMin);
LOG_TRACE(<< "Top max variance scale = " << varianceMax);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) > 0.98);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) < 1.01);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::variance(varianceStat) < 0.0025);
BOOST_TEST_REQUIRE(varianceMin[0] > 0.85);
BOOST_TEST_REQUIRE(varianceMax[0] < 1.12);
}
LOG_DEBUG(<< "Mean queue size = " << maths::common::CBasicStatistics::mean(meanQueueSize));
LOG_DEBUG(<< "Mean min variance = "
<< maths::common::CBasicStatistics::mean(meanMinVariance));
LOG_DEBUG(<< "Mean max variance = "
<< maths::common::CBasicStatistics::mean(meanMaxVariance));
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(meanMinVariance) > 0.90);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(meanMaxVariance) < 1.1);
}
BOOST_AUTO_TEST_CASE(testQualityOfSamplesGivenVariableRate) {
std::size_t sampleCountFactor(5);
std::size_t latencyBuckets(3);
double growthFactor(0.1);
core_t::TTime bucketLength(600);
unsigned int sampleCount(30);
core_t::TTime latency = (latencyBuckets + 1) * bucketLength;
std::size_t numberOfMeasurements = 5000;
std::size_t numberOfRuns = 100;
test::CRandomNumbers rng;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanQueueSize;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanMinVariance;
maths::common::CBasicStatistics::SSampleMean<double>::TAccumulator meanMaxVariance;
for (std::size_t runId = 0; runId < numberOfRuns; ++runId) {
TSampleVec samples;
core_t::TTime latestTime = bucketLength * (latencyBuckets + 1);
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
for (std::size_t measurementId = 0;
measurementId < numberOfMeasurements; ++measurementId) {
TDoubleVec testData;
rng.generateUniformSamples(static_cast<double>(latestTime - latency),
static_cast<double>(latestTime), 1, testData);
latestTime +=
60 + static_cast<core_t::TTime>(
40.0 * std::sin(boost::math::constants::two_pi<double>() *
static_cast<double>(latestTime % 86400) / 86400.0));
core_t::TTime measurementTime = static_cast<core_t::TTime>(testData[0]);
queue.add(measurementTime, {1.0}, 1u, sampleCount);
}
meanQueueSize.add(queue.size());
queue.sample(latestTime, sampleCount, model_t::E_IndividualMeanByPerson, samples);
maths::common::CBasicStatistics::SSampleMeanVar<double>::TAccumulator varianceStat;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 5u> varianceMin;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 5u, std::greater<double>> varianceMax;
for (std::size_t i = 0; i < samples.size(); ++i) {
varianceStat.add(samples[i].varianceScale());
varianceMin.add(samples[i].varianceScale());
varianceMax.add(samples[i].varianceScale());
}
varianceMin.sort();
varianceMax.sort();
meanMinVariance.add(varianceMin[0]);
meanMaxVariance.add(varianceMax[0]);
LOG_TRACE(<< "Results for run: " << runId);
LOG_TRACE(<< "Mean variance scale = "
<< maths::common::CBasicStatistics::mean(varianceStat));
LOG_TRACE(<< "Variance of variance scale = "
<< maths::common::CBasicStatistics::variance(varianceStat));
LOG_TRACE(<< "Top min variance scale = " << varianceMin);
LOG_TRACE(<< "Top max variance scale = " << varianceMax);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) > 0.97);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) < 1.01);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::variance(varianceStat) < 0.0065);
BOOST_TEST_REQUIRE(varianceMin[0] > 0.74);
BOOST_TEST_REQUIRE(varianceMax[0] < 1.26);
}
LOG_DEBUG(<< "Mean queue size = " << maths::common::CBasicStatistics::mean(meanQueueSize));
LOG_DEBUG(<< "Mean min variance = "
<< maths::common::CBasicStatistics::mean(meanMinVariance));
LOG_DEBUG(<< "Mean max variance = "
<< maths::common::CBasicStatistics::mean(meanMaxVariance));
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(meanMinVariance) > 0.82);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(meanMaxVariance) < 1.16);
}
BOOST_AUTO_TEST_CASE(testQualityOfSamplesGivenHighLatencyAndDataInReverseOrder) {
std::size_t sampleCountFactor(5);
std::size_t latencyBuckets(500);
double growthFactor(0.1);
core_t::TTime bucketLength(600);
unsigned int sampleCount(30);
std::size_t numberOfMeasurements = 5000;
test::CRandomNumbers rng;
TSampleVec samples;
core_t::TTime latestTime = 60 * numberOfMeasurements;
core_t::TTime time = latestTime;
TTestSampleQueue queue(1, sampleCountFactor, latencyBuckets, growthFactor, bucketLength);
for (std::size_t measurementId = 0; measurementId < numberOfMeasurements; ++measurementId) {
queue.add(time, {1.0}, 1u, sampleCount);
time -= 60;
}
queue.add(360000, {1.0}, 1u, sampleCount);
queue.sample(latestTime, sampleCount, model_t::E_IndividualMeanByPerson, samples);
maths::common::CBasicStatistics::SSampleMeanVar<double>::TAccumulator varianceStat;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 1u> varianceMin;
maths::common::CBasicStatistics::COrderStatisticsStack<double, 1u, std::greater<double>> varianceMax;
for (std::size_t i = 0; i < samples.size(); ++i) {
varianceStat.add(samples[i].varianceScale());
varianceMin.add(samples[i].varianceScale());
varianceMax.add(samples[i].varianceScale());
}
LOG_DEBUG(<< "Mean variance scale = "
<< maths::common::CBasicStatistics::mean(varianceStat));
LOG_DEBUG(<< "Variance of variance scale = "
<< maths::common::CBasicStatistics::variance(varianceStat));
LOG_DEBUG(<< "Min variance scale = " << varianceMin[0]);
LOG_DEBUG(<< "Max variance scale = " << varianceMax[0]);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) >= 0.999);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::mean(varianceStat) <= 1.0);
BOOST_TEST_REQUIRE(maths::common::CBasicStatistics::variance(varianceStat) <= 0.0001);
BOOST_TEST_REQUIRE(varianceMin[0] > 0.96);
BOOST_TEST_REQUIRE(varianceMax[0] <= 1.0);
}
BOOST_AUTO_TEST_SUITE_END()