From c7c467230c90693ae11d793e95fb5c22005edb84 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Thu, 4 Jan 2024 22:05:58 +0100 Subject: [PATCH] test: add speedometer test --- CMakeLists.txt | 1 + include/dwarfs/speedometer.h | 24 ++++++---- test/speedometer_test.cpp | 90 ++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 test/speedometer_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b8cae422..69cac3ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -608,6 +608,7 @@ if(WITH_TESTS) metadata_requirements_test pcm_sample_transformer_test pcmaudio_categorizer_test + speedometer_test terminal_test tool_main_test tools_test diff --git a/include/dwarfs/speedometer.h b/include/dwarfs/speedometer.h index b508212d..8a28e10b 100644 --- a/include/dwarfs/speedometer.h +++ b/include/dwarfs/speedometer.h @@ -26,14 +26,17 @@ namespace dwarfs { -template -class speedometer { +template +class basic_speedometer { public: - speedometer(std::chrono::milliseconds window_length) + using clock_type = ClockT; + using value_type = ValueT; + + basic_speedometer(std::chrono::milliseconds window_length) : window_length_{window_length} {} - void put(T s) { - auto now = std::chrono::steady_clock::now(); + void put(value_type s) { + auto now = clock_type::now(); auto old = now - window_length_; while (!samples_.empty() && samples_.front().first < old) { @@ -43,9 +46,9 @@ class speedometer { samples_.emplace_back(now, s); } - T num_per_second() const { + value_type num_per_second() const { if (samples_.size() < 2) { - return T(); + return value_type(); } auto const& first = samples_.front(); auto const& last = samples_.back(); @@ -53,14 +56,17 @@ class speedometer { auto const dv = last.second - first.second; auto const elapsed_ms = std::chrono::duration_cast(dt).count(); - return elapsed_ms > 0 ? (1000 * dv) / elapsed_ms : T(); + return elapsed_ms > 0 ? (1000 * dv) / elapsed_ms : value_type(); } void clear() { samples_.clear(); } private: - std::deque> samples_; + std::deque> samples_; std::chrono::milliseconds window_length_; }; +template +using speedometer = basic_speedometer; + } // namespace dwarfs diff --git a/test/speedometer_test.cpp b/test/speedometer_test.cpp new file mode 100644 index 00000000..859897d1 --- /dev/null +++ b/test/speedometer_test.cpp @@ -0,0 +1,90 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#include +#include + +#include "dwarfs/speedometer.h" + +using namespace dwarfs; + +namespace { + +class mock_clock { + public: + using duration = std::chrono::microseconds; + using time_point = std::chrono::time_point; + + static time_point now() { return now_; } + + static void advance(duration d) { now_ += d; } + + private: + static thread_local inline time_point now_; +}; + +template +using test_speedometer = basic_speedometer; + +} // namespace + +TEST(speedometer_test, basic) { + using namespace std::chrono_literals; + + test_speedometer s{2s}; + + EXPECT_EQ(0, s.num_per_second()); + + mock_clock::advance(250ms); + s.put(10000); + + EXPECT_EQ(0, s.num_per_second()); + + mock_clock::advance(250ms); // [250ms, 500ms] + s.put(20000); // [10000 -> 20000] + + EXPECT_EQ(40000, s.num_per_second()); + + mock_clock::advance(750ms); // [250ms, 1250ms] + s.put(90000); // [10000 -> 90000] + + EXPECT_EQ(80000, s.num_per_second()); + + mock_clock::advance(500ms); // [250ms, 1750ms] + s.put(115000); // [10000 -> 115000] + + EXPECT_EQ(70000, s.num_per_second()); + + mock_clock::advance(500ms); // [250ms, 2250ms] + s.put(130000); // [10000 -> 130000] + + EXPECT_EQ(60000, s.num_per_second()); + + mock_clock::advance(500ms); // [1250ms, 2750ms] + s.put(150000); // [90000 -> 150000] + + EXPECT_EQ(40000, s.num_per_second()); + + mock_clock::advance(750ms); // [1750ms, 3500ms] + s.put(176250); // [115000 -> 176250] + + EXPECT_EQ(35000, s.num_per_second()); +}