Skip to content

Commit 9fff807

Browse files
committed
feat multi-index-lru: allow time mocking and make the tests more reliable
Tests: протестировано CI commit_hash:243ec522bacd2e97b356205791d2addc8b8fcfcc
1 parent 47145c4 commit 9fff807

3 files changed

Lines changed: 20 additions & 14 deletions

File tree

libraries/multi-index-lru/include/userver/multi-index-lru/expirable_container.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "impl/mpl_helpers.hpp"
88

99
#include <userver/utils/assert.hpp>
10+
#include <userver/utils/datetime.hpp>
1011

1112
USERVER_NAMESPACE_BEGIN
1213

@@ -28,10 +29,11 @@ class ExpirableContainer {
2829

2930
template <typename... Args>
3031
auto emplace(Args&&... args) {
31-
auto result = container_.emplace(std::forward<Args>(args)...);
32+
const auto now = utils::datetime::SteadyClock::now();
33+
auto result = container_.emplace(now, std::forward<Args>(args)...);
3234

3335
if (!result.second) {
34-
result.first->last_accessed = std::chrono::steady_clock::now();
36+
result.first->last_accessed = now;
3537
}
3638

3739
return result;
@@ -43,7 +45,7 @@ class ExpirableContainer {
4345

4446
template <typename Tag, typename Key>
4547
auto find(const Key& key) {
46-
const auto now = std::chrono::steady_clock::now();
48+
const auto now = utils::datetime::SteadyClock::now();
4749
auto it = container_.template find<Tag, Key>(key);
4850

4951
if (it != container_.template end<Tag>()) {
@@ -66,7 +68,7 @@ class ExpirableContainer {
6668

6769
template <typename Tag, typename Key>
6870
auto equal_range(const Key& key) {
69-
const auto now = std::chrono::steady_clock::now();
71+
const auto now = utils::datetime::SteadyClock::now();
7072
auto range = container_.template equal_range<Tag, Key>(key);
7173

7274
auto it = range.first;
@@ -139,7 +141,7 @@ class ExpirableContainer {
139141

140142
/// @brief Removes all expired items from container
141143
void cleanup_expired() {
142-
const auto now = std::chrono::steady_clock::now();
144+
const auto now = utils::datetime::SteadyClock::now();
143145

144146
while (!container_.empty()) {
145147
const auto it = container_.find_last_accessed_no_update();

libraries/multi-index-lru/include/userver/multi-index-lru/impl/mpl_helpers.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ struct TimestampedValue {
5858

5959
TimestampedValue() = default;
6060

61-
explicit TimestampedValue(const Value& val)
61+
TimestampedValue(std::chrono::steady_clock::time_point now, const Value& val)
6262
: value(val),
63-
last_accessed(std::chrono::steady_clock::now())
63+
last_accessed(now)
6464
{}
6565

66-
explicit TimestampedValue(Value&& val)
66+
TimestampedValue(std::chrono::steady_clock::time_point now, Value&& val)
6767
: value(std::move(val)),
68-
last_accessed(std::chrono::steady_clock::now())
68+
last_accessed(now)
6969
{}
7070

7171
operator Value&() noexcept { return value; }

libraries/multi-index-lru/src/expirable_container_test.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <userver/multi-index-lru/expirable_container.hpp>
44
#include <userver/utest/utest.hpp>
55
#include <userver/utils/async.hpp>
6+
#include <userver/utils/mock_now.hpp>
67

78
#include <mutex>
89
#include <string>
@@ -109,6 +110,7 @@ UTEST_F(ExpirableUsersTest, LRUEviction) {
109110

110111
UTEST_F(ExpirableUsersTest, TTLExpiration) {
111112
using namespace std::chrono_literals;
113+
utils::datetime::MockNowSet(std::chrono::system_clock::now());
112114

113115
UserCacheExpirable cache(100, 100ms); // Very short TTL for testing
114116

@@ -121,7 +123,7 @@ UTEST_F(ExpirableUsersTest, TTLExpiration) {
121123
EXPECT_EQ(cache.size(), 2);
122124

123125
// Wait for TTL to expire
124-
engine::SleepFor(150ms);
126+
utils::datetime::MockSleep(150ms);
125127

126128
EXPECT_EQ(cache.find<IdTag>(1), cache.end<IdTag>());
127129
EXPECT_EQ(cache.find<IdTag>(2), cache.end<IdTag>());
@@ -130,23 +132,24 @@ UTEST_F(ExpirableUsersTest, TTLExpiration) {
130132

131133
UTEST_F(ExpirableUsersTest, TTLRefreshOnAccess) {
132134
using namespace std::chrono_literals;
135+
utils::datetime::MockNowSet(std::chrono::system_clock::now());
133136

134137
UserCacheExpirable cache(100, 190ms);
135138

136139
cache.insert(User{1, "alice@test.com", "Alice"});
137140

138141
// Wait a bit but not enough to expire
139-
engine::SleepFor(99ms);
142+
utils::datetime::MockSleep(99ms);
140143

141144
// Access via find should refresh TTL
142145
EXPECT_NE(cache.find<IdTag>(1), cache.end<IdTag>());
143146

144147
// Wait again - should still be alive due to refresh
145-
engine::SleepFor(99ms);
148+
utils::datetime::MockSleep(99ms);
146149
EXPECT_NE(cache.find<IdTag>(1), cache.end<IdTag>());
147150

148151
// Wait for full TTL from last access
149-
engine::SleepFor(200ms);
152+
utils::datetime::MockSleep(200ms);
150153
EXPECT_EQ(cache.find<IdTag>(1), cache.end<IdTag>());
151154
}
152155

@@ -248,14 +251,15 @@ UTEST_F(ExpirableUsersTest, Clear) {
248251

249252
UTEST_F(ExpirableUsersTest, CleanupExpired) {
250253
using namespace std::chrono_literals;
254+
utils::datetime::MockNowSet(std::chrono::system_clock::now());
251255

252256
UserCacheExpirable cache(5, 100ms);
253257

254258
cache.insert(User{1, "alice@test.com", "Alice"});
255259
cache.insert(User{2, "bob@test.com", "Bob"});
256260

257261
// Wait for TTL to expire
258-
engine::SleepFor(150ms);
262+
utils::datetime::MockSleep(150ms);
259263

260264
// cleanup_expired should remove expired items
261265
cache.cleanup_expired();

0 commit comments

Comments
 (0)