1b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien/*
2b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * Copyright (C) 2012 The Android Open Source Project
3b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien *
4b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * Licensed under the Apache License, Version 2.0 (the "License");
5b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * you may not use this file except in compliance with the License.
6b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * You may obtain a copy of the License at
7b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien *
8b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien *      http://www.apache.org/licenses/LICENSE-2.0
9b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien *
10b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * Unless required by applicable law or agreed to in writing, software
11b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * distributed under the License is distributed on an "AS IS" BASIS,
12b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * See the License for the specific language governing permissions and
14b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien * limitations under the License.
15b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien */
16b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
17b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien#include <stdlib.h>
18b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien#include <utils/JenkinsHash.h>
19b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien#include <utils/LruCache.h>
20b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien#include <cutils/log.h>
21b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien#include <gtest/gtest.h>
22b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
2327d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albertnamespace {
24b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
25b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levientypedef int SimpleKey;
26b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levientypedef const char* StringValue;
27b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
28b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienstruct ComplexKey {
29b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    int k;
30b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
31b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    explicit ComplexKey(int k) : k(k) {
32b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount += 1;
33b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
34b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
35b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ComplexKey(const ComplexKey& other) : k(other.k) {
36b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount += 1;
37b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
38b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
39b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ~ComplexKey() {
40b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount -= 1;
41b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
42b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
43b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    bool operator ==(const ComplexKey& other) const {
44b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        return k == other.k;
45b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
46b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
47b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    bool operator !=(const ComplexKey& other) const {
48b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        return k != other.k;
49b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
50b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
51b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    static ssize_t instanceCount;
52b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien};
53b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
54b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienssize_t ComplexKey::instanceCount = 0;
55b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
56b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienstruct ComplexValue {
57b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    int v;
58b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
59b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    explicit ComplexValue(int v) : v(v) {
60b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount += 1;
61b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
62b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
63b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ComplexValue(const ComplexValue& other) : v(other.v) {
64b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount += 1;
65b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
66b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
67b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ~ComplexValue() {
68b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        instanceCount -= 1;
69b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
70b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
71b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    static ssize_t instanceCount;
72b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien};
73b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
74b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienssize_t ComplexValue::instanceCount = 0;
75b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
76b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Girostruct KeyWithPointer {
77b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    int *ptr;
78b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    bool operator ==(const KeyWithPointer& other) const {
79b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro        return *ptr == *other.ptr;
80b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    }
81b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro};
82b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro
8327d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert} // namespace
8427d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
8527d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
8627d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albertnamespace android {
8727d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
88b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levientypedef LruCache<ComplexKey, ComplexValue> ComplexCache;
89b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
9027d166cb3aecc003b2ea576ec23695aff78de1a5Dan Alberttemplate<> inline android::hash_t hash_type(const ComplexKey& value) {
9127d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert    return hash_type(value.k);
9227d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert}
9327d166cb3aecc003b2ea576ec23695aff78de1a5Dan Albert
94b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Girotemplate<> inline android::hash_t hash_type(const KeyWithPointer& value) {
95b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    return hash_type(*value.ptr);
96b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro}
97b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro
98b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienclass EntryRemovedCallback : public OnEntryRemoved<SimpleKey, StringValue> {
99b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienpublic:
100b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EntryRemovedCallback() : callbackCount(0), lastKey(-1), lastValue(NULL) { }
101b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ~EntryRemovedCallback() {}
102b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    void operator()(SimpleKey& k, StringValue& v) {
103b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        callbackCount += 1;
104b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        lastKey = k;
105b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        lastValue = v;
106b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
107b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ssize_t callbackCount;
108b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    SimpleKey lastKey;
109b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    StringValue lastValue;
110b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien};
111b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
112b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giroclass InvalidateKeyCallback : public OnEntryRemoved<KeyWithPointer, StringValue> {
113b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giropublic:
114b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    void operator()(KeyWithPointer& k, StringValue&) {
115b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro        delete k.ptr;
116b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro        k.ptr = nullptr;
117b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    }
118b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro};
119b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro
120b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienclass LruCacheTest : public testing::Test {
121b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienprotected:
122b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    virtual void SetUp() {
123b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        ComplexKey::instanceCount = 0;
124b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        ComplexValue::instanceCount = 0;
125b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
126b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
127b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    virtual void TearDown() {
128b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
129b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
130b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
131b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    void assertInstanceCount(ssize_t keys, ssize_t values) {
132b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        if (keys != ComplexKey::instanceCount || values != ComplexValue::instanceCount) {
133b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien            FAIL() << "Expected " << keys << " keys and " << values << " values "
134b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien                    "but there were actually " << ComplexKey::instanceCount << " keys and "
135b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien                    << ComplexValue::instanceCount << " values";
136b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        }
137b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
138b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien};
139b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
140b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, Empty) {
141b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
142b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
143b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(NULL, cache.get(0));
144b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(0u, cache.size());
145b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
146b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
147b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, Simple) {
148b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
149b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
150b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
151b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
152b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
153b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("one", cache.get(1));
154b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("two", cache.get(2));
155b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("three", cache.get(3));
156b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(3u, cache.size());
157b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
158b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
159b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, MaxCapacity) {
160b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(2);
161b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
162b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
163b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
164b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
165b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(NULL, cache.get(1));
166b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("two", cache.get(2));
167b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("three", cache.get(3));
168b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(2u, cache.size());
169b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
170b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
171b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, RemoveLru) {
172b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
173b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
174b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
175b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
176b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
177b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.removeOldest();
178b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(NULL, cache.get(1));
179b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("two", cache.get(2));
180b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("three", cache.get(3));
181b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(2u, cache.size());
182b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
183b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
184b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, GetUpdatesLru) {
185b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
186b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
187b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
188b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
189b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
190b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("one", cache.get(1));
191b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.removeOldest();
192b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("one", cache.get(1));
193b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(NULL, cache.get(2));
194b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("three", cache.get(3));
195b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(2u, cache.size());
196b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
197b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
198b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levienuint32_t hash_int(int x) {
199b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    return JenkinsHashWhiten(JenkinsHashMix(0, x));
200b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
201b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
202b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, StressTest) {
203b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    const size_t kCacheSize = 512;
204b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(512);
205b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    const size_t kNumKeys = 16 * 1024;
206b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    const size_t kNumIters = 100000;
207b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    char* strings[kNumKeys];
208b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
209b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    for (size_t i = 0; i < kNumKeys; i++) {
210b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        strings[i] = (char *)malloc(16);
211cdc1cfb3e51f3caddc1f290b46dc789c036f22edSasha Levitskiy        sprintf(strings[i], "%zu", i);
212b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
213b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
214b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    srandom(12345);
215b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    int hitCount = 0;
216b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    for (size_t i = 0; i < kNumIters; i++) {
217b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        int index = random() % kNumKeys;
218b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        uint32_t key = hash_int(index);
219b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        const char *val = cache.get(key);
220b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        if (val != NULL) {
221b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien            EXPECT_EQ(strings[index], val);
222b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien            hitCount++;
223b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        } else {
224b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien            cache.put(key, strings[index]);
225b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        }
226b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
227b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    size_t expectedHitCount = kNumIters * kCacheSize / kNumKeys;
228b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_LT(int(expectedHitCount * 0.9), hitCount);
229b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_GT(int(expectedHitCount * 1.1), hitCount);
230b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(kCacheSize, cache.size());
231b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
232b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    for (size_t i = 0; i < kNumKeys; i++) {
233b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        free((void *)strings[i]);
234b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
235b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
236b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
237b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, NoLeak) {
238b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ComplexCache cache(100);
239b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
240b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(0), ComplexValue(0));
241b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(1), ComplexValue(1));
2423e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(2U, cache.size());
243bb58cde899dc331d0146faa8a85e7fe2e8f1f490Sergio Giro    assertInstanceCount(2, 3);  // the member mNullValue counts as an instance
244b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
245b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
246b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, Clear) {
247b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ComplexCache cache(100);
248b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
249b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(0), ComplexValue(0));
250b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(1), ComplexValue(1));
2513e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(2U, cache.size());
252b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(2, 3);
253b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.clear();
254b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(0, 1);
255b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
256b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
257b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, ClearNoDoubleFree) {
258b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    {
259b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        ComplexCache cache(100);
260b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
261b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        cache.put(ComplexKey(0), ComplexValue(0));
262b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        cache.put(ComplexKey(1), ComplexValue(1));
2633e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich        EXPECT_EQ(2U, cache.size());
264b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        assertInstanceCount(2, 3);
265b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        cache.removeOldest();
266b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        cache.clear();
267b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien        assertInstanceCount(0, 1);
268b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    }
269b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(0, 0);
270b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
271b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
272b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, ClearReuseOk) {
273b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    ComplexCache cache(100);
274b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
275b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(0), ComplexValue(0));
276b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(1), ComplexValue(1));
2773e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(2U, cache.size());
278b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(2, 3);
279b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.clear();
280b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(0, 1);
281b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(0), ComplexValue(0));
282b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(ComplexKey(1), ComplexValue(1));
2833e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(2U, cache.size());
284b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    assertInstanceCount(2, 3);
285b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
286b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
287b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, Callback) {
288b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
289b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EntryRemovedCallback callback;
290b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.setOnEntryRemovedListener(&callback);
291b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
292b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
293b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
294b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
2953e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(3U, cache.size());
296b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.removeOldest();
297b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(1, callback.callbackCount);
298b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(1, callback.lastKey);
299b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_STREQ("one", callback.lastValue);
300b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
301b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
302b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph LevienTEST_F(LruCacheTest, CallbackOnClear) {
303b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    LruCache<SimpleKey, StringValue> cache(100);
304b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EntryRemovedCallback callback;
305b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.setOnEntryRemovedListener(&callback);
306b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
307b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(1, "one");
308b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(2, "two");
309b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.put(3, "three");
3103e6c451908418484d6e3b4a9f26e793af5d04b62Nick Kralevich    EXPECT_EQ(3U, cache.size());
311b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    cache.clear();
312b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien    EXPECT_EQ(3, callback.callbackCount);
313b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
314b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien
315b7170fe3fe0d8933de57968222bab95ef6615a5aSergio GiroTEST_F(LruCacheTest, CallbackRemovesKeyWorksOK) {
316b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    LruCache<KeyWithPointer, StringValue> cache(1);
317b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    InvalidateKeyCallback callback;
318b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    cache.setOnEntryRemovedListener(&callback);
319b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    KeyWithPointer key1;
320b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    key1.ptr = new int(1);
321b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    KeyWithPointer key2;
322b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    key2.ptr = new int(2);
323b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro
324b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    cache.put(key1, "one");
325b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    // As the size of the cache is 1, the put will call the callback.
326b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    // Make sure everything goes smoothly even if the callback invalidates
327b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    // the key (b/24785286)
328b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    cache.put(key2, "two");
329b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    EXPECT_EQ(1U, cache.size());
330b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    EXPECT_STREQ("two", cache.get(key2));
331b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro    cache.clear();
332b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro}
333b7170fe3fe0d8933de57968222bab95ef6615a5aSergio Giro
3340cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, IteratorCheck) {
3350cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
3360cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3370cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 4);
3380cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(2, 5);
3390cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(3, 6);
3400cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(3U, cache.size());
3410cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3420cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
3430cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
3440cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
3450cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        int v = it.value();
3460cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        // Check we haven't seen the value before.
3470cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        EXPECT_TRUE(returnedValues.find(v) == returnedValues.end());
3480cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(v);
3490cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
3500cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({4, 5, 6}), returnedValues);
3510cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
3520cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3530cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, EmptyCacheIterator) {
3540cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    // Check that nothing crashes...
3550cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
3560cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3570cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
3580cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
3590cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
3600cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
3610cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
3620cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>(), returnedValues);
3630cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
3640cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3650cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, OneElementCacheIterator) {
3660cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    // Check that nothing crashes...
3670cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
3680cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 2);
3690cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3700cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
3710cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
3720cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
3730cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
3740cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
3750cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({ 2 }), returnedValues);
3760cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
3770cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3780cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, OneElementCacheRemove) {
3790cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
3800cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 2);
3810cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3820cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.remove(1);
3830cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3840cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
3850cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
3860cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
3870cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
3880cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
3890cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({ }), returnedValues);
3900cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
3910cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3920cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, Remove) {
3930cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
3940cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 4);
3950cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(2, 5);
3960cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(3, 6);
3970cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
3980cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.remove(2);
3990cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4000cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
4010cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
4020cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
4030cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
4040cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
4050cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({ 4, 6 }), returnedValues);
4060cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
4070cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4080cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, RemoveYoungest) {
4090cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
4100cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 4);
4110cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(2, 5);
4120cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(3, 6);
4130cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4140cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.remove(3);
4150cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4160cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
4170cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
4180cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
4190cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
4200cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
4210cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({ 4, 5 }), returnedValues);
4220cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
4230cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4240cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio GiroTEST_F(LruCacheTest, RemoveNonMember) {
4250cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int> cache(100);
4260cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(1, 4);
4270cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(2, 5);
4280cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.put(3, 6);
4290cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4300cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    cache.remove(7);
4310cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
4320cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    LruCache<int, int>::Iterator it(cache);
4330cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    std::unordered_set<int> returnedValues;
4340cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    while (it.next()) {
4350cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro        returnedValues.insert(it.value());
4360cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    }
4370cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro    EXPECT_EQ(std::unordered_set<int>({ 4, 5, 6 }), returnedValues);
4380cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro}
4390cb59c0dce34bd1518aa775e45e1dd7810195b78Sergio Giro
440b6ea175b6b4d0aaac85ed6cd8ccac01ab896486bRaph Levien}
441