1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18
19 #include <android/log.h>
20 #include <gtest/gtest.h>
21 #include <utils/JenkinsHash.h>
22 #include <utils/LruCache.h>
23
24 namespace {
25
26 typedef int SimpleKey;
27 typedef const char* StringValue;
28
29 struct ComplexKey {
30 int k;
31
ComplexKey__anon1de738fe0111::ComplexKey32 explicit ComplexKey(int k) : k(k) {
33 instanceCount += 1;
34 }
35
ComplexKey__anon1de738fe0111::ComplexKey36 ComplexKey(const ComplexKey& other) : k(other.k) {
37 instanceCount += 1;
38 }
39
~ComplexKey__anon1de738fe0111::ComplexKey40 ~ComplexKey() {
41 instanceCount -= 1;
42 }
43
operator ==__anon1de738fe0111::ComplexKey44 bool operator ==(const ComplexKey& other) const {
45 return k == other.k;
46 }
47
operator !=__anon1de738fe0111::ComplexKey48 bool operator !=(const ComplexKey& other) const {
49 return k != other.k;
50 }
51
52 static ssize_t instanceCount;
53 };
54
55 ssize_t ComplexKey::instanceCount = 0;
56
57 struct ComplexValue {
58 int v;
59
ComplexValue__anon1de738fe0111::ComplexValue60 explicit ComplexValue(int v) : v(v) {
61 instanceCount += 1;
62 }
63
ComplexValue__anon1de738fe0111::ComplexValue64 ComplexValue(const ComplexValue& other) : v(other.v) {
65 instanceCount += 1;
66 }
67
~ComplexValue__anon1de738fe0111::ComplexValue68 ~ComplexValue() {
69 instanceCount -= 1;
70 }
71
72 static ssize_t instanceCount;
73 };
74
75 ssize_t ComplexValue::instanceCount = 0;
76
77 struct KeyWithPointer {
78 int *ptr;
operator ==__anon1de738fe0111::KeyWithPointer79 bool operator ==(const KeyWithPointer& other) const {
80 return *ptr == *other.ptr;
81 }
82 };
83
84 struct KeyFailsOnCopy : public ComplexKey {
85 public:
KeyFailsOnCopy__anon1de738fe0111::KeyFailsOnCopy86 KeyFailsOnCopy(const KeyFailsOnCopy& key) : ComplexKey(key) {
87 ADD_FAILURE();
88 }
KeyFailsOnCopy__anon1de738fe0111::KeyFailsOnCopy89 KeyFailsOnCopy(int key) : ComplexKey(key) { }
90 };
91
92 } // namespace
93
94
95 namespace android {
96
97 typedef LruCache<ComplexKey, ComplexValue> ComplexCache;
98
hash_type(const ComplexKey & value)99 template<> inline android::hash_t hash_type(const ComplexKey& value) {
100 return hash_type(value.k);
101 }
102
hash_type(const KeyWithPointer & value)103 template<> inline android::hash_t hash_type(const KeyWithPointer& value) {
104 return hash_type(*value.ptr);
105 }
106
hash_type(const KeyFailsOnCopy & value)107 template<> inline android::hash_t hash_type(const KeyFailsOnCopy& value) {
108 return hash_type<ComplexKey>(value);
109 }
110
111 class EntryRemovedCallback : public OnEntryRemoved<SimpleKey, StringValue> {
112 public:
EntryRemovedCallback()113 EntryRemovedCallback() : callbackCount(0), lastKey(-1), lastValue(nullptr) { }
~EntryRemovedCallback()114 ~EntryRemovedCallback() {}
operator ()(SimpleKey & k,StringValue & v)115 void operator()(SimpleKey& k, StringValue& v) {
116 callbackCount += 1;
117 lastKey = k;
118 lastValue = v;
119 }
120 ssize_t callbackCount;
121 SimpleKey lastKey;
122 StringValue lastValue;
123 };
124
125 class InvalidateKeyCallback : public OnEntryRemoved<KeyWithPointer, StringValue> {
126 public:
operator ()(KeyWithPointer & k,StringValue &)127 void operator()(KeyWithPointer& k, StringValue&) {
128 delete k.ptr;
129 k.ptr = nullptr;
130 }
131 };
132
133 class LruCacheTest : public testing::Test {
134 protected:
SetUp()135 virtual void SetUp() {
136 ComplexKey::instanceCount = 0;
137 ComplexValue::instanceCount = 0;
138 }
139
TearDown()140 virtual void TearDown() {
141 ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
142 }
143
assertInstanceCount(ssize_t keys,ssize_t values)144 void assertInstanceCount(ssize_t keys, ssize_t values) {
145 if (keys != ComplexKey::instanceCount || values != ComplexValue::instanceCount) {
146 FAIL() << "Expected " << keys << " keys and " << values << " values "
147 "but there were actually " << ComplexKey::instanceCount << " keys and "
148 << ComplexValue::instanceCount << " values";
149 }
150 }
151 };
152
TEST_F(LruCacheTest,Empty)153 TEST_F(LruCacheTest, Empty) {
154 LruCache<SimpleKey, StringValue> cache(100);
155
156 EXPECT_EQ(nullptr, cache.get(0));
157 EXPECT_EQ(0u, cache.size());
158 }
159
TEST_F(LruCacheTest,Simple)160 TEST_F(LruCacheTest, Simple) {
161 LruCache<SimpleKey, StringValue> cache(100);
162
163 cache.put(1, "one");
164 cache.put(2, "two");
165 cache.put(3, "three");
166 EXPECT_STREQ("one", cache.get(1));
167 EXPECT_STREQ("two", cache.get(2));
168 EXPECT_STREQ("three", cache.get(3));
169 EXPECT_EQ(3u, cache.size());
170 }
171
TEST_F(LruCacheTest,MaxCapacity)172 TEST_F(LruCacheTest, MaxCapacity) {
173 LruCache<SimpleKey, StringValue> cache(2);
174
175 cache.put(1, "one");
176 cache.put(2, "two");
177 cache.put(3, "three");
178 EXPECT_EQ(nullptr, cache.get(1));
179 EXPECT_STREQ("two", cache.get(2));
180 EXPECT_STREQ("three", cache.get(3));
181 EXPECT_EQ(2u, cache.size());
182 }
183
TEST_F(LruCacheTest,RemoveLru)184 TEST_F(LruCacheTest, RemoveLru) {
185 LruCache<SimpleKey, StringValue> cache(100);
186
187 cache.put(1, "one");
188 cache.put(2, "two");
189 cache.put(3, "three");
190 cache.removeOldest();
191 EXPECT_EQ(nullptr, cache.get(1));
192 EXPECT_STREQ("two", cache.get(2));
193 EXPECT_STREQ("three", cache.get(3));
194 EXPECT_EQ(2u, cache.size());
195 }
196
TEST_F(LruCacheTest,GetUpdatesLru)197 TEST_F(LruCacheTest, GetUpdatesLru) {
198 LruCache<SimpleKey, StringValue> cache(100);
199
200 cache.put(1, "one");
201 cache.put(2, "two");
202 cache.put(3, "three");
203 EXPECT_STREQ("one", cache.get(1));
204 cache.removeOldest();
205 EXPECT_STREQ("one", cache.get(1));
206 EXPECT_EQ(nullptr, cache.get(2));
207 EXPECT_STREQ("three", cache.get(3));
208 EXPECT_EQ(2u, cache.size());
209 }
210
hash_int(int x)211 uint32_t hash_int(int x) {
212 return JenkinsHashWhiten(JenkinsHashMix(0, x));
213 }
214
TEST_F(LruCacheTest,StressTest)215 TEST_F(LruCacheTest, StressTest) {
216 const size_t kCacheSize = 512;
217 LruCache<SimpleKey, StringValue> cache(512);
218 const size_t kNumKeys = 16 * 1024;
219 const size_t kNumIters = 100000;
220 char* strings[kNumKeys];
221
222 for (size_t i = 0; i < kNumKeys; i++) {
223 strings[i] = (char *)malloc(16);
224 sprintf(strings[i], "%zu", i);
225 }
226
227 srandom(12345);
228 int hitCount = 0;
229 for (size_t i = 0; i < kNumIters; i++) {
230 int index = random() % kNumKeys;
231 uint32_t key = hash_int(index);
232 const char *val = cache.get(key);
233 if (val != nullptr) {
234 EXPECT_EQ(strings[index], val);
235 hitCount++;
236 } else {
237 cache.put(key, strings[index]);
238 }
239 }
240 size_t expectedHitCount = kNumIters * kCacheSize / kNumKeys;
241 EXPECT_LT(int(expectedHitCount * 0.9), hitCount);
242 EXPECT_GT(int(expectedHitCount * 1.1), hitCount);
243 EXPECT_EQ(kCacheSize, cache.size());
244
245 for (size_t i = 0; i < kNumKeys; i++) {
246 free((void *)strings[i]);
247 }
248 }
249
TEST_F(LruCacheTest,NoLeak)250 TEST_F(LruCacheTest, NoLeak) {
251 ComplexCache cache(100);
252
253 cache.put(ComplexKey(0), ComplexValue(0));
254 cache.put(ComplexKey(1), ComplexValue(1));
255 EXPECT_EQ(2U, cache.size());
256 assertInstanceCount(2, 3); // the member mNullValue counts as an instance
257 }
258
TEST_F(LruCacheTest,Clear)259 TEST_F(LruCacheTest, Clear) {
260 ComplexCache cache(100);
261
262 cache.put(ComplexKey(0), ComplexValue(0));
263 cache.put(ComplexKey(1), ComplexValue(1));
264 EXPECT_EQ(2U, cache.size());
265 assertInstanceCount(2, 3);
266 cache.clear();
267 assertInstanceCount(0, 1);
268 }
269
TEST_F(LruCacheTest,ClearNoDoubleFree)270 TEST_F(LruCacheTest, ClearNoDoubleFree) {
271 {
272 ComplexCache cache(100);
273
274 cache.put(ComplexKey(0), ComplexValue(0));
275 cache.put(ComplexKey(1), ComplexValue(1));
276 EXPECT_EQ(2U, cache.size());
277 assertInstanceCount(2, 3);
278 cache.removeOldest();
279 cache.clear();
280 assertInstanceCount(0, 1);
281 }
282 assertInstanceCount(0, 0);
283 }
284
TEST_F(LruCacheTest,ClearReuseOk)285 TEST_F(LruCacheTest, ClearReuseOk) {
286 ComplexCache cache(100);
287
288 cache.put(ComplexKey(0), ComplexValue(0));
289 cache.put(ComplexKey(1), ComplexValue(1));
290 EXPECT_EQ(2U, cache.size());
291 assertInstanceCount(2, 3);
292 cache.clear();
293 assertInstanceCount(0, 1);
294 cache.put(ComplexKey(0), ComplexValue(0));
295 cache.put(ComplexKey(1), ComplexValue(1));
296 EXPECT_EQ(2U, cache.size());
297 assertInstanceCount(2, 3);
298 }
299
TEST_F(LruCacheTest,Callback)300 TEST_F(LruCacheTest, Callback) {
301 EntryRemovedCallback callback;
302 LruCache<SimpleKey, StringValue> cache(100);
303 cache.setOnEntryRemovedListener(&callback);
304
305 cache.put(1, "one");
306 cache.put(2, "two");
307 cache.put(3, "three");
308 EXPECT_EQ(3U, cache.size());
309 cache.removeOldest();
310 EXPECT_EQ(1, callback.callbackCount);
311 EXPECT_EQ(1, callback.lastKey);
312 EXPECT_STREQ("one", callback.lastValue);
313 }
314
TEST_F(LruCacheTest,CallbackOnClear)315 TEST_F(LruCacheTest, CallbackOnClear) {
316 EntryRemovedCallback callback;
317 LruCache<SimpleKey, StringValue> cache(100);
318 cache.setOnEntryRemovedListener(&callback);
319
320 cache.put(1, "one");
321 cache.put(2, "two");
322 cache.put(3, "three");
323 EXPECT_EQ(3U, cache.size());
324 cache.clear();
325 EXPECT_EQ(3, callback.callbackCount);
326 }
327
TEST_F(LruCacheTest,CallbackRemovesKeyWorksOK)328 TEST_F(LruCacheTest, CallbackRemovesKeyWorksOK) {
329 InvalidateKeyCallback callback;
330 LruCache<KeyWithPointer, StringValue> cache(1);
331 cache.setOnEntryRemovedListener(&callback);
332 KeyWithPointer key1;
333 key1.ptr = new int(1);
334 KeyWithPointer key2;
335 key2.ptr = new int(2);
336
337 cache.put(key1, "one");
338 // As the size of the cache is 1, the put will call the callback.
339 // Make sure everything goes smoothly even if the callback invalidates
340 // the key (b/24785286)
341 cache.put(key2, "two");
342 EXPECT_EQ(1U, cache.size());
343 EXPECT_STREQ("two", cache.get(key2));
344 cache.clear();
345 }
346
TEST_F(LruCacheTest,IteratorCheck)347 TEST_F(LruCacheTest, IteratorCheck) {
348 LruCache<int, int> cache(100);
349
350 cache.put(1, 4);
351 cache.put(2, 5);
352 cache.put(3, 6);
353 EXPECT_EQ(3U, cache.size());
354
355 LruCache<int, int>::Iterator it(cache);
356 std::unordered_set<int> returnedValues;
357 while (it.next()) {
358 int v = it.value();
359 // Check we haven't seen the value before.
360 EXPECT_TRUE(returnedValues.find(v) == returnedValues.end());
361 returnedValues.insert(v);
362 }
363 EXPECT_EQ(std::unordered_set<int>({4, 5, 6}), returnedValues);
364 }
365
TEST_F(LruCacheTest,EmptyCacheIterator)366 TEST_F(LruCacheTest, EmptyCacheIterator) {
367 // Check that nothing crashes...
368 LruCache<int, int> cache(100);
369
370 LruCache<int, int>::Iterator it(cache);
371 std::unordered_set<int> returnedValues;
372 while (it.next()) {
373 returnedValues.insert(it.value());
374 }
375 EXPECT_EQ(std::unordered_set<int>(), returnedValues);
376 }
377
TEST_F(LruCacheTest,OneElementCacheIterator)378 TEST_F(LruCacheTest, OneElementCacheIterator) {
379 // Check that nothing crashes...
380 LruCache<int, int> cache(100);
381 cache.put(1, 2);
382
383 LruCache<int, int>::Iterator it(cache);
384 std::unordered_set<int> returnedValues;
385 while (it.next()) {
386 returnedValues.insert(it.value());
387 }
388 EXPECT_EQ(std::unordered_set<int>({ 2 }), returnedValues);
389 }
390
TEST_F(LruCacheTest,OneElementCacheRemove)391 TEST_F(LruCacheTest, OneElementCacheRemove) {
392 LruCache<int, int> cache(100);
393 cache.put(1, 2);
394
395 cache.remove(1);
396
397 LruCache<int, int>::Iterator it(cache);
398 std::unordered_set<int> returnedValues;
399 while (it.next()) {
400 returnedValues.insert(it.value());
401 }
402 EXPECT_EQ(std::unordered_set<int>({ }), returnedValues);
403 }
404
TEST_F(LruCacheTest,Remove)405 TEST_F(LruCacheTest, Remove) {
406 LruCache<int, int> cache(100);
407 cache.put(1, 4);
408 cache.put(2, 5);
409 cache.put(3, 6);
410
411 cache.remove(2);
412
413 LruCache<int, int>::Iterator it(cache);
414 std::unordered_set<int> returnedValues;
415 while (it.next()) {
416 returnedValues.insert(it.value());
417 }
418 EXPECT_EQ(std::unordered_set<int>({ 4, 6 }), returnedValues);
419 }
420
TEST_F(LruCacheTest,RemoveYoungest)421 TEST_F(LruCacheTest, RemoveYoungest) {
422 LruCache<int, int> cache(100);
423 cache.put(1, 4);
424 cache.put(2, 5);
425 cache.put(3, 6);
426
427 cache.remove(3);
428
429 LruCache<int, int>::Iterator it(cache);
430 std::unordered_set<int> returnedValues;
431 while (it.next()) {
432 returnedValues.insert(it.value());
433 }
434 EXPECT_EQ(std::unordered_set<int>({ 4, 5 }), returnedValues);
435 }
436
TEST_F(LruCacheTest,RemoveNonMember)437 TEST_F(LruCacheTest, RemoveNonMember) {
438 LruCache<int, int> cache(100);
439 cache.put(1, 4);
440 cache.put(2, 5);
441 cache.put(3, 6);
442
443 cache.remove(7);
444
445 LruCache<int, int>::Iterator it(cache);
446 std::unordered_set<int> returnedValues;
447 while (it.next()) {
448 returnedValues.insert(it.value());
449 }
450 EXPECT_EQ(std::unordered_set<int>({ 4, 5, 6 }), returnedValues);
451 }
452
TEST_F(LruCacheTest,DontCopyKeyInGet)453 TEST_F(LruCacheTest, DontCopyKeyInGet) {
454 LruCache<KeyFailsOnCopy, KeyFailsOnCopy> cache(1);
455 // Check that get doesn't copy the key
456 cache.get(KeyFailsOnCopy(0));
457 }
458
459 }
460