1//
2// UniqueExpireLRUCacheTest.cpp
3//
4// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "UniqueExpireLRUCacheTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Exception.h"
15#include "Poco/UniqueExpireLRUCache.h"
16#include "Poco/UniqueAccessExpireLRUCache.h"
17#include "Poco/AccessExpirationDecorator.h"
18#include "Poco/Bugcheck.h"
19#include "Poco/Thread.h"
20
21
22using namespace Poco;
23
24
25struct IntVal
26{
27 int value;
28 Poco::Timestamp validUntil;
29 IntVal(int val, Poco::Timestamp::TimeDiff v):value(val), validUntil()
30 {
31 validUntil += (v*1000);
32 }
33
34 const Poco::Timestamp& getExpiration() const
35 {
36 return validUntil;
37 }
38};
39
40
41typedef AccessExpirationDecorator<int> DIntVal;
42
43
44#define DURSLEEP 250
45#define DURHALFSLEEP DURSLEEP / 2
46#define DURWAIT 300
47
48
49UniqueExpireLRUCacheTest::UniqueExpireLRUCacheTest(const std::string& rName): CppUnit::TestCase(rName)
50{
51}
52
53
54UniqueExpireLRUCacheTest::~UniqueExpireLRUCacheTest()
55{
56}
57
58
59void UniqueExpireLRUCacheTest::testClear()
60{
61 UniqueExpireLRUCache<int, IntVal> aCache;
62 aCache.add(1, IntVal(2, DURSLEEP));
63 aCache.add(3, IntVal(4, DURSLEEP));
64 aCache.add(5, IntVal(6, DURSLEEP));
65 assertTrue (aCache.has(1));
66 assertTrue (aCache.has(3));
67 assertTrue (aCache.has(5));
68 assertTrue (aCache.get(1)->value == 2);
69 assertTrue (aCache.get(3)->value == 4);
70 assertTrue (aCache.get(5)->value == 6);
71 aCache.clear();
72 assertTrue (!aCache.has(1));
73 assertTrue (!aCache.has(3));
74 assertTrue (!aCache.has(5));
75}
76
77
78
79void UniqueExpireLRUCacheTest::testAccessClear()
80{
81 UniqueAccessExpireLRUCache<int, DIntVal> aCache;
82 aCache.add(1, DIntVal(2, DURSLEEP));
83 aCache.add(3, DIntVal(4, DURSLEEP));
84 aCache.add(5, DIntVal(6, DURSLEEP));
85 assertTrue (aCache.has(1));
86 assertTrue (aCache.has(3));
87 assertTrue (aCache.has(5));
88 assertTrue (aCache.get(1)->value() == 2);
89 assertTrue (aCache.get(3)->value() == 4);
90 assertTrue (aCache.get(5)->value() == 6);
91 aCache.clear();
92 assertTrue (!aCache.has(1));
93 assertTrue (!aCache.has(3));
94 assertTrue (!aCache.has(5));
95}
96
97void UniqueExpireLRUCacheTest::testExpire0()
98{
99 UniqueExpireLRUCache<int, IntVal> aCache;
100 aCache.add(1, IntVal(2, 0));
101 assertTrue (!aCache.has(1));
102}
103
104
105void UniqueExpireLRUCacheTest::testExpireN()
106{
107 // 3-1 represents the cache sorted by age, elements get replaced at the end of the list
108 // 3-1|5 -> 5 gets removed
109 UniqueExpireLRUCache<int, IntVal> aCache(3);
110 aCache.add(1, IntVal(2, DURSLEEP)); // 1
111 assertTrue (aCache.has(1));
112 SharedPtr<IntVal> tmp = aCache.get(1);
113 assertTrue (!tmp.isNull());
114 assertTrue (tmp->value == 2);
115 Thread::sleep(DURWAIT);
116 assertTrue (!aCache.has(1));
117
118 // tmp must still be valid, access it
119 assertTrue (tmp->value == 2);
120 tmp = aCache.get(1);
121 assertTrue (!tmp);
122
123 aCache.add(1, IntVal(2, DURSLEEP)); // 1
124 Thread::sleep(DURHALFSLEEP);
125 aCache.add(3, IntVal(4, DURSLEEP)); // 3-1
126 assertTrue (aCache.has(1));
127 assertTrue (aCache.has(3));
128 tmp = aCache.get(1);
129 SharedPtr<IntVal> tmp2 = aCache.get(3);
130 assertTrue (tmp->value == 2);
131 assertTrue (tmp2->value == 4);
132
133 Thread::sleep(DURHALFSLEEP+25); //3|1
134 assertTrue (!aCache.has(1));
135 assertTrue (aCache.has(3));
136 assertTrue (tmp->value == 2); // 1-3
137 assertTrue (tmp2->value == 4); // 3-1
138 tmp2 = aCache.get(3);
139 assertTrue (tmp2->value == 4);
140 Thread::sleep(DURHALFSLEEP+25); //3|1
141 assertTrue (!aCache.has(3));
142 assertTrue (tmp2->value == 4);
143 tmp = aCache.get(1);
144 tmp2 = aCache.get(3);
145 assertTrue (!tmp);
146 assertTrue (!tmp2);
147
148 // removing illegal entries should work too
149 aCache.remove(666);
150
151 aCache.clear();
152 assertTrue (!aCache.has(5));
153 assertTrue (!aCache.has(3));
154}
155
156
157void UniqueExpireLRUCacheTest::testCacheSize0()
158{
159 // cache size 0 is illegal
160 try
161 {
162 UniqueExpireLRUCache<int, IntVal> aCache(0);
163 failmsg ("cache size of 0 is illegal, test should fail");
164 }
165 catch (Poco::InvalidArgumentException&)
166 {
167 }
168}
169
170
171void UniqueExpireLRUCacheTest::testCacheSize1()
172{
173 UniqueExpireLRUCache<int, IntVal> aCache(1);
174 aCache.add(1, IntVal(2, DURSLEEP));
175 assertTrue (aCache.has(1));
176 assertTrue (aCache.get(1)->value == 2);
177
178 aCache.add(3, IntVal(4, DURSLEEP)); // replaces 1
179 assertTrue (!aCache.has(1));
180 assertTrue (aCache.has(3));
181 assertTrue (aCache.get(3)->value == 4);
182
183 aCache.add(5, IntVal(6, DURSLEEP));
184 assertTrue (!aCache.has(1));
185 assertTrue (!aCache.has(3));
186 assertTrue (aCache.has(5));
187 assertTrue (aCache.get(5)->value == 6);
188
189 aCache.remove(5);
190 assertTrue (!aCache.has(5));
191
192 // removing illegal entries should work too
193 aCache.remove(666);
194}
195
196
197void UniqueExpireLRUCacheTest::testCacheSize2()
198{
199 // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list
200 // 3-1|5 -> 5 gets removed
201 UniqueExpireLRUCache<int, IntVal> aCache(2);
202 aCache.add(1, IntVal(2, DURSLEEP)); // 1
203 assertTrue (aCache.has(1));
204 assertTrue (aCache.get(1)->value == 2);
205
206 aCache.add(3, IntVal(4, DURSLEEP)); // 3-1
207 assertTrue (aCache.has(1));
208 assertTrue (aCache.has(3));
209 assertTrue (aCache.get(1)->value == 2); // 1-3
210 assertTrue (aCache.get(3)->value == 4); // 3-1
211
212 aCache.add(5, IntVal(6, DURSLEEP)); // 5-3|1
213 assertTrue (!aCache.has(1));
214 assertTrue (aCache.has(3));
215 assertTrue (aCache.has(5));
216 assertTrue (aCache.get(5)->value == 6); // 5-3
217 assertTrue (aCache.get(3)->value == 4); // 3-5
218
219 // test remove from the end and the beginning of the list
220 aCache.remove(5); // 3
221 assertTrue (!aCache.has(5));
222 assertTrue (aCache.get(3)->value == 4); // 3
223 aCache.add(5, IntVal(6, DURSLEEP)); // 5-3
224 assertTrue (aCache.get(3)->value == 4); // 3-5
225 aCache.remove(3); // 5
226 assertTrue (!aCache.has(3));
227 assertTrue (aCache.get(5)->value == 6); // 5
228
229 // removing illegal entries should work too
230 aCache.remove(666);
231
232 aCache.clear();
233 assertTrue (!aCache.has(5));
234}
235
236
237void UniqueExpireLRUCacheTest::testCacheSizeN()
238{
239 // 3-1 represents the cache sorted by pos, elements get replaced at the end of the list
240 // 3-1|5 -> 5 gets removed
241 UniqueExpireLRUCache<int, IntVal> aCache(3);
242 aCache.add(1, IntVal(2, DURSLEEP)); // 1
243 assertTrue (aCache.has(1));
244 assertTrue (aCache.get(1)->value == 2);
245
246 aCache.add(3, IntVal(4, DURSLEEP)); // 3-1
247 assertTrue (aCache.has(1));
248 assertTrue (aCache.has(3));
249 assertTrue (aCache.get(1)->value == 2); // 1-3
250 assertTrue (aCache.get(3)->value == 4); // 3-1
251
252 aCache.add(5, IntVal(6, DURSLEEP)); // 5-3-1
253 assertTrue (aCache.has(1));
254 assertTrue (aCache.has(3));
255 assertTrue (aCache.has(5));
256 assertTrue (aCache.get(5)->value == 6); // 5-3-1
257 assertTrue (aCache.get(3)->value == 4); // 3-5-1
258
259 aCache.add(7, IntVal(8, DURSLEEP)); // 7-5-3|1
260 assertTrue (!aCache.has(1));
261 assertTrue (aCache.has(7));
262 assertTrue (aCache.has(3));
263 assertTrue (aCache.has(5));
264 assertTrue (aCache.get(5)->value == 6); // 5-7-3
265 assertTrue (aCache.get(3)->value == 4); // 3-5-7
266 assertTrue (aCache.get(7)->value == 8); // 7-3-5
267
268 // test remove from the end and the beginning of the list
269 aCache.remove(5); // 7-3
270 assertTrue (!aCache.has(5));
271 assertTrue (aCache.get(3)->value == 4); // 3-7
272 aCache.add(5, IntVal(6, DURSLEEP)); // 5-3-7
273 assertTrue (aCache.get(7)->value == 8); // 7-5-3
274 aCache.remove(7); // 5-3
275 assertTrue (!aCache.has(7));
276 assertTrue (aCache.has(3));
277 assertTrue (aCache.get(5)->value == 6); // 5-3
278
279 // removing illegal entries should work too
280 aCache.remove(666);
281
282 aCache.clear();
283 assertTrue (!aCache.has(5));
284 assertTrue (!aCache.has(3));
285}
286
287
288void UniqueExpireLRUCacheTest::testDuplicateAdd()
289{
290 UniqueExpireLRUCache<int, IntVal> aCache(3);
291 aCache.add(1, IntVal(2, DURSLEEP)); // 1
292 assertTrue (aCache.has(1));
293 assertTrue (aCache.get(1)->value == 2);
294 aCache.add(1, IntVal(3, DURSLEEP));
295 assertTrue (aCache.has(1));
296 assertTrue (aCache.get(1)->value == 3);
297}
298
299
300void UniqueExpireLRUCacheTest::setUp()
301{
302}
303
304
305void UniqueExpireLRUCacheTest::tearDown()
306{
307}
308
309
310CppUnit::Test* UniqueExpireLRUCacheTest::suite()
311{
312 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("UniqueExpireLRUCacheTest");
313
314 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testClear);
315 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testAccessClear);
316 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testExpire0);
317 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testExpireN);
318 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testCacheSize0);
319 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testCacheSize1);
320 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testCacheSize2);
321 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testCacheSizeN);
322 CppUnit_addTest(pSuite, UniqueExpireLRUCacheTest, testDuplicateAdd);
323
324 return pSuite;
325}
326