cache_ut.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include <library/cpp/cache/cache.h>
  2. #include <library/cpp/cache/thread_safe_cache.h>
  3. #include <library/cpp/testing/unittest/registar.h>
  4. struct TStrokaWeighter {
  5. static size_t Weight(const TString& s) {
  6. return s.size();
  7. }
  8. };
  9. Y_UNIT_TEST_SUITE(TCacheTest) {
  10. Y_UNIT_TEST(LRUListTest) {
  11. typedef TLRUList<int, TString> TListType;
  12. TListType list(2);
  13. TListType::TItem x1(1, "ttt");
  14. list.Insert(&x1);
  15. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  16. TListType::TItem x2(2, "yyy");
  17. list.Insert(&x2);
  18. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  19. list.Promote(list.GetOldest());
  20. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 2);
  21. TListType::TItem x3(3, "zzz");
  22. list.Insert(&x3);
  23. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  24. }
  25. Y_UNIT_TEST(LRUListWeightedTest) {
  26. typedef TLRUList<int, TString, size_t (*)(const TString&)> TListType;
  27. TListType list(7, [](auto& string) {
  28. return string.size();
  29. });
  30. TListType::TItem x1(1, "ttt");
  31. list.Insert(&x1);
  32. while (list.RemoveIfOverflown()) {
  33. }
  34. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  35. TListType::TItem x2(2, "yyy");
  36. list.Insert(&x2);
  37. while (list.RemoveIfOverflown()) {
  38. }
  39. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  40. list.Promote(list.GetOldest());
  41. while (list.RemoveIfOverflown()) {
  42. }
  43. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 2);
  44. TListType::TItem x3(3, "zzz");
  45. list.Insert(&x3);
  46. while (list.RemoveIfOverflown()) {
  47. }
  48. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
  49. TListType::TItem x4(4, "longlong");
  50. list.Insert(&x4);
  51. while (list.RemoveIfOverflown()) {
  52. }
  53. UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 4);
  54. }
  55. Y_UNIT_TEST(LFUListTest) {
  56. typedef TLFUList<int, TString> TListType;
  57. TListType list(2);
  58. TListType::TItem x1(1, "ttt");
  59. list.Insert(&x1);
  60. UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
  61. TListType::TItem x2(2, "yyy");
  62. list.Insert(&x2);
  63. UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
  64. list.Promote(list.GetLeastFrequentlyUsed());
  65. UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 2);
  66. TListType::TItem x3(3, "zzz");
  67. list.Insert(&x3);
  68. UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
  69. }
  70. Y_UNIT_TEST(LWListTest) {
  71. typedef TLWList<int, TString, size_t, TStrokaWeighter> TListType;
  72. TListType list(2);
  73. TListType::TItem x1(1, "tt");
  74. list.Insert(&x1);
  75. UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
  76. UNIT_ASSERT_EQUAL(list.GetSize(), 1);
  77. TListType::TItem x2(2, "yyyy");
  78. list.Insert(&x2);
  79. UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
  80. UNIT_ASSERT_EQUAL(list.GetSize(), 2);
  81. TListType::TItem x3(3, "z");
  82. list.Insert(&x3);
  83. UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
  84. UNIT_ASSERT_EQUAL(list.GetSize(), 2);
  85. TListType::TItem x4(4, "xxxxxx");
  86. list.Insert(&x4);
  87. UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 2);
  88. UNIT_ASSERT_EQUAL(list.GetSize(), 2);
  89. list.Erase(&x2);
  90. UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 4);
  91. UNIT_ASSERT_EQUAL(list.GetSize(), 1);
  92. }
  93. Y_UNIT_TEST(SimpleTest) {
  94. typedef TLRUCache<int, TString> TCache;
  95. TCache s(2); // size 2
  96. s.Insert(1, "abcd");
  97. UNIT_ASSERT(s.Find(1) != s.End());
  98. UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
  99. s.Insert(2, "defg");
  100. UNIT_ASSERT(s.GetOldest() == "abcd");
  101. s.Insert(3, "hjkl");
  102. UNIT_ASSERT(s.GetOldest() == "defg");
  103. // key 1 will be deleted
  104. UNIT_ASSERT(s.Find(1) == s.End());
  105. UNIT_ASSERT(s.Find(2) != s.End());
  106. UNIT_ASSERT(*s.Find(2) == "defg");
  107. UNIT_ASSERT(s.Find(3) != s.End());
  108. UNIT_ASSERT(*s.Find(3) == "hjkl");
  109. UNIT_ASSERT(!s.Insert(3, "abcd"));
  110. UNIT_ASSERT(*s.Find(3) == "hjkl");
  111. s.Update(3, "abcd");
  112. UNIT_ASSERT(*s.Find(3) == "abcd");
  113. TCache::TIterator it = s.Find(3);
  114. s.Erase(it);
  115. UNIT_ASSERT(s.Find(3) == s.End());
  116. }
  117. Y_UNIT_TEST(LRUWithCustomSizeProviderTest) {
  118. typedef TLRUCache<int, TString, TNoopDelete, size_t(*)(const TString&)> TCache;
  119. TCache s(10, false, [](auto& string) { return string.size(); }); // size 10
  120. s.Insert(1, "abcd");
  121. UNIT_ASSERT(s.Find(1) != s.End());
  122. UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
  123. s.Insert(2, "defg");
  124. UNIT_ASSERT(s.GetOldest() == "abcd");
  125. s.Insert(3, "2c");
  126. UNIT_ASSERT(s.GetOldest() == "abcd");
  127. s.Insert(4, "hjkl");
  128. UNIT_ASSERT(s.GetOldest() == "defg");
  129. // key 1 will be deleted
  130. UNIT_ASSERT(s.Find(1) == s.End());
  131. UNIT_ASSERT(s.Find(2) != s.End());
  132. UNIT_ASSERT(*s.Find(2) == "defg");
  133. UNIT_ASSERT(s.Find(3) != s.End());
  134. UNIT_ASSERT(*s.Find(3) == "2c");
  135. UNIT_ASSERT(s.Find(4) != s.End());
  136. UNIT_ASSERT(*s.Find(4) == "hjkl");
  137. UNIT_ASSERT(!s.Insert(3, "abcd"));
  138. UNIT_ASSERT(*s.Find(3) == "2c");
  139. s.Update(3, "abcd");
  140. UNIT_ASSERT(*s.Find(3) == "abcd");
  141. TCache::TIterator it = s.Find(3);
  142. s.Erase(it);
  143. UNIT_ASSERT(s.Find(3) == s.End());
  144. }
  145. Y_UNIT_TEST(LRUSetMaxSizeTest) {
  146. typedef TLRUCache<int, TString> TCache;
  147. TCache s(2); // size 2
  148. s.Insert(1, "abcd");
  149. s.Insert(2, "efgh");
  150. s.Insert(3, "ijkl");
  151. UNIT_ASSERT(s.GetOldest() == "efgh");
  152. UNIT_ASSERT(s.Find(1) == s.End());
  153. UNIT_ASSERT(s.Find(2) != s.End());
  154. UNIT_ASSERT(s.Find(3) != s.End());
  155. // Increasing size should not change anything
  156. s.SetMaxSize(3);
  157. UNIT_ASSERT(s.GetOldest() == "efgh");
  158. UNIT_ASSERT(s.Find(1) == s.End());
  159. UNIT_ASSERT(s.Find(2) != s.End());
  160. UNIT_ASSERT(s.Find(3) != s.End());
  161. // And we should be able to add fit more entries
  162. s.Insert(4, "mnop");
  163. s.Insert(5, "qrst");
  164. UNIT_ASSERT(s.GetOldest() == "ijkl");
  165. UNIT_ASSERT(s.Find(1) == s.End());
  166. UNIT_ASSERT(s.Find(2) == s.End());
  167. UNIT_ASSERT(s.Find(3) != s.End());
  168. UNIT_ASSERT(s.Find(4) != s.End());
  169. UNIT_ASSERT(s.Find(5) != s.End());
  170. // Decreasing size should remove oldest entries
  171. s.SetMaxSize(2);
  172. UNIT_ASSERT(s.GetOldest() == "mnop");
  173. UNIT_ASSERT(s.Find(1) == s.End());
  174. UNIT_ASSERT(s.Find(2) == s.End());
  175. UNIT_ASSERT(s.Find(3) == s.End());
  176. UNIT_ASSERT(s.Find(4) != s.End());
  177. UNIT_ASSERT(s.Find(5) != s.End());
  178. // Ano no more entries will fit
  179. s.Insert(6, "uvwx");
  180. UNIT_ASSERT(s.GetOldest() == "qrst");
  181. UNIT_ASSERT(s.Find(1) == s.End());
  182. UNIT_ASSERT(s.Find(2) == s.End());
  183. UNIT_ASSERT(s.Find(3) == s.End());
  184. UNIT_ASSERT(s.Find(4) == s.End());
  185. UNIT_ASSERT(s.Find(5) != s.End());
  186. UNIT_ASSERT(s.Find(6) != s.End());
  187. }
  188. Y_UNIT_TEST(LWSetMaxSizeTest) {
  189. typedef TLWCache<int, TString, size_t, TStrokaWeighter> TCache;
  190. TCache s(2); // size 2
  191. s.Insert(1, "a");
  192. s.Insert(2, "aa");
  193. s.Insert(3, "aaa");
  194. UNIT_ASSERT(s.GetLightest() == "aa");
  195. UNIT_ASSERT(s.Find(1) == s.End());
  196. UNIT_ASSERT(s.Find(2) != s.End());
  197. UNIT_ASSERT(s.Find(3) != s.End());
  198. // Increasing size should not change anything
  199. s.SetMaxSize(3);
  200. UNIT_ASSERT(s.GetLightest() == "aa");
  201. UNIT_ASSERT(s.Find(1) == s.End());
  202. UNIT_ASSERT(s.Find(2) != s.End());
  203. UNIT_ASSERT(s.Find(3) != s.End());
  204. // And we should be able to add fit more entries
  205. s.Insert(4, "aaaa");
  206. s.Insert(5, "aaaaa");
  207. UNIT_ASSERT(s.GetLightest() == "aaa");
  208. UNIT_ASSERT(s.Find(1) == s.End());
  209. UNIT_ASSERT(s.Find(2) == s.End());
  210. UNIT_ASSERT(s.Find(3) != s.End());
  211. UNIT_ASSERT(s.Find(4) != s.End());
  212. UNIT_ASSERT(s.Find(5) != s.End());
  213. // Decreasing size should remove oldest entries
  214. s.SetMaxSize(2);
  215. UNIT_ASSERT(s.GetLightest() == "aaaa");
  216. UNIT_ASSERT(s.Find(1) == s.End());
  217. UNIT_ASSERT(s.Find(2) == s.End());
  218. UNIT_ASSERT(s.Find(3) == s.End());
  219. UNIT_ASSERT(s.Find(4) != s.End());
  220. UNIT_ASSERT(s.Find(5) != s.End());
  221. // Ano no more entries will fit
  222. s.Insert(6, "aaaaaa");
  223. UNIT_ASSERT(s.GetLightest() == "aaaaa");
  224. UNIT_ASSERT(s.Find(1) == s.End());
  225. UNIT_ASSERT(s.Find(2) == s.End());
  226. UNIT_ASSERT(s.Find(3) == s.End());
  227. UNIT_ASSERT(s.Find(4) == s.End());
  228. UNIT_ASSERT(s.Find(5) != s.End());
  229. UNIT_ASSERT(s.Find(6) != s.End());
  230. }
  231. Y_UNIT_TEST(LFUSetMaxSizeTest) {
  232. typedef TLFUCache<int, TString> TCache;
  233. TCache s(2); // size 2
  234. s.Insert(1, "abcd");
  235. s.Insert(2, "efgh");
  236. s.Insert(3, "ijkl");
  237. UNIT_ASSERT(s.Find(1) == s.End());
  238. UNIT_ASSERT(s.Find(2) != s.End());
  239. UNIT_ASSERT(s.Find(3) != s.End());
  240. // Increasing size should not change anything
  241. s.SetMaxSize(3);
  242. UNIT_ASSERT(s.Find(1) == s.End());
  243. UNIT_ASSERT(s.Find(2) != s.End());
  244. UNIT_ASSERT(s.Find(3) != s.End());
  245. // And we should be able to add fit more entries
  246. s.Insert(4, "mnop");
  247. s.Insert(5, "qrst");
  248. UNIT_ASSERT(s.Find(1) == s.End());
  249. UNIT_ASSERT(s.Find(2) == s.End());
  250. UNIT_ASSERT(s.Find(3) != s.End());
  251. UNIT_ASSERT(s.Find(4) != s.End());
  252. UNIT_ASSERT(s.Find(5) != s.End());
  253. // Decreasing size should remove oldest entries
  254. s.SetMaxSize(2);
  255. UNIT_ASSERT(s.Find(1) == s.End());
  256. UNIT_ASSERT(s.Find(2) == s.End());
  257. UNIT_ASSERT(s.Find(3) != s.End());
  258. UNIT_ASSERT(s.Find(4) == s.End());
  259. UNIT_ASSERT(s.Find(5) != s.End());
  260. // Ano no more entries will fit
  261. s.Insert(6, "uvwx");
  262. UNIT_ASSERT(s.Find(1) == s.End());
  263. UNIT_ASSERT(s.Find(2) == s.End());
  264. UNIT_ASSERT(s.Find(3) != s.End());
  265. UNIT_ASSERT(s.Find(4) == s.End());
  266. UNIT_ASSERT(s.Find(5) == s.End());
  267. UNIT_ASSERT(s.Find(6) != s.End());
  268. }
  269. Y_UNIT_TEST(MultiCacheTest) {
  270. typedef TLRUCache<int, TString> TCache;
  271. TCache s(3, true);
  272. UNIT_ASSERT(s.Insert(1, "abcd"));
  273. UNIT_ASSERT(s.Insert(1, "bcde"));
  274. UNIT_ASSERT(s.Insert(2, "fghi"));
  275. UNIT_ASSERT(s.Insert(2, "ghij"));
  276. // (1, "abcd") will be deleted
  277. UNIT_ASSERT(*s.Find(1) == "bcde");
  278. // (1, "bcde") will be promoted
  279. UNIT_ASSERT(*s.FindOldest() == "fghi");
  280. }
  281. struct TMyDelete {
  282. static int count;
  283. template <typename T>
  284. static void Destroy(const T&) {
  285. ++count;
  286. }
  287. };
  288. int TMyDelete::count = 0;
  289. Y_UNIT_TEST(DeleterTest) {
  290. typedef TLRUCache<int, TString, TMyDelete> TCache;
  291. TCache s(2);
  292. s.Insert(1, "123");
  293. s.Insert(2, "456");
  294. s.Insert(3, "789");
  295. UNIT_ASSERT(TMyDelete::count == 1);
  296. TCache::TIterator it = s.Find(2);
  297. UNIT_ASSERT(it != s.End());
  298. s.Erase(it);
  299. UNIT_ASSERT(TMyDelete::count == 2);
  300. }
  301. Y_UNIT_TEST(PromoteOnFind) {
  302. typedef TLRUCache<int, TString> TCache;
  303. TCache s(2);
  304. s.Insert(1, "123");
  305. s.Insert(2, "456");
  306. UNIT_ASSERT(s.Find(1) != s.End());
  307. s.Insert(3, "789");
  308. UNIT_ASSERT(s.Find(1) != s.End()); // Key 2 should have been deleted
  309. }
  310. }
  311. Y_UNIT_TEST_SUITE(TThreadSafeCacheTest) {
  312. typedef TThreadSafeCache<ui32, TString, ui32> TCache;
  313. const char* VALS[] = {"abcd", "defg", "hjkl"};
  314. class TCallbacks: public TCache::ICallbacks {
  315. public:
  316. TKey GetKey(ui32 i) const override {
  317. return i;
  318. }
  319. TValue* CreateObject(ui32 i) const override {
  320. Creations++;
  321. return new TString(VALS[i]);
  322. }
  323. mutable i32 Creations = 0;
  324. };
  325. Y_UNIT_TEST(SimpleTest) {
  326. for (ui32 i = 0; i < Y_ARRAY_SIZE(VALS); ++i) {
  327. const TString data = *TCache::Get<TCallbacks>(i);
  328. UNIT_ASSERT(data == VALS[i]);
  329. }
  330. }
  331. Y_UNIT_TEST(InsertUpdateTest) {
  332. TCallbacks callbacks;
  333. TCache cache(callbacks, 10);
  334. cache.Insert(2, MakeAtomicShared<TString>("hj"));
  335. TAtomicSharedPtr<TString> item = cache.Get(2);
  336. UNIT_ASSERT(callbacks.Creations == 0);
  337. UNIT_ASSERT(*item == "hj");
  338. cache.Insert(2, MakeAtomicShared<TString>("hjk"));
  339. item = cache.Get(2);
  340. UNIT_ASSERT(callbacks.Creations == 0);
  341. UNIT_ASSERT(*item == "hj");
  342. cache.Update(2, MakeAtomicShared<TString>("hjk"));
  343. item = cache.Get(2);
  344. UNIT_ASSERT(callbacks.Creations == 0);
  345. UNIT_ASSERT(*item == "hjk");
  346. }
  347. }
  348. Y_UNIT_TEST_SUITE(TThreadSafeCacheUnsafeTest) {
  349. typedef TThreadSafeCache<ui32, TString, ui32> TCache;
  350. const char* VALS[] = {"abcd", "defg", "hjkl"};
  351. const ui32 FAILED_IDX = 1;
  352. class TCallbacks: public TCache::ICallbacks {
  353. public:
  354. TKey GetKey(ui32 i) const override {
  355. return i;
  356. }
  357. TValue* CreateObject(ui32 i) const override {
  358. if (i == FAILED_IDX) {
  359. return nullptr;
  360. }
  361. return new TString(VALS[i]);
  362. }
  363. };
  364. Y_UNIT_TEST(SimpleTest) {
  365. TCallbacks callbacks;
  366. TCache cache(callbacks, Y_ARRAY_SIZE(VALS));
  367. for (ui32 i = 0; i < Y_ARRAY_SIZE(VALS); ++i) {
  368. const TString* data = cache.GetUnsafe(i).Get();
  369. if (i == FAILED_IDX) {
  370. UNIT_ASSERT(data == nullptr);
  371. } else {
  372. UNIT_ASSERT(*data == VALS[i]);
  373. }
  374. }
  375. }
  376. }
  377. Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheTest) {
  378. typedef TThreadSafeLRUCache<size_t, TString, size_t> TCache;
  379. TVector<TString> Values = {"zero", "one", "two", "three", "four"};
  380. class TCallbacks: public TCache::ICallbacks {
  381. public:
  382. TKey GetKey(size_t i) const override {
  383. return i;
  384. }
  385. TValue* CreateObject(size_t i) const override {
  386. UNIT_ASSERT(i < Values.size());
  387. Creations++;
  388. return new TString(Values[i]);
  389. }
  390. mutable size_t Creations = 0;
  391. };
  392. Y_UNIT_TEST(SimpleTest) {
  393. for (size_t i = 0; i < Values.size(); ++i) {
  394. const TString data = *TCache::Get<TCallbacks>(i);
  395. UNIT_ASSERT(data == Values[i]);
  396. }
  397. }
  398. Y_UNIT_TEST(InsertUpdateTest) {
  399. TCallbacks callbacks;
  400. TCache cache(callbacks, 10);
  401. cache.Insert(2, MakeAtomicShared<TString>("hj"));
  402. TAtomicSharedPtr<TString> item = cache.Get(2);
  403. UNIT_ASSERT(callbacks.Creations == 0);
  404. UNIT_ASSERT(*item == "hj");
  405. cache.Insert(2, MakeAtomicShared<TString>("hjk"));
  406. item = cache.Get(2);
  407. UNIT_ASSERT(callbacks.Creations == 0);
  408. UNIT_ASSERT(*item == "hj");
  409. cache.Update(2, MakeAtomicShared<TString>("hjk"));
  410. item = cache.Get(2);
  411. UNIT_ASSERT(callbacks.Creations == 0);
  412. UNIT_ASSERT(*item == "hjk");
  413. }
  414. Y_UNIT_TEST(LRUTest) {
  415. TCallbacks callbacks;
  416. TCache cache(callbacks, 3);
  417. UNIT_ASSERT_EQUAL(cache.GetMaxSize(), 3);
  418. for (size_t i = 0; i < Values.size(); ++i) {
  419. TAtomicSharedPtr<TString> item = cache.Get(i);
  420. UNIT_ASSERT(*item == Values[i]);
  421. }
  422. UNIT_ASSERT(callbacks.Creations == Values.size());
  423. size_t expectedCreations = Values.size();
  424. TAtomicSharedPtr<TString> item;
  425. item = cache.Get(4);
  426. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  427. UNIT_ASSERT(*item == "four");
  428. item = cache.Get(2);
  429. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  430. UNIT_ASSERT(*item == "two");
  431. item = cache.Get(0);
  432. expectedCreations++;
  433. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  434. UNIT_ASSERT(*item == "zero");
  435. UNIT_ASSERT(cache.Contains(1) == false);
  436. UNIT_ASSERT(cache.Contains(3) == false);
  437. UNIT_ASSERT(cache.Contains(4));
  438. UNIT_ASSERT(cache.Contains(2));
  439. UNIT_ASSERT(cache.Contains(0));
  440. item = cache.Get(3);
  441. expectedCreations++;
  442. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  443. UNIT_ASSERT(*item == "three");
  444. item = cache.Get(2);
  445. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  446. UNIT_ASSERT(*item == "two");
  447. item = cache.Get(0);
  448. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  449. UNIT_ASSERT(*item == "zero");
  450. item = cache.Get(1);
  451. expectedCreations++;
  452. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  453. UNIT_ASSERT(*item == "one");
  454. item = cache.Get(2);
  455. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  456. UNIT_ASSERT(*item == "two");
  457. item = cache.Get(4);
  458. expectedCreations++;
  459. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  460. UNIT_ASSERT(*item == "four");
  461. }
  462. Y_UNIT_TEST(ChangeMaxSizeTest) {
  463. TCallbacks callbacks;
  464. TCache cache(callbacks, 3);
  465. UNIT_ASSERT_EQUAL(cache.GetMaxSize(), 3);
  466. for (size_t i = 0; i < Values.size(); ++i) {
  467. TAtomicSharedPtr<TString> item = cache.Get(i);
  468. UNIT_ASSERT(*item == Values[i]);
  469. }
  470. size_t expectedCreations = Values.size();
  471. TAtomicSharedPtr<TString> item;
  472. item = cache.Get(4);
  473. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  474. UNIT_ASSERT(*item == "four");
  475. item = cache.Get(3);
  476. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  477. UNIT_ASSERT(*item == "three");
  478. item = cache.Get(2);
  479. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  480. UNIT_ASSERT(*item == "two");
  481. item = cache.Get(1);
  482. expectedCreations++;
  483. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  484. UNIT_ASSERT(*item == "one");
  485. cache.SetMaxSize(4);
  486. item = cache.Get(0);
  487. expectedCreations++;
  488. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  489. UNIT_ASSERT(*item == "zero");
  490. item = cache.Get(4);
  491. expectedCreations++;
  492. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  493. UNIT_ASSERT(*item == "four");
  494. item = cache.Get(3);
  495. expectedCreations++;
  496. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  497. UNIT_ASSERT(*item == "three");
  498. UNIT_ASSERT(cache.Contains(2) == false);
  499. cache.SetMaxSize(2);
  500. UNIT_ASSERT(cache.Contains(3));
  501. UNIT_ASSERT(cache.Contains(4));
  502. UNIT_ASSERT(cache.Contains(2) == false);
  503. UNIT_ASSERT(cache.Contains(1) == false);
  504. UNIT_ASSERT(cache.Contains(0) == false);
  505. item = cache.Get(0);
  506. expectedCreations++;
  507. UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
  508. UNIT_ASSERT(*item == "zero");
  509. UNIT_ASSERT(cache.Contains(4) == false);
  510. UNIT_ASSERT(cache.Contains(3));
  511. UNIT_ASSERT(cache.Contains(0));
  512. }
  513. }