diff options
Diffstat (limited to 'src/lib/stats/tests/observation_unittest.cc')
-rw-r--r-- | src/lib/stats/tests/observation_unittest.cc | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/src/lib/stats/tests/observation_unittest.cc b/src/lib/stats/tests/observation_unittest.cc new file mode 100644 index 0000000..63fbece --- /dev/null +++ b/src/lib/stats/tests/observation_unittest.cc @@ -0,0 +1,717 @@ +// Copyright (C) 2015-2023 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <exceptions/exceptions.h> +#include <stats/observation.h> +#include <util/chrono_time_utils.h> +#include <util/bigints.h> + +#include <boost/shared_ptr.hpp> + +#include <gtest/gtest.h> + +#include <iostream> +#include <sstream> + +#include <unistd.h> + +using namespace isc; +using namespace isc::stats; +using namespace isc::util; +using namespace std::chrono; + +namespace { + +static const StatsDuration& dur1234(hours(1) + minutes(2) + seconds(3) + + milliseconds(4)); +static const StatsDuration& dur5678(hours(5) + minutes(6) + seconds(7) + + milliseconds(8)); +static const StatsDuration& dur681012(hours(6) + minutes(8) + seconds(10) + + milliseconds(12)); +static const StatsDuration& dur453(minutes(4) + seconds(5) + milliseconds(3)); + +// This test verifies that the number of seconds can be retrieved. +TEST(StatsDurationTest, toSeconds) { + StatsDuration dur = StatsDuration::zero(); + dur += hours(1) + minutes(1) + seconds(1) + milliseconds(1); + EXPECT_EQ(3661, toSeconds(dur)); +} + +/// @brief Test class for Observation +/// +/// This simple fixture class initializes four observations: +/// a (integer), b (float), c(time duration) and d (string). +class ObservationTest : public ::testing::Test { +public: + + /// @brief Constructor + /// Initializes four observations. + ObservationTest() : + a("alpha", static_cast<int64_t>(1234)), // integer + b("beta", 12.34), // float + c("gamma", dur1234), // duration + d("delta", "1234"), // string + e("epsilon", int128_t(12e34)) { // big integer + } + + Observation a; + Observation b; + Observation c; + Observation d; + Observation e; +}; + +// Basic tests for the Observation constructors. This test checks whether +// parameters passed to the constructor initialize the object properly. +TEST_F(ObservationTest, constructor) { + EXPECT_EQ(Observation::STAT_INTEGER, a.getType()); + EXPECT_EQ(Observation::STAT_FLOAT, b.getType()); + EXPECT_EQ(Observation::STAT_DURATION, c.getType()); + EXPECT_EQ(Observation::STAT_STRING, d.getType()); + EXPECT_EQ(Observation::STAT_BIG_INTEGER, e.getType()); + + EXPECT_EQ(1234, a.getInteger().first); + EXPECT_EQ(12.34, b.getFloat().first); + EXPECT_EQ(dur1234, c.getDuration().first); + EXPECT_EQ("1234", d.getString().first); + EXPECT_EQ(int128_t(12e34), e.getBigInteger().first); + + // Let's check that attempting to get a different type + // than used will cause an exception. + EXPECT_THROW(a.getFloat(), InvalidStatType); + EXPECT_THROW(a.getDuration(), InvalidStatType); + EXPECT_THROW(a.getString(), InvalidStatType); + EXPECT_THROW(a.getBigInteger(), InvalidStatType); + + EXPECT_THROW(b.getInteger(), InvalidStatType); + EXPECT_THROW(b.getDuration(), InvalidStatType); + EXPECT_THROW(b.getString(), InvalidStatType); + EXPECT_THROW(b.getBigInteger(), InvalidStatType); + + EXPECT_THROW(c.getInteger(), InvalidStatType); + EXPECT_THROW(c.getFloat(), InvalidStatType); + EXPECT_THROW(c.getString(), InvalidStatType); + EXPECT_THROW(c.getBigInteger(), InvalidStatType); + + EXPECT_THROW(d.getInteger(), InvalidStatType); + EXPECT_THROW(d.getFloat(), InvalidStatType); + EXPECT_THROW(d.getDuration(), InvalidStatType); + EXPECT_THROW(d.getBigInteger(), InvalidStatType); + + EXPECT_THROW(e.getInteger(), InvalidStatType); + EXPECT_THROW(e.getFloat(), InvalidStatType); + EXPECT_THROW(e.getDuration(), InvalidStatType); + EXPECT_THROW(e.getString(), InvalidStatType); +} + +// This test checks whether it is possible to set to an absolute value for all +// given types. +TEST_F(ObservationTest, setValue) { + EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678))); + EXPECT_NO_THROW(b.setValue(56e+78)); + EXPECT_NO_THROW(c.setValue(dur5678)); + EXPECT_NO_THROW(d.setValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.setValue(int128_t(43e21))); + + EXPECT_EQ(5678, a.getInteger().first); + EXPECT_EQ(56e+78, b.getFloat().first); + EXPECT_EQ(dur5678, c.getDuration().first); + EXPECT_EQ("fiveSixSevenEight", d.getString().first); + EXPECT_EQ(int128_t(43e21), e.getBigInteger().first); + + // Now check whether setting value to a different type does + // throw an exception + EXPECT_THROW(a.setValue(56e+78), InvalidStatType); + EXPECT_THROW(a.setValue(dur5678), InvalidStatType); + EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(a.setValue(int128_t(43e21)), InvalidStatType); + + EXPECT_THROW(b.setValue(static_cast<int64_t>(5678)), InvalidStatType); + EXPECT_THROW(b.setValue(dur5678), InvalidStatType); + EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(b.setValue(int128_t(43e21)), InvalidStatType); + + EXPECT_THROW(c.setValue(static_cast<int64_t>(5678)), InvalidStatType); + EXPECT_THROW(c.setValue(56e+78), InvalidStatType); + EXPECT_THROW(c.setValue("fiveSixSevenEight"), InvalidStatType); + EXPECT_THROW(c.setValue(int128_t(43e21)), InvalidStatType); + + EXPECT_THROW(d.setValue(static_cast<int64_t>(5678)), InvalidStatType); + EXPECT_THROW(d.setValue(56e+78), InvalidStatType); + EXPECT_THROW(d.setValue(dur5678), InvalidStatType); + EXPECT_THROW(d.setValue(int128_t(43e21)), InvalidStatType); + + EXPECT_THROW(e.setValue(int64_t(5678)), InvalidStatType); + EXPECT_THROW(e.setValue(56e+78), InvalidStatType); + EXPECT_THROW(e.setValue(dur5678), InvalidStatType); + EXPECT_THROW(e.setValue("fiveSixSevenEight"), InvalidStatType); +} + +// This test checks whether it is possible to add value to existing +// counter. +TEST_F(ObservationTest, addValue) { + // Note: all Observations were set to 1234, 12.34 or similar in + // ObservationTest constructor. + + EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678))); + EXPECT_NO_THROW(b.addValue(56.78)); + EXPECT_NO_THROW(c.addValue(dur5678)); + EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); + + EXPECT_EQ(6912, a.getInteger().first); + EXPECT_EQ(69.12, b.getFloat().first); + EXPECT_EQ(dur681012, c.getDuration().first); + EXPECT_EQ("1234fiveSixSevenEight", d.getString().first); + EXPECT_EQ(int128_t(12e34) + int128_t(43e21), e.getBigInteger().first); + + ASSERT_EQ(a.getSize(), 2); + ASSERT_EQ(b.getSize(), 2); + ASSERT_EQ(c.getSize(), 2); + ASSERT_EQ(d.getSize(), 2); + ASSERT_EQ(e.getSize(), 2); +} + +// This test checks if collecting more than one sample +// works well. +TEST_F(ObservationTest, moreThanOne) { + // Arrays of 4 types of samples + int64_t int_samples[3] = {1234, 6912, 5678}; + double float_samples[3] = {12.34, 69.12, 56e+78}; + StatsDuration duration_samples[3] = {dur1234, dur681012, dur5678}; + std::string string_samples[3] = {"1234", "1234fiveSixSevenEight", "fiveSixSevenEight"}; + int128_t bigint_samples[3] = {int128_t(12e34), int128_t(12e34) + int128_t(43e21), + int128_t(43e21)}; + + EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678))); + EXPECT_NO_THROW(b.addValue(56.78)); + EXPECT_NO_THROW(c.addValue(dur5678)); + EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); + + EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678))); + EXPECT_NO_THROW(b.setValue(56e+78)); + EXPECT_NO_THROW(c.setValue(dur5678)); + EXPECT_NO_THROW(d.setValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.setValue(int128_t(43e21))); + + ASSERT_EQ(a.getSize(), 3); + ASSERT_EQ(b.getSize(), 3); + ASSERT_EQ(c.getSize(), 3); + ASSERT_EQ(d.getSize(), 3); + ASSERT_EQ(e.getSize(), 3); + + ASSERT_NO_THROW(a.getIntegers()); + ASSERT_NO_THROW(b.getFloats()); + ASSERT_NO_THROW(c.getDurations()); + ASSERT_NO_THROW(d.getStrings()); + ASSERT_NO_THROW(e.getBigIntegers()); + + std::list<IntegerSample> samples_int = a.getIntegers(); // List of all integer samples + std::list<FloatSample> samples_float = b.getFloats(); // List of all float samples + std::list<DurationSample> samples_dur = c.getDurations(); // List of all duration samples + std::list<StringSample> samples_str = d.getStrings(); // List of all string samples + std::list<BigIntegerSample> samples_bigint = e.getBigIntegers(); // List of all big integer samples + + uint32_t i = 2; // Index pointed to the end of array of samples + for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { + EXPECT_EQ(int_samples[i], static_cast<int64_t>((*it).first)); + --i; + } + i = 2; + for (std::list<FloatSample>::iterator it = samples_float.begin(); it != samples_float.end(); ++it) { + EXPECT_EQ(float_samples[i], (*it).first); + --i; + } + i = 2; + for (std::list<DurationSample>::iterator it = samples_dur.begin(); it != samples_dur.end(); ++it) { + EXPECT_EQ(duration_samples[i], (*it).first); + --i; + } + i = 2; + for (std::list<StringSample>::iterator it = samples_str.begin(); it != samples_str.end(); ++it) { + EXPECT_EQ(string_samples[i], (*it).first); + --i; + } + i = 2; + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(bigint_samples[i], sample.first); + --i; + } +} + +// This test checks whether the size of storage +// is equal to the true value +TEST_F(ObservationTest, getSize) { + // Check if size of storages is equal to 1 + ASSERT_EQ(a.getSize(), 1); + ASSERT_EQ(b.getSize(), 1); + ASSERT_EQ(c.getSize(), 1); + ASSERT_EQ(d.getSize(), 1); + ASSERT_EQ(e.getSize(), 1); + + a.addValue(static_cast<int64_t>(5678)); + b.addValue(56.78); + c.addValue(dur5678); + d.addValue("fiveSixSevenEight"); + e.addValue(int128_t(43e21)); + + EXPECT_NO_THROW(a.getSize()); + EXPECT_NO_THROW(b.getSize()); + EXPECT_NO_THROW(c.getSize()); + EXPECT_NO_THROW(d.getSize()); + EXPECT_NO_THROW(e.getSize()); + + // Check if size of storages is equal to 2 + ASSERT_EQ(a.getSize(), 2); + ASSERT_EQ(b.getSize(), 2); + ASSERT_EQ(c.getSize(), 2); + ASSERT_EQ(d.getSize(), 2); + ASSERT_EQ(e.getSize(), 2); + + a.setValue(static_cast<int64_t>(5678)); + b.setValue(56e+78); + c.setValue(dur5678); + d.setValue("fiveSixSevenEight"); + e.setValue(int128_t(43e21)); + + EXPECT_NO_THROW(a.getSize()); + EXPECT_NO_THROW(b.getSize()); + EXPECT_NO_THROW(c.getSize()); + EXPECT_NO_THROW(d.getSize()); + + // Check if size of storages is equal to 3 + ASSERT_EQ(a.getSize(), 3); + ASSERT_EQ(b.getSize(), 3); + ASSERT_EQ(c.getSize(), 3); + ASSERT_EQ(d.getSize(), 3); + ASSERT_EQ(e.getSize(), 3); +} + +// Checks whether setting amount limits works properly +TEST_F(ObservationTest, setCountLimit) { + // Preparing of 21 test's samples for each type of storage + int64_t int_samples[22] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21}; + double float_samples[22] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, + 20.0, 21.0}; + std::string string_samples[22] = {"a", "b", "c", "d", "e", "f", "g", "h", + "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", + "v"}; + StatsDuration duration_samples[22]; + + for (uint32_t i = 0; i < 22; ++i) { + duration_samples[i] = milliseconds(i); + } + + // By default the max_sample_count is set to 20 and max_sample_age + // is deactivated + // Adding 21 samples to each type of Observation + for (uint32_t i = 0; i < 21; ++i) { + a.setValue(int_samples[i]); + } + for (uint32_t i = 0; i < 21; ++i) { + b.setValue(float_samples[i]); + } + for (uint32_t i = 0; i < 21; ++i) { + c.setValue(duration_samples[i]); + } + for (uint32_t i = 0; i < 21; ++i) { + d.setValue(string_samples[i]); + } + for (uint32_t i = 0; i < 21; ++i) { + e.setValue(int128_t(int_samples[i])); + } + + // Getting all 4 types of samples after inserting 21 values + std::list<IntegerSample> samples_int = a.getIntegers(); + std::list<FloatSample> samples_float = b.getFloats(); + std::list<DurationSample> samples_duration = c.getDurations(); + std::list<StringSample> samples_string = d.getStrings(); + std::list<BigIntegerSample> samples_bigint = e.getBigIntegers(); + + // Check if size of storages is equal to 20 + ASSERT_EQ(a.getSize(), 20); + ASSERT_EQ(b.getSize(), 20); + ASSERT_EQ(c.getSize(), 20); + ASSERT_EQ(d.getSize(), 20); + ASSERT_EQ(e.getSize(), 20); + + // And whether stored values are correct + uint32_t i = 20; // index of the last element in array of test's samples + for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { + EXPECT_EQ((*it).first, int_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<FloatSample>::iterator it = samples_float.begin(); it != samples_float.end(); ++it) { + EXPECT_EQ((*it).first, float_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<DurationSample>::iterator it = samples_duration.begin(); it != samples_duration.end(); ++it) { + EXPECT_EQ((*it).first, duration_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<StringSample>::iterator it = samples_string.begin(); it != samples_string.end(); ++it) { + EXPECT_EQ((*it).first, string_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } + + // Change size of storage to smaller one + ASSERT_NO_THROW(a.setMaxSampleCount(10)); + ASSERT_NO_THROW(b.setMaxSampleCount(10)); + ASSERT_NO_THROW(c.setMaxSampleCount(10)); + ASSERT_NO_THROW(d.setMaxSampleCount(10)); + ASSERT_NO_THROW(e.setMaxSampleCount(10)); + + samples_int = a.getIntegers(); + samples_float = b.getFloats(); + samples_duration = c.getDurations(); + samples_string = d.getStrings(); + samples_bigint = e.getBigIntegers(); + + // Check if size of storages is equal to 10 + ASSERT_EQ(a.getSize(), 10); + ASSERT_EQ(b.getSize(), 10); + ASSERT_EQ(c.getSize(), 10); + ASSERT_EQ(d.getSize(), 10); + ASSERT_EQ(e.getSize(), 10); + + // And whether storages contain only the 10 newest values + i = 20; // index of last element in array of test's samples + for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { + EXPECT_EQ((*it).first, int_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<FloatSample>::iterator it = samples_float.begin(); it != samples_float.end(); ++it) { + EXPECT_EQ((*it).first, float_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<DurationSample>::iterator it = samples_duration.begin(); it != samples_duration.end(); ++it) { + EXPECT_EQ((*it).first, duration_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (std::list<StringSample>::iterator it = samples_string.begin(); it != samples_string.end(); ++it) { + EXPECT_EQ((*it).first, string_samples[i]); + --i; + } + i = 20; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } + + // Resize max_sample_count to greater + ASSERT_NO_THROW(a.setMaxSampleCount(50)); + ASSERT_NO_THROW(b.setMaxSampleCount(50)); + ASSERT_NO_THROW(c.setMaxSampleCount(50)); + ASSERT_NO_THROW(d.setMaxSampleCount(50)); + ASSERT_NO_THROW(e.setMaxSampleCount(50)); + + // Check if size of storages did not change without adding new value + ASSERT_EQ(a.getSize(), 10); + ASSERT_EQ(b.getSize(), 10); + ASSERT_EQ(c.getSize(), 10); + ASSERT_EQ(d.getSize(), 10); + ASSERT_EQ(e.getSize(), 10); + + // Add new values to each type of Observation + a.setValue(static_cast<int64_t>(21)); + b.setValue(21.0); + c.setValue(milliseconds(21)); + d.setValue("v"); + e.setValue(int128_t(21)); + + samples_int = a.getIntegers(); + samples_float = b.getFloats(); + samples_duration = c.getDurations(); + samples_string = d.getStrings(); + samples_bigint = e.getBigIntegers(); + + ASSERT_EQ(a.getSize(), 11); + ASSERT_EQ(b.getSize(), 11); + ASSERT_EQ(c.getSize(), 11); + ASSERT_EQ(d.getSize(), 11); + ASSERT_EQ(e.getSize(), 11); + + i = 21; // index of last element in array of test's samples + for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) { + EXPECT_EQ((*it).first, int_samples[i]); + --i; + } + i = 21; // index of last element in array of test's samples + for (std::list<FloatSample>::iterator it = samples_float.begin(); it != samples_float.end(); ++it) { + EXPECT_EQ((*it).first, float_samples[i]); + --i; + } + i = 21; // index of last element in array of test's samples + for (std::list<DurationSample>::iterator it = samples_duration.begin(); it != samples_duration.end(); ++it) { + EXPECT_EQ((*it).first, duration_samples[i]); + --i; + } + i = 21; // index of last element in array of test's samples + for (std::list<StringSample>::iterator it = samples_string.begin(); it != samples_string.end(); ++it) { + EXPECT_EQ((*it).first, string_samples[i]); + --i; + } + i = 21; // index of last element in array of test's samples + for (BigIntegerSample const& sample : samples_bigint) { + EXPECT_EQ(sample.first, int_samples[i]); + --i; + } +} + +// Checks whether setting age limits works properly +TEST_F(ObservationTest, setAgeLimit) { + // Set max_sample_age to 1 second + ASSERT_NO_THROW(c.setMaxSampleAge(seconds(1))); + // Add some value + c.setValue(milliseconds(5)); + // Wait 1 second + sleep(1); + // and add new value + c.setValue(milliseconds(3)); + + // get the list of all samples + std::list<DurationSample> samples_duration = c.getDurations(); + // check whether the size of samples is equal to 1 + ASSERT_EQ(c.getSize(), 1); + // and whether it contains an expected value + EXPECT_EQ((*samples_duration.begin()).first, milliseconds(3)); + + // Wait 1 second to ensure removing previously set value + sleep(1); + // add 10 new values + for (uint32_t i = 0; i < 10; ++i) { + c.setValue(milliseconds(i)); + } + // change the max_sample_age to smaller + ASSERT_NO_THROW(c.setMaxSampleAge(milliseconds(300))); + + samples_duration = c.getDurations(); + // check whether the size of samples is equal to 10 + ASSERT_EQ(c.getSize(), 10); + + // and whether it contains expected values + uint32_t i = 9; + for (std::list<DurationSample>::iterator it = samples_duration.begin(); it != samples_duration.end(); ++it) { + EXPECT_EQ((*it).first, milliseconds(i)); + --i; + } +} + +// Test checks whether we can get max_sample_age_ and max_sample_count_ +// properly. +TEST_F(ObservationTest, getLimits) { + // First checks whether getting default values works properly + EXPECT_EQ(a.getMaxSampleAge().first, false); + EXPECT_EQ(b.getMaxSampleAge().first, false); + EXPECT_EQ(c.getMaxSampleAge().first, false); + EXPECT_EQ(d.getMaxSampleAge().first, false); + EXPECT_EQ(e.getMaxSampleAge().first, false); + + EXPECT_EQ(a.getMaxSampleCount().first, true); + EXPECT_EQ(b.getMaxSampleCount().first, true); + EXPECT_EQ(c.getMaxSampleCount().first, true); + EXPECT_EQ(d.getMaxSampleCount().first, true); + EXPECT_EQ(e.getMaxSampleCount().first, true); + + EXPECT_EQ(a.getMaxSampleCount().second, 20); + EXPECT_EQ(b.getMaxSampleCount().second, 20); + EXPECT_EQ(c.getMaxSampleCount().second, 20); + EXPECT_EQ(d.getMaxSampleCount().second, 20); + EXPECT_EQ(e.getMaxSampleCount().second, 20); + + // change limit to time duration + ASSERT_NO_THROW(a.setMaxSampleAge(dur453)); + ASSERT_NO_THROW(b.setMaxSampleAge(dur453)); + ASSERT_NO_THROW(c.setMaxSampleAge(dur453)); + ASSERT_NO_THROW(d.setMaxSampleAge(dur453)); + ASSERT_NO_THROW(e.setMaxSampleAge(dur453)); + + EXPECT_EQ(a.getMaxSampleAge().first, true); + EXPECT_EQ(b.getMaxSampleAge().first, true); + EXPECT_EQ(c.getMaxSampleAge().first, true); + EXPECT_EQ(d.getMaxSampleAge().first, true); + EXPECT_EQ(e.getMaxSampleAge().first, true); + + EXPECT_EQ(a.getMaxSampleAge().second, dur453); + EXPECT_EQ(b.getMaxSampleAge().second, dur453); + EXPECT_EQ(c.getMaxSampleAge().second, dur453); + EXPECT_EQ(d.getMaxSampleAge().second, dur453); + EXPECT_EQ(e.getMaxSampleAge().second, dur453); + + EXPECT_EQ(a.getMaxSampleCount().first, false); + EXPECT_EQ(b.getMaxSampleCount().first, false); + EXPECT_EQ(c.getMaxSampleCount().first, false); + EXPECT_EQ(d.getMaxSampleCount().first, false); + EXPECT_EQ(e.getMaxSampleCount().first, false); + + EXPECT_EQ(a.getMaxSampleCount().second, 20); + EXPECT_EQ(b.getMaxSampleCount().second, 20); + EXPECT_EQ(c.getMaxSampleCount().second, 20); + EXPECT_EQ(d.getMaxSampleCount().second, 20); + EXPECT_EQ(e.getMaxSampleCount().second, 20); +} + +// limit defaults are tested with StatsMgr. + +// Test checks whether timing is reported properly. +TEST_F(ObservationTest, timers) { + auto before = SampleClock::now(); + b.setValue(123.0); // Set it to a random value and record the time. + + // Allow a bit of imprecision. This test allows 500ms. That should be ok, + // when running on virtual machines. + auto after = before + milliseconds(500); + + // Now wait some time. We want to confirm that the timestamp recorded is the + // time the observation took place, not current time. + sleep(1); + + FloatSample sample = b.getFloat(); + + // Let's check that the timestamp is within (before, after) range: + // before < sample-time < after + EXPECT_TRUE(before <= sample.second); + EXPECT_TRUE(sample.second <= after); +} + +// Checks whether an integer statistic can generate proper JSON structures. +// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design +/// for details. +TEST_F(ObservationTest, integerToJSON) { + // String which contains first added sample + std::string first_sample = ", [ 1234, \"" + + isc::util::clockToText(a.getInteger().second) + "\" ] ]"; + + a.setValue(static_cast<int64_t>(1234)); + + std::string exp = "[ [ 1234, \"" + + isc::util::clockToText(a.getInteger().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, a.getJSON()->str()); +} + +// Checks whether a floating point statistic can generate proper JSON +// structures. See +/// https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design +/// for details. +TEST_F(ObservationTest, floatToJSON) { + // String which contains first added sample + std::string first_sample = ", [ 12.34, \"" + + isc::util::clockToText(b.getFloat().second) + "\" ] ]"; + + // Let's use a value that converts easily to floating point. + // No need to deal with infinite fractions in binary systems. + + b.setValue(1234.5); + + std::string exp = "[ [ 1234.5, \"" + + isc::util::clockToText(b.getFloat().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, b.getJSON()->str()); +} + +// Checks whether a time duration statistic can generate proper JSON structures. +// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design for +// details. +TEST_F(ObservationTest, durationToJSON) { + // String which contains first added sample + std::string first_sample = ", [ \"01:02:03.004000\", \"" + + isc::util::clockToText(c.getDuration().second) + "\" ] ]"; + + // 1 hour 2 minutes 3 seconds and 4 milliseconds + c.setValue(dur1234); + + std::string exp = "[ [ \"01:02:03.004000\", \"" + + isc::util::clockToText(c.getDuration().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, c.getJSON()->str()); +} + +// Checks whether a string statistic can generate proper JSON structures. +// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design +// for details. +TEST_F(ObservationTest, stringToJSON) { + // String which contains first added sample + std::string first_sample = ", [ \"1234\", \"" + + isc::util::clockToText(d.getString().second) + "\" ] ]"; + + d.setValue("Lorem ipsum dolor sit amet"); + + std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" + + isc::util::clockToText(d.getString().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, d.getJSON()->str()); +} + +// Checks whether a big integer statistic can generate proper JSON structures. +// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design +// for details. +TEST_F(ObservationTest, bigIntegerToJSON) { + // String which contains first added sample + std::string first_sample = ", [ 120000000000000007304085773727301632, \"" + + isc::util::clockToText(e.getBigInteger().second) + "\" ] ]"; + + e.setValue(int128_t(43e21)); + + std::string exp = "[ [ 43000000000000002097152, \"" + + isc::util::clockToText(e.getBigInteger().second) + "\" ]" + first_sample; + + EXPECT_EQ(exp, e.getJSON()->str()); +} + +// Checks whether reset() resets the statistics properly. +TEST_F(ObservationTest, reset) { + EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678))); + EXPECT_NO_THROW(b.addValue(56.78)); + EXPECT_NO_THROW(c.addValue(dur5678)); + EXPECT_NO_THROW(d.addValue("fiveSixSevenEight")); + EXPECT_NO_THROW(e.addValue(int128_t(43e21))); + + a.reset(); // integer + b.reset(); // float + c.reset(); // duration + d.reset(); // string + e.reset(); // big integer + + EXPECT_EQ(0, a.getInteger().first); + EXPECT_EQ(0.0, b.getFloat().first); + EXPECT_EQ(StatsDuration::zero(), c.getDuration().first); + EXPECT_EQ("", d.getString().first); + EXPECT_EQ(0, e.getBigInteger().first); + + ASSERT_EQ(a.getSize(), 1); + ASSERT_EQ(b.getSize(), 1); + ASSERT_EQ(c.getSize(), 1); + ASSERT_EQ(d.getSize(), 1); + ASSERT_EQ(e.getSize(), 1); +} + +// Checks whether an observation can keep its name. +TEST_F(ObservationTest, names) { + EXPECT_EQ("alpha", a.getName()); + EXPECT_EQ("beta", b.getName()); + EXPECT_EQ("gamma", c.getName()); + EXPECT_EQ("delta", d.getName()); + EXPECT_EQ("epsilon", e.getName()); +} + +} // namespace |