From cb46f466339d66307effafc37b496ca083bab8f0 Mon Sep 17 00:00:00 2001 From: Kerstin Keller Date: Thu, 20 Jun 2024 17:22:00 +0200 Subject: [PATCH] [core] Expmap takes additional template parameter for clock type. This improves testability and allows to expire based on different time base, if required. --- ecal/core/src/util/ecal_expmap.h | 15 ++-- .../tests/cpp/expmap_test/src/expmap_test.cpp | 75 +++++++++++++------ 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/ecal/core/src/util/ecal_expmap.h b/ecal/core/src/util/ecal_expmap.h index 9726c8d42..9d41864ad 100644 --- a/ecal/core/src/util/ecal_expmap.h +++ b/ecal/core/src/util/ecal_expmap.h @@ -41,15 +41,14 @@ namespace eCAL **/ template, class Alloc = std::allocator > > class CExpMap { public: - using clock_type = std::chrono::steady_clock; - // Key access history, most recent at back - using key_tracker_type = std::list>; + using key_tracker_type = std::list>; // Key to value and key history iterator using key_to_value_type = std::map>; @@ -147,12 +146,12 @@ namespace eCAL // Constructor specifies the timeout of the map CExpMap() : _timeout(std::chrono::milliseconds(5000)) {}; - explicit CExpMap(clock_type::duration t) : _timeout(t) {}; + explicit CExpMap(typename clock_type::duration t) : _timeout(t) {}; /** * @brief set expiration time **/ - void set_expiration(clock_type::duration t) { _timeout = t; }; + void set_expiration(typename clock_type::duration t) { _timeout = t; }; // Iterators: iterator begin() noexcept @@ -261,7 +260,7 @@ namespace eCAL { // Assert method is never called when cache is empty //assert(!_key_tracker.empty()); - clock_type::time_point eviction_limit = get_curr_time() - _timeout; + typename clock_type::time_point eviction_limit = get_curr_time() - _timeout; auto it(_key_tracker.begin()); @@ -328,7 +327,7 @@ namespace eCAL return ret; } - clock_type::time_point get_curr_time() + typename clock_type::time_point get_curr_time() { return clock_type::now(); } @@ -340,7 +339,7 @@ namespace eCAL key_to_value_type _key_to_value; // Timeout of map - clock_type::duration _timeout; + typename clock_type::duration _timeout; }; } } diff --git a/ecal/tests/cpp/expmap_test/src/expmap_test.cpp b/ecal/tests/cpp/expmap_test/src/expmap_test.cpp index 224eae6af..8fbe3993e 100644 --- a/ecal/tests/cpp/expmap_test/src/expmap_test.cpp +++ b/ecal/tests/cpp/expmap_test/src/expmap_test.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,10 +27,41 @@ #include +class TestingClock { +public: + // Define the required types for TrivialClock + using duration = std::chrono::milliseconds; + using rep = duration::rep; + using period = duration::period; + using time_point = std::chrono::time_point; + static const bool is_steady = false; + + // Function to get the current time + static time_point now() noexcept { + return time_point(current_time); + } + + // Function to manually set the current time + static void set_time(const time_point& tp) { + current_time = tp.time_since_epoch(); + } + + // Function to manually increment the current time by a given duration + static void increment_time(const duration& d) { + current_time += d; + } + +private: + static duration current_time; +}; + +// Initialize the static member +TestingClock::duration TestingClock::current_time{ 0 }; + TEST(core_cpp_core, ExpMap_SetGet) { // create the map with 2500 ms expiration - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); // set "A" expmap["A"] = 1; @@ -43,7 +74,7 @@ TEST(core_cpp_core, ExpMap_SetGet) EXPECT_EQ(1, expmap.size()); // sleep - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); // access and reset timer EXPECT_EQ(1, expmap["A"]); @@ -54,7 +85,7 @@ TEST(core_cpp_core, ExpMap_SetGet) EXPECT_EQ(1, expmap.size()); // sleep - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); // check size //content = expmap.clone(); @@ -62,7 +93,7 @@ TEST(core_cpp_core, ExpMap_SetGet) EXPECT_EQ(1, expmap.size()); // sleep - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); // check size //content = expmap.clone(); @@ -70,25 +101,25 @@ TEST(core_cpp_core, ExpMap_SetGet) EXPECT_EQ(0, expmap.size()); expmap["A"] = 1; - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); expmap["B"] = 2; expmap["C"] = 3; expmap.remove_deprecated(); EXPECT_EQ(3, expmap.size()); - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); expmap["B"] = 4; expmap.remove_deprecated(); EXPECT_EQ(2, expmap.size()); - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); expmap.remove_deprecated(); EXPECT_EQ(1, expmap.size()); // sleep - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + TestingClock::increment_time(std::chrono::milliseconds(150)); } TEST(core_cpp_core, ExpMap_Insert) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); auto ret = expmap.insert(std::make_pair("A", 1)); auto key = (*ret.first).first; @@ -100,7 +131,7 @@ TEST(core_cpp_core, ExpMap_Insert) EXPECT_EQ(i, 1); - std::this_thread::sleep_for(std::chrono::milliseconds(300)); + TestingClock::increment_time(std::chrono::milliseconds(300)); expmap.remove_deprecated(); EXPECT_EQ(0, expmap.size()); } @@ -108,7 +139,7 @@ TEST(core_cpp_core, ExpMap_Insert) // This tests uses find to find an element TEST(core_cpp_core, ExpMap_Find) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); auto it = expmap.find("A"); EXPECT_EQ(expmap.end(), it); @@ -119,7 +150,7 @@ TEST(core_cpp_core, ExpMap_Find) int i = (*it).second; EXPECT_EQ(i, 1); - std::this_thread::sleep_for(std::chrono::milliseconds(300)); + TestingClock::increment_time(std::chrono::milliseconds(300)); expmap.remove_deprecated(); EXPECT_EQ(0, expmap.size()); } @@ -127,7 +158,7 @@ TEST(core_cpp_core, ExpMap_Find) // This test assures that find can be called on a const CExpMap and returns an CExpMap::const_iterator TEST(core_cpp_core, ExpMap_FindConst) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); auto it = expmap.find("A"); EXPECT_EQ(expmap.end(), it); @@ -137,11 +168,11 @@ TEST(core_cpp_core, ExpMap_FindConst) const auto& const_ref_exmap = expmap; auto const_it = const_ref_exmap.find("A"); // assert that we are actually getting a const_iterator here! - static_assert(std::is_same::const_iterator>::value, "We're not being returned a const_iterator from find."); + static_assert(std::is_same::const_iterator>::value, "We're not being returned a const_iterator from find."); int i = (*const_it).second; EXPECT_EQ(i, 1); - std::this_thread::sleep_for(std::chrono::milliseconds(300)); + TestingClock::increment_time(std::chrono::milliseconds(300)); expmap.remove_deprecated(); EXPECT_EQ(0, expmap.size()); } @@ -149,7 +180,7 @@ TEST(core_cpp_core, ExpMap_FindConst) TEST(core_cpp_core, ExpMap_Iterate) { // create the map with 2500 ms expiration - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); expmap["A"] = 1; std::string key; @@ -165,7 +196,7 @@ TEST(core_cpp_core, ExpMap_Iterate) EXPECT_EQ(1, value); } -void ConstRefIterate(const eCAL::Util::CExpMap& map) +void ConstRefIterate(const eCAL::Util::CExpMap& map) { std::string key; int value; @@ -183,7 +214,7 @@ void ConstRefIterate(const eCAL::Util::CExpMap& map) TEST(core_cpp_core, ExpMap_ConstExpMapIterate) { // create the map with 2500 ms expiration - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); expmap["A"] = 1; ConstRefIterate(expmap); @@ -191,7 +222,7 @@ TEST(core_cpp_core, ExpMap_ConstExpMapIterate) TEST(core_cpp_core, ExpMap_Empty) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); EXPECT_EQ(true, expmap.empty()); expmap["A"] = 1; EXPECT_EQ(false, expmap.empty()); @@ -199,7 +230,7 @@ TEST(core_cpp_core, ExpMap_Empty) TEST(core_cpp_core, ExpMap_Size) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); EXPECT_EQ(0, expmap.size()); expmap["A"] = 1; EXPECT_EQ(1, expmap.size()); @@ -207,7 +238,7 @@ TEST(core_cpp_core, ExpMap_Size) TEST(core_cpp_core, ExpMap_Remove) { - eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); + eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); expmap["A"] = 1; EXPECT_EQ(1, expmap.size()); EXPECT_TRUE(expmap.erase("A"));