summaryrefslogtreecommitdiffstats
path: root/library/cpp/cache/ut/cache_ut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/cache/ut/cache_ut.cpp')
-rw-r--r--library/cpp/cache/ut/cache_ut.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/library/cpp/cache/ut/cache_ut.cpp b/library/cpp/cache/ut/cache_ut.cpp
index 16f29b29d1f..c4c829cdb7d 100644
--- a/library/cpp/cache/ut/cache_ut.cpp
+++ b/library/cpp/cache/ut/cache_ut.cpp
@@ -2,6 +2,10 @@
#include <library/cpp/cache/thread_safe_cache.h>
#include <library/cpp/testing/unittest/registar.h>
+#include <util/thread/pool.h>
+#include <util/string/cast.h>
+#include <util/random/random.h>
+
struct TStrokaWeighter {
static size_t Weight(const TString& s) {
return s.size();
@@ -536,6 +540,53 @@ Y_UNIT_TEST_SUITE(TThreadSafeCacheTest) {
}
}
+Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheMultiThreadTest) {
+ typedef TThreadSafeLRUCache<ui32, TString, ui32> TCache;
+
+ class TSimpleCallbacks: public TCache::ICallbacks {
+ public:
+ TKey GetKey(ui32 i) const override {
+ return i;
+ }
+ TValue* CreateObject(ui32 i) const override {
+ Y_UNUSED(i);
+ return nullptr;
+ }
+ };
+
+ Y_UNIT_TEST(GetOrNullMultiThreadTest) {
+ const size_t poolSize = 8;
+ const size_t passCnt = 128;
+ const size_t tasksCnt = 128;
+
+ TRWMutex lock;
+ TThreadPool pool;
+ TSimpleCallbacks callbacks;
+ TCache cache(callbacks, poolSize);
+
+ for (size_t i = 0; i < poolSize; ++i) {
+ cache.Insert(i, MakeAtomicShared<TString>(ToString(i)));
+ }
+
+ pool.Start(poolSize);
+ {
+ TWriteGuard wGruard(lock);
+ for (size_t i = 0; i < tasksCnt; ++i) {
+ pool.SafeAddFunc([&lock, &cache]() {
+ TReadGuard rGuard(lock);
+ for (size_t j = 0; j < passCnt; ++j) {
+ UNIT_ASSERT(cache.GetOrNull(RandomNumber<size_t>(poolSize)) != nullptr);
+ }
+ });
+ }
+ } // start race
+ pool.Stop();
+ for (size_t i = 0; i < cache.Size(); ++i) {
+ UNIT_ASSERT(cache.GetOrNull(i) != nullptr);
+ }
+ }
+}
+
Y_UNIT_TEST_SUITE(TThreadSafeCacheUnsafeTest) {
typedef TThreadSafeCache<ui32, TString, ui32> TCache;