123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020 |
- #include <library/cpp/cache/cache.h>
- #include <library/cpp/cache/thread_safe_cache.h>
- #include <library/cpp/testing/unittest/registar.h>
- struct TStrokaWeighter {
- static size_t Weight(const TString& s) {
- return s.size();
- }
- };
- Y_UNIT_TEST_SUITE(TCacheTest) {
- Y_UNIT_TEST(LRUListTest) {
- typedef TLRUList<int, TString> TListType;
- TListType list(2);
- TListType::TItem x1(1, "ttt");
- list.Insert(&x1);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- TListType::TItem x2(2, "yyy");
- list.Insert(&x2);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- list.Promote(list.GetOldest());
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 2);
- TListType::TItem x3(3, "zzz");
- list.Insert(&x3);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- }
- Y_UNIT_TEST(LRUListWeightedTest) {
- typedef TLRUList<int, TString, size_t (*)(const TString&)> TListType;
- TListType list(7, [](auto& string) {
- return string.size();
- });
- TListType::TItem x1(1, "ttt");
- list.Insert(&x1);
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 3);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- TListType::TItem x2(2, "yyy");
- list.Insert(&x2);
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 6);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- list.Promote(list.GetOldest());
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 2);
- TListType::TItem x3(3, "zzz");
- list.Insert(&x3);
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 6);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
- TListType::TItem x4(4, "longlong");
- list.Insert(&x4);
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 8);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 4);
- TListType::TItem x5(5, "xxx");
- list.Insert(&x5);
- while (list.RemoveIfOverflown()) {
- }
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 3);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 5);
- }
- Y_UNIT_TEST(LFUListTest) {
- typedef TLFUList<int, TString> TListType;
- TListType list(2);
- TListType::TItem x1(1, "ttt");
- list.Insert(&x1);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
- TListType::TItem x2(2, "yyy");
- list.Insert(&x2);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
- list.Promote(list.GetLeastFrequentlyUsed());
- UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 2);
- TListType::TItem x3(3, "zzz");
- list.Insert(&x3);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
- }
- Y_UNIT_TEST(LWListTest) {
- typedef TLWList<int, TString, size_t, TStrokaWeighter> TListType;
- TListType list(2);
- TListType::TItem x1(1, "tt");
- list.Insert(&x1);
- UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- TListType::TItem x2(2, "yyyy");
- list.Insert(&x2);
- UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- TListType::TItem x3(3, "z");
- list.Insert(&x3);
- UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- TListType::TItem x4(4, "xxxxxx");
- list.Insert(&x4);
- UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 2);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
- UNIT_ASSERT_EQUAL(list.GetSize(), 2);
- list.Erase(&x2);
- UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 4);
- UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
- UNIT_ASSERT_EQUAL(list.GetSize(), 1);
- }
- Y_UNIT_TEST(SimpleTest) {
- typedef TLRUCache<int, TString> TCache;
- TCache s(2); // size 2
- s.Insert(1, "abcd");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 1);
- UNIT_ASSERT_EQUAL(s.Size(), 1);
- UNIT_ASSERT(s.Find(1) != s.End());
- UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
- s.Insert(2, "defg");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
- UNIT_ASSERT_EQUAL(s.Size(), 2);
- UNIT_ASSERT(s.GetOldest() == "abcd");
- s.Insert(3, "hjkl");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
- UNIT_ASSERT_EQUAL(s.Size(), 2);
- UNIT_ASSERT(s.GetOldest() == "defg");
- // key 1 will be deleted
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(*s.Find(2) == "defg");
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(*s.Find(3) == "hjkl");
- UNIT_ASSERT(!s.Insert(3, "abcd"));
- UNIT_ASSERT(*s.Find(3) == "hjkl");
- s.Update(3, "abcd");
- UNIT_ASSERT(*s.Find(3) == "abcd");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
- UNIT_ASSERT_EQUAL(s.Size(), 2);
- TCache::TIterator it = s.Find(3);
- s.Erase(it);
- UNIT_ASSERT_EQUAL(s.TotalSize(), 1);
- UNIT_ASSERT_EQUAL(s.Size(), 1);
- UNIT_ASSERT(s.Find(3) == s.End());
- }
- Y_UNIT_TEST(LRUWithCustomSizeProviderTest) {
- typedef TLRUCache<int, TString, TNoopDelete, size_t(*)(const TString&)> TCache;
- TCache s(10, false, [](auto& string) { return string.size(); }); // size 10
- s.Insert(1, "abcd");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 4);
- UNIT_ASSERT_EQUAL(s.Size(), 1);
- UNIT_ASSERT(s.Find(1) != s.End());
- UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
- s.Insert(2, "defg");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 8);
- UNIT_ASSERT_EQUAL(s.Size(), 2);
- UNIT_ASSERT(s.GetOldest() == "abcd");
- s.Insert(3, "2c");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 10);
- UNIT_ASSERT_EQUAL(s.Size(), 3);
- UNIT_ASSERT(s.GetOldest() == "abcd");
- s.Insert(4, "hjkl");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 10);
- UNIT_ASSERT_EQUAL(s.Size(), 3);
- UNIT_ASSERT(s.GetOldest() == "defg");
- // key 1 will be deleted
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(*s.Find(2) == "defg");
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(*s.Find(3) == "2c");
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(*s.Find(4) == "hjkl");
- UNIT_ASSERT(!s.Insert(3, "abcd"));
- UNIT_ASSERT(*s.Find(3) == "2c");
- s.Update(3, "abcd");
- UNIT_ASSERT_EQUAL(s.TotalSize(), 8);
- UNIT_ASSERT_EQUAL(s.Size(), 2);
- UNIT_ASSERT(*s.Find(3) == "abcd");
- TCache::TIterator it = s.Find(3);
- s.Erase(it);
- UNIT_ASSERT_EQUAL(s.TotalSize(), 4);
- UNIT_ASSERT_EQUAL(s.Size(), 1);
- UNIT_ASSERT(s.Find(3) == s.End());
- }
- Y_UNIT_TEST(LRUSetMaxSizeTest) {
- typedef TLRUCache<int, TString> TCache;
- TCache s(2); // size 2
- s.Insert(1, "abcd");
- s.Insert(2, "efgh");
- s.Insert(3, "ijkl");
- UNIT_ASSERT(s.GetOldest() == "efgh");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // Increasing size should not change anything
- s.SetMaxSize(3);
- UNIT_ASSERT(s.GetOldest() == "efgh");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // And we should be able to add fit more entries
- s.Insert(4, "mnop");
- s.Insert(5, "qrst");
- UNIT_ASSERT(s.GetOldest() == "ijkl");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Decreasing size should remove oldest entries
- s.SetMaxSize(2);
- UNIT_ASSERT(s.GetOldest() == "mnop");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) == s.End());
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Ano no more entries will fit
- s.Insert(6, "uvwx");
- UNIT_ASSERT(s.GetOldest() == "qrst");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) == s.End());
- UNIT_ASSERT(s.Find(4) == s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- UNIT_ASSERT(s.Find(6) != s.End());
- }
- Y_UNIT_TEST(LWSetMaxSizeTest) {
- typedef TLWCache<int, TString, size_t, TStrokaWeighter> TCache;
- TCache s(2); // size 2
- s.Insert(1, "a");
- s.Insert(2, "aa");
- s.Insert(3, "aaa");
- UNIT_ASSERT(s.GetLightest() == "aa");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // Increasing size should not change anything
- s.SetMaxSize(3);
- UNIT_ASSERT(s.GetLightest() == "aa");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // And we should be able to add fit more entries
- s.Insert(4, "aaaa");
- s.Insert(5, "aaaaa");
- UNIT_ASSERT(s.GetLightest() == "aaa");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Decreasing size should remove oldest entries
- s.SetMaxSize(2);
- UNIT_ASSERT(s.GetLightest() == "aaaa");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) == s.End());
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Ano no more entries will fit
- s.Insert(6, "aaaaaa");
- UNIT_ASSERT(s.GetLightest() == "aaaaa");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) == s.End());
- UNIT_ASSERT(s.Find(4) == s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- UNIT_ASSERT(s.Find(6) != s.End());
- }
- Y_UNIT_TEST(LFUSetMaxSizeTest) {
- typedef TLFUCache<int, TString> TCache;
- TCache s(2); // size 2
- s.Insert(1, "abcd");
- s.Insert(2, "efgh");
- s.Insert(3, "ijkl");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // Increasing size should not change anything
- s.SetMaxSize(3);
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) != s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- // And we should be able to add fit more entries
- s.Insert(4, "mnop");
- s.Insert(5, "qrst");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(s.Find(4) != s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Decreasing size should remove oldest entries
- s.SetMaxSize(2);
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(s.Find(4) == s.End());
- UNIT_ASSERT(s.Find(5) != s.End());
- // Ano no more entries will fit
- s.Insert(6, "uvwx");
- UNIT_ASSERT(s.Find(1) == s.End());
- UNIT_ASSERT(s.Find(2) == s.End());
- UNIT_ASSERT(s.Find(3) != s.End());
- UNIT_ASSERT(s.Find(4) == s.End());
- UNIT_ASSERT(s.Find(5) == s.End());
- UNIT_ASSERT(s.Find(6) != s.End());
- }
- Y_UNIT_TEST(MultiCacheTest) {
- typedef TLRUCache<int, TString> TCache;
- TCache s(3, true);
- UNIT_ASSERT(s.Insert(1, "abcd"));
- UNIT_ASSERT(s.Insert(1, "bcde"));
- UNIT_ASSERT(s.Insert(2, "fghi"));
- // (1, "abcd") will be deleted
- UNIT_ASSERT(s.Insert(2, "ghij"));
- UNIT_ASSERT_EQUAL(s.TotalSize(), 3);
- UNIT_ASSERT_EQUAL(s.Size(), 3);
- // (1, "bcde") will be promoted
- UNIT_ASSERT(*s.Find(1) == "bcde");
- UNIT_ASSERT(*s.FindOldest() == "fghi");
- }
- struct TMyDelete {
- static int count;
- template <typename T>
- static void Destroy(const T&) {
- ++count;
- }
- };
- int TMyDelete::count = 0;
- Y_UNIT_TEST(DeleterTest) {
- typedef TLRUCache<int, TString, TMyDelete> TCache;
- TCache s(2);
- s.Insert(1, "123");
- s.Insert(2, "456");
- s.Insert(3, "789");
- UNIT_ASSERT(TMyDelete::count == 1);
- TCache::TIterator it = s.Find(2);
- UNIT_ASSERT(it != s.End());
- s.Erase(it);
- UNIT_ASSERT(TMyDelete::count == 2);
- }
- Y_UNIT_TEST(PromoteOnFind) {
- typedef TLRUCache<int, TString> TCache;
- TCache s(2);
- s.Insert(1, "123");
- s.Insert(2, "456");
- UNIT_ASSERT(s.Find(1) != s.End());
- s.Insert(3, "789");
- UNIT_ASSERT(s.Find(1) != s.End()); // Key 2 should have been deleted
- }
- class TMoveOnlyInt {
- public:
- ui32 Value = 0;
- explicit TMoveOnlyInt(ui32 value = 0) : Value(value) {}
- TMoveOnlyInt(TMoveOnlyInt&&) = default;
- TMoveOnlyInt& operator=(TMoveOnlyInt&&) = default;
- TMoveOnlyInt(const TMoveOnlyInt&) = delete;
- TMoveOnlyInt& operator=(const TMoveOnlyInt&) = delete;
- bool operator==(const TMoveOnlyInt& rhs) const {
- return Value == rhs.Value;
- }
- explicit operator size_t() const {
- return Value;
- }
- };
- Y_UNIT_TEST(MoveOnlySimpleTest) {
- typedef TLRUCache<TMoveOnlyInt, TMoveOnlyInt> TCache;
- TCache s(2); // size 2
- s.Insert(TMoveOnlyInt(1), TMoveOnlyInt(0x11111111));
- TMoveOnlyInt lookup1(1), lookup2(2), lookup3(3);
- UNIT_ASSERT(s.Find(lookup1) != s.End());
- UNIT_ASSERT_EQUAL(s.Find(lookup1)->Value, 0x11111111);
- s.Insert(TMoveOnlyInt(2), TMoveOnlyInt(0x22222222));
- UNIT_ASSERT(s.GetOldest().Value == 0x11111111);
- s.Insert(TMoveOnlyInt(3), TMoveOnlyInt(0x33333333));
- UNIT_ASSERT(s.GetOldest().Value == 0x22222222);
- // key 1 will be deleted
- UNIT_ASSERT(s.Find(lookup1) == s.End());
- UNIT_ASSERT(s.Find(lookup2) != s.End());
- UNIT_ASSERT(s.Find(lookup2)->Value == 0x22222222);
- UNIT_ASSERT(s.Find(lookup3) != s.End());
- UNIT_ASSERT(s.Find(lookup3)->Value == 0x33333333);
- UNIT_ASSERT(!s.Insert(TMoveOnlyInt(3), TMoveOnlyInt(0x11111111)));
- UNIT_ASSERT(s.Find(lookup3)->Value == 0x33333333);
- s.Update(TMoveOnlyInt(3), TMoveOnlyInt(0x11111111));
- UNIT_ASSERT(s.Find(lookup3)->Value == 0x11111111);
- TCache::TIterator it = s.Find(lookup3);
- s.Erase(it);
- UNIT_ASSERT(s.Find(lookup3) == s.End());
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeCacheTest) {
- typedef TThreadSafeCache<ui32, TString, ui32> TCache;
- const char* VALS[] = {"abcd", "defg", "hjkl"};
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(ui32 i) const override {
- return i;
- }
- TValue* CreateObject(ui32 i) const override {
- Creations++;
- return new TString(VALS[i]);
- }
- mutable i32 Creations = 0;
- };
- Y_UNIT_TEST(SimpleTest) {
- for (ui32 i = 0; i < Y_ARRAY_SIZE(VALS); ++i) {
- const TString data = *TCache::Get<TCallbacks>(i);
- UNIT_ASSERT(data == VALS[i]);
- }
- }
- Y_UNIT_TEST(InsertUpdateTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 10);
- cache.Insert(2, MakeAtomicShared<TString>("hj"));
- TAtomicSharedPtr<TString> item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Insert(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Update(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 1);
- UNIT_ASSERT_EQUAL(cache.Size(), 1);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hjk");
- }
- Y_UNIT_TEST(GetOrNullTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 10);
- i32 expectedCreations = 0;
- auto item = cache.GetOrNull(0);
- UNIT_ASSERT(item == nullptr);
- UNIT_ASSERT(callbacks.Creations == expectedCreations);
- UNIT_ASSERT(cache.TotalSize() == 0);
- item = cache.Get(0);
- UNIT_ASSERT(*item == "abcd");
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- UNIT_ASSERT(cache.TotalSize() == 1);
- item = cache.GetOrNull(0);
- UNIT_ASSERT(*item == "abcd");
- UNIT_ASSERT(callbacks.Creations == expectedCreations);
- UNIT_ASSERT(cache.TotalSize() == 1);
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeCacheUnsafeTest) {
- typedef TThreadSafeCache<ui32, TString, ui32> TCache;
- const char* VALS[] = {"abcd", "defg", "hjkl"};
- const ui32 FAILED_IDX = 1;
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(ui32 i) const override {
- return i;
- }
- TValue* CreateObject(ui32 i) const override {
- if (i == FAILED_IDX) {
- return nullptr;
- }
- return new TString(VALS[i]);
- }
- };
- Y_UNIT_TEST(SimpleTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, Y_ARRAY_SIZE(VALS));
- for (ui32 i = 0; i < Y_ARRAY_SIZE(VALS); ++i) {
- const TString* data = cache.GetUnsafe(i).Get();
- if (i == FAILED_IDX) {
- UNIT_ASSERT(data == nullptr);
- } else {
- UNIT_ASSERT(*data == VALS[i]);
- }
- }
- UNIT_ASSERT_EQUAL(cache.TotalSize(), Y_ARRAY_SIZE(VALS) - 1);
- UNIT_ASSERT_EQUAL(cache.Size(), Y_ARRAY_SIZE(VALS) - 1);
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheTest) {
- typedef TThreadSafeLRUCache<size_t, TString, size_t> TCache;
- TVector<TString> Values = {"zero", "one", "two", "three", "four"};
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(size_t i) const override {
- return i;
- }
- TValue* CreateObject(size_t i) const override {
- UNIT_ASSERT(i < Values.size());
- Creations++;
- return new TString(Values[i]);
- }
- mutable size_t Creations = 0;
- };
- Y_UNIT_TEST(SimpleTest) {
- for (size_t i = 0; i < Values.size(); ++i) {
- const TString data = *TCache::Get<TCallbacks>(i);
- UNIT_ASSERT(data == Values[i]);
- }
- }
- Y_UNIT_TEST(InsertUpdateTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 10);
- cache.Insert(2, MakeAtomicShared<TString>("hj"));
- TAtomicSharedPtr<TString> item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Insert(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Update(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 1);
- UNIT_ASSERT_EQUAL(cache.Size(), 1);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hjk");
- }
- Y_UNIT_TEST(LRUTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 3);
- UNIT_ASSERT_EQUAL(cache.GetMaxSize(), 3);
- for (size_t i = 0; i < Values.size(); ++i) {
- TAtomicSharedPtr<TString> item = cache.Get(i);
- UNIT_ASSERT(*item == Values[i]);
- }
- UNIT_ASSERT(callbacks.Creations == Values.size());
- size_t expectedCreations = Values.size();
- TAtomicSharedPtr<TString> item;
- item = cache.Get(4);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "four");
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "two");
- item = cache.Get(0);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "zero");
- UNIT_ASSERT(cache.Contains(1) == false);
- UNIT_ASSERT(cache.Contains(3) == false);
- UNIT_ASSERT(cache.Contains(4));
- UNIT_ASSERT(cache.Contains(2));
- UNIT_ASSERT(cache.Contains(0));
- item = cache.Get(3);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "three");
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "two");
- item = cache.Get(0);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "zero");
- item = cache.Get(1);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "one");
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "two");
- item = cache.Get(4);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "four");
- }
- Y_UNIT_TEST(ChangeMaxSizeTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 3);
- UNIT_ASSERT_EQUAL(cache.GetMaxSize(), 3);
- for (size_t i = 0; i < Values.size(); ++i) {
- TAtomicSharedPtr<TString> item = cache.Get(i);
- UNIT_ASSERT(*item == Values[i]);
- }
- size_t expectedCreations = Values.size();
- TAtomicSharedPtr<TString> item;
- item = cache.Get(4);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "four");
- item = cache.Get(3);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "three");
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "two");
- item = cache.Get(1);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "one");
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 3);
- UNIT_ASSERT_EQUAL(cache.Size(), 3);
- cache.SetMaxSize(4);
- item = cache.Get(0);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "zero");
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 4);
- UNIT_ASSERT_EQUAL(cache.Size(), 4);
- item = cache.Get(4);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "four");
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 4);
- UNIT_ASSERT_EQUAL(cache.Size(), 4);
- item = cache.Get(3);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "three");
- UNIT_ASSERT(cache.Contains(2) == false);
- cache.SetMaxSize(2);
- UNIT_ASSERT(cache.Contains(3));
- UNIT_ASSERT(cache.Contains(4));
- UNIT_ASSERT(cache.Contains(2) == false);
- UNIT_ASSERT(cache.Contains(1) == false);
- UNIT_ASSERT(cache.Contains(0) == false);
- item = cache.Get(0);
- expectedCreations++;
- UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
- UNIT_ASSERT(*item == "zero");
- UNIT_ASSERT(cache.Contains(4) == false);
- UNIT_ASSERT(cache.Contains(3));
- UNIT_ASSERT(cache.Contains(0));
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeLFUCacheTest) {
- using TCache = TThreadSafeLFUCache<size_t, TString, size_t>;
- TVector<TString> Values = {"a", "bb", "ccc", "dddd", "eeeee"};
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(size_t i) const override {
- return i;
- }
- TValue* CreateObject(size_t i) const override {
- UNIT_ASSERT(i < Values.size());
- ++Creations;
- return new TString(Values[i]);
- }
- mutable size_t Creations = 0;
- };
- Y_UNIT_TEST(SimpleTest) {
- for (size_t i = 0; i < Values.size(); ++i) {
- const TString data = *TCache::Get<TCallbacks>(i);
- UNIT_ASSERT_EQUAL(data, Values[i]);
- }
- }
- Y_UNIT_TEST(InsertUpdateTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 10);
- cache.Insert(2, MakeAtomicShared<TString>("hj"));
- TAtomicSharedPtr<TString> item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Insert(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hj");
- cache.Update(2, MakeAtomicShared<TString>("hjk"));
- item = cache.Get(2);
- UNIT_ASSERT_EQUAL(cache.TotalSize(), 1);
- UNIT_ASSERT_EQUAL(cache.Size(), 1);
- UNIT_ASSERT(callbacks.Creations == 0);
- UNIT_ASSERT(*item == "hjk");
- }
- Y_UNIT_TEST(LFUTest) {
- TCallbacks callbacks;
- TCache cache(callbacks, 3);
- size_t expectedCreations = 0;
- UNIT_ASSERT_EQUAL(cache.GetMaxSize(), 3);
- auto item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- UNIT_ASSERT(cache.TotalSize() == 1);
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- item = cache.Get(1);
- UNIT_ASSERT(*item == "bb");
- UNIT_ASSERT(cache.TotalSize() == 2);
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- item = cache.Get(2);
- UNIT_ASSERT(*item == "ccc");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- cache.Get(0);
- cache.Get(0);
- cache.Get(0);
- cache.Get(1);
- cache.Get(2);
- cache.Get(2);
- // evict 1
- item = cache.Get(3);
- UNIT_ASSERT(*item == "dddd");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- // check that 0 was evicted and left only 1 2 3
- item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- item = cache.Get(2);
- UNIT_ASSERT(*item == "ccc");
- item = cache.Get(3);
- UNIT_ASSERT(*item == "dddd");
- UNIT_ASSERT(callbacks.Creations == expectedCreations);
- cache.Get(0);
- cache.Get(2);
- cache.Get(3);
- // evict 3
- item = cache.Get(4);
- UNIT_ASSERT(*item == "eeeee");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(callbacks.Creations == ++expectedCreations);
- // check that 1 was evicted and left only 2 3 4
- item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- item = cache.Get(2);
- UNIT_ASSERT(*item == "ccc");
- item = cache.Get(4);
- UNIT_ASSERT(*item == "eeeee");
- UNIT_ASSERT(callbacks.Creations == expectedCreations);
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheWithSizeProviderTest) {
- struct TStringLengthSizeProvider {
- size_t operator()(const TString& s) const {
- return s.size();
- }
- };
- using TCache = TThreadSafeLRUCacheWithSizeProvider<size_t, TString, TStringLengthSizeProvider, size_t>;
- TVector<TString> Values = {"a", "bb", "ccc", "dddd", "eeeee"};
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(size_t i) const override {
- return i;
- }
- TValue* CreateObject(size_t i) const override {
- UNIT_ASSERT(i < Values.size());
- return new TString(Values[i]);
- }
- };
- Y_UNIT_TEST(Test) {
- TCallbacks callbacks;
- TCache cache(callbacks, 6);
- auto item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- UNIT_ASSERT(cache.TotalSize() == 1);
- UNIT_ASSERT(cache.Size() == 1);
- item = cache.Get(1);
- UNIT_ASSERT(*item == "bb");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(cache.Size() == 2);
- item = cache.Get(2);
- UNIT_ASSERT(*item == "ccc");
- UNIT_ASSERT(cache.TotalSize() == 6);
- UNIT_ASSERT(cache.Size() == 3);
- item = cache.Get(3);
- UNIT_ASSERT(*item == "dddd");
- UNIT_ASSERT(cache.TotalSize() == 4);
- UNIT_ASSERT(cache.Size() == 1);
- item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- UNIT_ASSERT(cache.TotalSize() == 5);
- UNIT_ASSERT(cache.Size() == 2);
- item = cache.Get(4);
- UNIT_ASSERT(*item == "eeeee");
- UNIT_ASSERT(cache.TotalSize() == 6);
- UNIT_ASSERT(cache.Size() == 2);
- cache.Update(0, MakeAtomicShared<TString>("aaa"));
- item = cache.Get(0);
- UNIT_ASSERT(*item == "aaa");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(cache.Size() == 1);
- }
- }
- Y_UNIT_TEST_SUITE(TThreadSafeLFUCacheWithSizeProviderTest) {
- struct TStringLengthSizeProvider {
- size_t operator()(const TString& s) const {
- return s.size();
- }
- };
- using TCache = TThreadSafeLFUCacheWithSizeProvider<size_t, TString, TStringLengthSizeProvider, size_t>;
- TVector<TString> Values = {"a", "bb", "ccc", "dddd", "eeeee"};
- class TCallbacks: public TCache::ICallbacks {
- public:
- TKey GetKey(size_t i) const override {
- return i;
- }
- TValue* CreateObject(size_t i) const override {
- UNIT_ASSERT(i < Values.size());
- return new TString(Values[i]);
- }
- };
- Y_UNIT_TEST(Test) {
- TCallbacks callbacks;
- TCache cache(callbacks, 6);
- auto item = cache.Get(0);
- UNIT_ASSERT(*item == "a");
- UNIT_ASSERT(cache.TotalSize() == 1);
- UNIT_ASSERT(cache.Size() == 1);
- item = cache.Get(1);
- UNIT_ASSERT(*item == "bb");
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(cache.Size() == 2);
- item = cache.Get(2);
- UNIT_ASSERT(*item == "ccc");
- UNIT_ASSERT(cache.TotalSize() == 6);
- UNIT_ASSERT(cache.Size() == 3);
- cache.Get(0);
- cache.Get(0);
- cache.Get(0);
- cache.Get(1);
- cache.Get(2);
- cache.Get(2);
- // evict 1. 0 and 3 left
- item = cache.Get(3);
- UNIT_ASSERT(*item == "dddd");
- UNIT_ASSERT(cache.TotalSize() == 5);
- UNIT_ASSERT(cache.Size() == 2);
- cache.Get(0);
- UNIT_ASSERT(cache.TotalSize() == 5);
- UNIT_ASSERT(cache.Size() == 2);
- // evict 3. 0 and 4 left
- cache.Get(4);
- UNIT_ASSERT(cache.TotalSize() == 6);
- UNIT_ASSERT(cache.Size() == 2);
- cache.Get(4);
- cache.Get(4);
- cache.Get(4);
- cache.Get(4);
- cache.Get(4);
- // evict both 0 and 4, even if evict only 4 was ok to fit size
- // thats because 4 used more times, so it is deleted only after 0
- cache.Get(2);
- UNIT_ASSERT(cache.TotalSize() == 3);
- UNIT_ASSERT(cache.Size() == 1);
- }
- }
|