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 | |
22 | using namespace Poco; |
23 | |
24 | |
25 | struct 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 | |
41 | typedef AccessExpirationDecorator<int> DIntVal; |
42 | |
43 | |
44 | #define DURSLEEP 250 |
45 | #define DURHALFSLEEP DURSLEEP / 2 |
46 | #define DURWAIT 300 |
47 | |
48 | |
49 | UniqueExpireLRUCacheTest::UniqueExpireLRUCacheTest(const std::string& rName): CppUnit::TestCase(rName) |
50 | { |
51 | } |
52 | |
53 | |
54 | UniqueExpireLRUCacheTest::~UniqueExpireLRUCacheTest() |
55 | { |
56 | } |
57 | |
58 | |
59 | void 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 | |
79 | void 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 | |
97 | void UniqueExpireLRUCacheTest::testExpire0() |
98 | { |
99 | UniqueExpireLRUCache<int, IntVal> aCache; |
100 | aCache.add(1, IntVal(2, 0)); |
101 | assertTrue (!aCache.has(1)); |
102 | } |
103 | |
104 | |
105 | void 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 | |
157 | void 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 | |
171 | void 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 | |
197 | void 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 | |
237 | void 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 | |
288 | void 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 | |
300 | void UniqueExpireLRUCacheTest::setUp() |
301 | { |
302 | } |
303 | |
304 | |
305 | void UniqueExpireLRUCacheTest::tearDown() |
306 | { |
307 | } |
308 | |
309 | |
310 | CppUnit::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 | |