1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include "base/memory/ref_counted.h"
9 #include "chrome/browser/android/thumbnail/scoped_ptr_expiring_cache.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 #define MAX_CACHE_SIZE 5u
17 unsigned int GenerateValue(unsigned int key
) {
18 return (key
* key
* 127) % 133 + key
* 23;
23 static scoped_ptr
<MockObject
> Create(unsigned int key
) {
24 return make_scoped_ptr(new MockObject(key
));
27 unsigned int value() const { return value_
; }
30 explicit MockObject(unsigned int key
) : value_(GenerateValue(key
)) {}
33 DISALLOW_COPY_AND_ASSIGN(MockObject
);
38 typedef testing::Test ScopedPtrExpiringCacheTest
;
39 typedef ScopedPtrExpiringCache
<unsigned int, MockObject
>
40 TestScopedPtrExpiringCache
;
42 TEST_F(ScopedPtrExpiringCacheTest
, SimplePutAndGet
) {
43 TestScopedPtrExpiringCache
cache(MAX_CACHE_SIZE
);
44 EXPECT_EQ(MAX_CACHE_SIZE
, cache
.MaximumCacheSize());
45 EXPECT_EQ(0u, cache
.size());
47 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
48 cache
.Put(i
, MockObject::Create(i
).Pass());
51 EXPECT_EQ(MAX_CACHE_SIZE
, cache
.size());
53 unsigned int next_key
= MAX_CACHE_SIZE
;
55 // One cache entry should have been evicted.
56 cache
.Put(next_key
, MockObject::Create(next_key
).Pass());
57 EXPECT_EQ(MAX_CACHE_SIZE
, cache
.size());
59 size_t cached_count
= 0;
60 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
+ 1; i
++) {
62 EXPECT_EQ(GenerateValue(i
), cache
.Get(i
)->value());
67 EXPECT_EQ(MAX_CACHE_SIZE
, cached_count
);
69 // Test Get as membership test.
71 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
+ 1; i
++) {
75 EXPECT_EQ(MAX_CACHE_SIZE
, cached_count
);
78 EXPECT_EQ(0u, cache
.size());
80 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
+ 1; i
++) {
81 EXPECT_EQ(NULL
, cache
.Get(i
));
85 // The eviction policy is least-recently-used, where we define used as insertion
86 // into the cache. We test that the first to be evicted is the first entry
87 // inserted into the cache.
88 TEST_F(ScopedPtrExpiringCacheTest
, EvictedEntry
) {
89 TestScopedPtrExpiringCache
cache(MAX_CACHE_SIZE
);
90 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
91 cache
.Put(i
, MockObject::Create(i
).Pass());
94 unsigned int next_key
= MAX_CACHE_SIZE
;
95 cache
.Put(next_key
, MockObject::Create(next_key
).Pass());
96 EXPECT_EQ(MAX_CACHE_SIZE
, cache
.size());
97 EXPECT_EQ(GenerateValue(next_key
), cache
.Get(next_key
)->value());
99 // The first inserted entry should have been evicted.
100 EXPECT_EQ(NULL
, cache
.Get(0));
102 // The rest of the content should be present.
103 for (unsigned int i
= 1; i
< MAX_CACHE_SIZE
; i
++) {
104 EXPECT_TRUE(cache
.Get(i
) != NULL
);
109 // The first candidate to be evicted is the head of the iterator.
110 unsigned int head_key
= cache
.begin()->first
;
111 EXPECT_TRUE(cache
.Get(head_key
) != NULL
);
112 cache
.Put(next_key
, MockObject::Create(next_key
).Pass());
114 EXPECT_NE(cache
.begin()->first
, head_key
);
115 EXPECT_EQ(NULL
, cache
.Get(head_key
));
118 TEST_F(ScopedPtrExpiringCacheTest
, RetainedEntry
) {
119 TestScopedPtrExpiringCache
cache(MAX_CACHE_SIZE
);
120 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
121 cache
.Put(i
, MockObject::Create(i
).Pass());
124 // Add (cache size - 1)-entries.
125 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
126 EXPECT_TRUE(cache
.Get(i
) != NULL
);
129 for (unsigned int i
= MAX_CACHE_SIZE
; i
< 2 * MAX_CACHE_SIZE
- 1; i
++) {
130 cache
.Put(i
, MockObject::Create(i
).Pass());
133 EXPECT_EQ(MAX_CACHE_SIZE
, cache
.size());
135 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
- 1; i
++) {
136 EXPECT_EQ(NULL
, cache
.Get(i
));
139 // The only retained entry (from the first round of insertion) is the last to
141 EXPECT_TRUE(cache
.Get(MAX_CACHE_SIZE
- 1) != NULL
);
144 // Test that the iterator order is the insertion order. The first element of
145 // the iterator is the oldest entry in the cache.
146 TEST_F(ScopedPtrExpiringCacheTest
, Iterator
) {
147 TestScopedPtrExpiringCache
cache(MAX_CACHE_SIZE
);
148 std::vector
<unsigned int> test_keys
;
149 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
150 test_keys
.push_back(i
);
152 std::random_shuffle(test_keys
.begin(), test_keys
.end());
154 for (unsigned int i
= 0; i
< MAX_CACHE_SIZE
; i
++) {
155 cache
.Put(test_keys
[i
], MockObject::Create(test_keys
[i
]).Pass());
158 TestScopedPtrExpiringCache::iterator cache_iter
= cache
.begin();
159 std::vector
<unsigned int>::iterator key_iter
= test_keys
.begin();
160 while (cache_iter
!= cache
.end() && key_iter
!= test_keys
.end()) {
161 EXPECT_EQ(cache_iter
->first
, *key_iter
);