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 m : namespace refinery {
23 :
24 m : namespace {
25 :
26 m : const wchar_t kCacheKeyOne[] = L"cache-key-one";
27 :
28 m : class SimpleEntry : public base::RefCounted<SimpleEntry> {
29 m : public:
30 m : explicit SimpleEntry(int value) : value_(value) {}
31 :
32 m : bool operator==(const SimpleEntry& other) const {
33 m : return value_ == other.value_;
34 m : }
35 :
36 m : private:
37 m : friend class base::RefCounted<SimpleEntry>;
38 m : ~SimpleEntry() {}
39 :
40 m : int value_;
41 :
42 m : DISALLOW_COPY_AND_ASSIGN(SimpleEntry);
43 m : };
44 :
45 m : class SimpleCacheLoadingTest : public testing::Test {
46 m : public:
47 m : void SetUp() override {
48 m : Test::SetUp();
49 m : load_cnt_ = 0;
50 m : }
51 :
52 m : bool FailToLoad(scoped_refptr<SimpleEntry>* entry) {
53 m : CHECK(entry);
54 m : load_cnt_++;
55 m : return false;
56 m : }
57 :
58 m : bool Load(scoped_refptr<SimpleEntry>* entry) {
59 m : CHECK(entry);
60 m : *entry = new SimpleEntry(43);
61 m : load_cnt_++;
62 m : return true;
63 m : }
64 :
65 m : int load_cnt() { return load_cnt_; }
66 :
67 m : private:
68 m : int load_cnt_;
69 m : };
70 :
71 m : } // namespace
72 :
73 m : TEST(SimpleCacheTest, BasicTest) {
74 m : SimpleCache<SimpleEntry> cache;
75 :
76 : // Empty cache - retrieval fails.
77 m : scoped_refptr<SimpleEntry> retrieved;
78 m : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
79 m : ASSERT_EQ(nullptr, retrieved.get());
80 :
81 : // Store and retrieve.
82 m : scoped_refptr<SimpleEntry> entry_one = new SimpleEntry(42);
83 m : cache.Store(kCacheKeyOne, entry_one);
84 m : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
85 m : ASSERT_EQ(*entry_one, *retrieved);
86 m : }
87 :
88 m : TEST_F(SimpleCacheLoadingTest, LoadingFailsTest) {
89 m : SimpleCache<SimpleEntry> cache;
90 m : ASSERT_EQ(0, load_cnt());
91 :
92 : // The entry is not in the cache.
93 m : scoped_refptr<SimpleEntry> retrieved;
94 m : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
95 m : ASSERT_EQ(0, load_cnt());
96 :
97 : // GetOrLoad that fails to load.
98 m : SimpleCache<SimpleEntry>::LoadingCallback load_cb =
99 m : base::Bind(&SimpleCacheLoadingTest::FailToLoad, base::Unretained(this));
100 m : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
101 m : ASSERT_EQ(nullptr, retrieved.get());
102 m : ASSERT_EQ(1, load_cnt());
103 :
104 : // Second call uses the cached value.
105 m : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
106 m : ASSERT_EQ(nullptr, retrieved.get());
107 m : ASSERT_EQ(1, load_cnt());
108 :
109 : // There should now be a negative entry in the cache.
110 m : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
111 m : ASSERT_EQ(nullptr, retrieved.get());
112 m : ASSERT_EQ(1, load_cnt());
113 m : }
114 :
115 m : TEST_F(SimpleCacheLoadingTest, LoadingSucceedsTest) {
116 m : SimpleCache<SimpleEntry> cache;
117 :
118 : // The entry is not in the cache.
119 m : scoped_refptr<SimpleEntry> retrieved;
120 m : ASSERT_FALSE(cache.Get(kCacheKeyOne, &retrieved));
121 m : ASSERT_EQ(0, load_cnt());
122 :
123 : // GetOrLoad that succeeds to load.
124 m : SimpleCache<SimpleEntry>::LoadingCallback load_cb =
125 m : base::Bind(&SimpleCacheLoadingTest::Load, base::Unretained(this));
126 m : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
127 m : scoped_refptr<SimpleEntry> expected = new SimpleEntry(43);
128 m : ASSERT_EQ(*expected, *retrieved);
129 m : ASSERT_EQ(1, load_cnt());
130 :
131 : // Second call uses the cached value.
132 m : cache.GetOrLoad(kCacheKeyOne, load_cb, &retrieved);
133 m : ASSERT_EQ(*expected, *retrieved);
134 m : ASSERT_EQ(1, load_cnt());
135 :
136 : // The entry should be in the cache.
137 m : retrieved = nullptr;
138 m : ASSERT_TRUE(cache.Get(kCacheKeyOne, &retrieved));
139 m : ASSERT_EQ(*expected, *retrieved);
140 m : ASSERT_EQ(1, load_cnt());
141 m : }
142 :
143 :
144 m : } // namespace refinery
|