1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/refinery/symbols/simple_cache.h"
16 :
17 : #include "base/bind.h"
18 : #include "base/macros.h"
19 : #include "base/memory/ref_counted.h"
20 : #include "gtest/gtest.h"
21 :
22 : namespace refinery {
23 :
24 : namespace {
25 :
26 : const wchar_t kCacheKeyOne[] = L"cache-key-one";
27 :
28 : class SimpleEntry : public base::RefCounted<SimpleEntry> {
29 : public:
30 E : explicit SimpleEntry(int value) : value_(value) {}
31 :
32 E : bool operator==(const SimpleEntry& other) const {
33 E : return value_ == other.value_;
34 E : }
35 :
36 : private:
37 : friend class base::RefCounted<SimpleEntry>;
38 E : ~SimpleEntry() {}
39 :
40 : int value_;
41 :
42 : DISALLOW_COPY_AND_ASSIGN(SimpleEntry);
43 : };
44 :
45 : class SimpleCacheLoadingTest : public testing::Test {
46 : public:
47 E : void SetUp() override {
48 E : Test::SetUp();
49 E : load_cnt_ = 0;
50 E : }
51 :
52 E : bool FailToLoad(scoped_refptr<SimpleEntry>* entry) {
53 E : CHECK(entry);
54 E : load_cnt_++;
55 E : return false;
56 E : }
57 :
58 E : bool Load(scoped_refptr<SimpleEntry>* entry) {
59 E : CHECK(entry);
60 E : *entry = new SimpleEntry(43);
61 E : load_cnt_++;
62 E : return true;
63 E : }
64 :
65 E : int load_cnt() { return load_cnt_; }
66 :
67 : private:
68 : int load_cnt_;
69 : };
70 :
71 : } // namespace
72 :
73 E : TEST(SimpleCacheTest, BasicTest) {
74 E : SimpleCache<SimpleEntry> cache;
75 :
76 : // Empty cache - retrieval fails.
77 E : scoped_refptr<SimpleEntry> retrieved;
78 E : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
79 E : ASSERT_EQ(nullptr, retrieved.get());
80 :
81 : // Store and retrieve.
82 E : scoped_refptr<SimpleEntry> entry_one = new SimpleEntry(42);
83 E : cache.Store(kCacheKeyOne, entry_one);
84 E : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
85 E : ASSERT_EQ(*entry_one, *retrieved);
86 E : }
87 :
88 E : TEST_F(SimpleCacheLoadingTest, LoadingFailsTest) {
89 E : SimpleCache<SimpleEntry> cache;
90 E : ASSERT_EQ(0, load_cnt());
91 :
92 : // The entry is not in the cache.
93 E : scoped_refptr<SimpleEntry> retrieved;
94 E : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
95 E : ASSERT_EQ(0, load_cnt());
96 :
97 : // GetOrLoad that fails to load.
98 : SimpleCache<SimpleEntry>::LoadingCallback load_cb =
99 E : base::Bind(&SimpleCacheLoadingTest::FailToLoad, base::Unretained(this));
100 E : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
101 E : ASSERT_EQ(nullptr, retrieved.get());
102 E : ASSERT_EQ(1, load_cnt());
103 :
104 : // Second call uses the cached value.
105 E : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
106 E : ASSERT_EQ(nullptr, retrieved.get());
107 E : ASSERT_EQ(1, load_cnt());
108 :
109 : // There should now be a negative entry in the cache.
110 E : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
111 E : ASSERT_EQ(nullptr, retrieved.get());
112 E : ASSERT_EQ(1, load_cnt());
113 E : }
114 :
115 E : TEST_F(SimpleCacheLoadingTest, LoadingSucceedsTest) {
116 E : SimpleCache<SimpleEntry> cache;
117 :
118 : // The entry is not in the cache.
119 E : scoped_refptr<SimpleEntry> retrieved;
120 E : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
121 E : ASSERT_EQ(0, load_cnt());
122 :
123 : // GetOrLoad that succeeds to load.
124 : SimpleCache<SimpleEntry>::LoadingCallback load_cb =
125 E : base::Bind(&SimpleCacheLoadingTest::Load, base::Unretained(this));
126 E : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
127 E : scoped_refptr<SimpleEntry> expected = new SimpleEntry(43);
128 E : ASSERT_EQ(*expected, *retrieved);
129 E : ASSERT_EQ(1, load_cnt());
130 :
131 : // Second call uses the cached value.
132 E : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
133 E : ASSERT_EQ(*expected, *retrieved);
134 E : ASSERT_EQ(1, load_cnt());
135 :
136 : // The entry should be in the cache.
137 E : retrieved = nullptr;
138 E : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
139 E : ASSERT_EQ(*expected, *retrieved);
140 E : ASSERT_EQ(1, load_cnt());
141 E : }
142 :
143 :
144 : } // namespace refinery
|