ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
cache_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #define TEST_NAME "util/cache"
33 #include "util/cache.h"
34 
35 #include "util/testing.h"
36 
37 using namespace colmap;
38 
39 BOOST_AUTO_TEST_CASE(TestLRUCacheEmpty) {
40  LRUCache<int, int> cache(
41  5, [](const int key) { return std::make_shared<int>(key); });
42  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
43  BOOST_CHECK_EQUAL(cache.MaxNumElems(), 5);
44 }
45 
46 BOOST_AUTO_TEST_CASE(TestLRUCacheGet) {
47  LRUCache<int, int> cache(
48  5, [](const int key) { return std::make_shared<int>(key); });
49  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
50  for (int i = 0; i < 5; ++i) {
51  BOOST_CHECK_EQUAL(*cache.Get(i), i);
52  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
53  BOOST_CHECK(cache.Exists(i));
54  }
55 
56  BOOST_CHECK_EQUAL(*cache.Get(5), 5);
57  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
58  BOOST_CHECK(!cache.Exists(0));
59  BOOST_CHECK(cache.Exists(5));
60 
61  BOOST_CHECK_EQUAL(*cache.Get(5), 5);
62  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
63  BOOST_CHECK(!cache.Exists(0));
64  BOOST_CHECK(cache.Exists(5));
65 
66  BOOST_CHECK_EQUAL(*cache.Get(6), 6);
67  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
68  BOOST_CHECK(!cache.Exists(0));
69  BOOST_CHECK(!cache.Exists(1));
70  BOOST_CHECK(cache.Exists(6));
71 }
72 
73 BOOST_AUTO_TEST_CASE(TestLRUCacheGet) {
74  LRUCache<int, int> cache(
75  5, [](const int key) { return std::make_shared<int>(key); });
76  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
77  for (int i = 0; i < 5; ++i) {
78  BOOST_CHECK_EQUAL(*cache.Get(i), i);
79  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
80  BOOST_CHECK(cache.Exists(i));
81  }
82 
83  BOOST_CHECK_EQUAL(*cache.Get(5), 5);
84  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
85  BOOST_CHECK(!cache.Exists(0));
86  BOOST_CHECK(cache.Exists(5));
87 
88  BOOST_CHECK_EQUAL(*cache.Get(5), 5);
89  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
90  BOOST_CHECK(!cache.Exists(0));
91  BOOST_CHECK(cache.Exists(5));
92 
93  BOOST_CHECK_EQUAL(*cache.Get(6), 6);
94  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
95  BOOST_CHECK(!cache.Exists(0));
96  BOOST_CHECK(!cache.Exists(1));
97  BOOST_CHECK(cache.Exists(6));
98 
99  cache.Get(6) = 66;
100  BOOST_CHECK_EQUAL(*cache.Get(6), 66);
101  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
102  BOOST_CHECK(!cache.Exists(0));
103  BOOST_CHECK(!cache.Exists(1));
104  BOOST_CHECK(cache.Exists(6));
105 }
106 
107 BOOST_AUTO_TEST_CASE(TestLRUCacheSet) {
108  LRUCache<int, int> cache(5, [](const int key) { return std::make_shared<int>(-1); });
109  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
110  for (int i = 0; i < 5; ++i) {
111  cache.Set(i, std::make_shared<int>(i));
112  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
113  BOOST_CHECK(cache.Exists(i));
114  }
115 
116  BOOST_CHECK_EQUAL(*cache.Get(5), -1);
117  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
118  BOOST_CHECK(!cache.Exists(0));
119  BOOST_CHECK(cache.Exists(5));
120 
121  BOOST_CHECK_EQUAL(*cache.Get(6), -1);
122  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
123  BOOST_CHECK(!cache.Exists(0));
124  BOOST_CHECK(!cache.Exists(1));
125  BOOST_CHECK(cache.Exists(6));
126 }
127 
128 BOOST_AUTO_TEST_CASE(TestLRUCachePop) {
129  LRUCache<int, int> cache(
130  5, [](const int key) { return std::make_shared<int>(key); });
131  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
132  for (int i = 0; i < 5; ++i) {
133  BOOST_CHECK_EQUAL(*cache.Get(i), i);
134  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
135  BOOST_CHECK(cache.Exists(i));
136  }
137 
138  BOOST_CHECK_EQUAL(*cache.Get(5), 5);
139  BOOST_CHECK_EQUAL(cache.NumElems(), 5);
140  BOOST_CHECK(!cache.Exists(0));
141  BOOST_CHECK(cache.Exists(5));
142 
143  cache.Pop();
144  BOOST_CHECK_EQUAL(cache.NumElems(), 4);
145  cache.Pop();
146  BOOST_CHECK_EQUAL(cache.NumElems(), 3);
147  cache.Pop();
148  BOOST_CHECK_EQUAL(cache.NumElems(), 2);
149  cache.Pop();
150  BOOST_CHECK_EQUAL(cache.NumElems(), 1);
151  cache.Pop();
152  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
153  cache.Pop();
154  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
155 }
156 
157 BOOST_AUTO_TEST_CASE(TestLRUCacheClear) {
158  LRUCache<int, int> cache(
159  5, [](const int key) { return std::make_shared<int>(key); });
160  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
161  for (int i = 0; i < 5; ++i) {
162  BOOST_CHECK_EQUAL(*cache.Get(i), i);
163  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
164  BOOST_CHECK(cache.Exists(i));
165  }
166 
167  cache.Clear();
168  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
169 
170  BOOST_CHECK_EQUAL(*cache.Get(0), 0);
171  BOOST_CHECK_EQUAL(cache.NumElems(), 1);
172  BOOST_CHECK(cache.Exists(0));
173 }
174 
175 struct SizedElem {
176  SizedElem(const size_t num_bytes_) : num_bytes(num_bytes_) {}
177  size_t NumBytes() const { return num_bytes; }
178  size_t num_bytes;
179 };
180 
181 BOOST_AUTO_TEST_CASE(TestMemoryConstrainedLRUCacheEmpty) {
183  5, [](const int key) { return std::make_shared<SizedElem>(key); });
184  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
185  BOOST_CHECK_EQUAL(cache.MaxNumElems(), std::numeric_limits<size_t>::max());
186  BOOST_CHECK_EQUAL(cache.NumBytes(), 0);
187  BOOST_CHECK_EQUAL(cache.MaxNumBytes(), 5);
188 }
189 
190 BOOST_AUTO_TEST_CASE(TestMemoryConstrainedLRUCacheGet) {
192  10, [](const int key) { return std::make_shared<SizedElem>(key); });
193  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
194  for (int i = 0; i < 5; ++i) {
195  BOOST_CHECK_EQUAL(cache.Get(i)->NumBytes(), i);
196  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
197  BOOST_CHECK(cache.Exists(i));
198  }
199 
200  BOOST_CHECK_EQUAL(cache.Get(5)->NumBytes(), 5);
201  BOOST_CHECK_EQUAL(cache.NumElems(), 2);
202  BOOST_CHECK_EQUAL(cache.NumBytes(), 9);
203  BOOST_CHECK(!cache.Exists(0));
204  BOOST_CHECK(cache.Exists(5));
205 
206  BOOST_CHECK_EQUAL(cache.Get(5)->NumBytes(), 5);
207  BOOST_CHECK_EQUAL(cache.NumElems(), 2);
208  BOOST_CHECK_EQUAL(cache.NumBytes(), 9);
209  BOOST_CHECK(!cache.Exists(0));
210  BOOST_CHECK(cache.Exists(5));
211 
212  BOOST_CHECK_EQUAL(cache.Get(6)->NumBytes(), 6);
213  BOOST_CHECK_EQUAL(cache.NumElems(), 1);
214  BOOST_CHECK_EQUAL(cache.NumBytes(), 6);
215  BOOST_CHECK(!cache.Exists(0));
216  BOOST_CHECK(!cache.Exists(1));
217  BOOST_CHECK(cache.Exists(6));
218 
219  BOOST_CHECK_EQUAL(cache.Get(1)->NumBytes(), 1);
220  BOOST_CHECK_EQUAL(cache.NumElems(), 2);
221  BOOST_CHECK_EQUAL(cache.NumBytes(), 7);
222  BOOST_CHECK(!cache.Exists(0));
223  BOOST_CHECK(cache.Exists(1));
224  BOOST_CHECK(cache.Exists(6));
225 }
226 
227 BOOST_AUTO_TEST_CASE(TestMemoryConstrainedLRUCacheClear) {
229  10, [](const int key) { return std::make_shared<SizedElem>(key); });
230  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
231  for (int i = 0; i < 5; ++i) {
232  BOOST_CHECK_EQUAL(cache.Get(i)->NumBytes(), i);
233  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
234  BOOST_CHECK(cache.Exists(i));
235  }
236 
237  cache.Clear();
238  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
239  BOOST_CHECK_EQUAL(cache.NumBytes(), 0);
240 
241  BOOST_CHECK_EQUAL(cache.Get(1)->NumBytes(), 1);
242  BOOST_CHECK_EQUAL(cache.NumBytes(), 1);
243  BOOST_CHECK_EQUAL(cache.NumElems(), 1);
244  BOOST_CHECK(cache.Exists(1));
245 }
246 
247 BOOST_AUTO_TEST_CASE(TestMemoryConstrainedLRUCacheUpdateNumBytes) {
249  50, [](const int key) { return std::make_shared<SizedElem>(key); });
250  BOOST_CHECK_EQUAL(cache.NumElems(), 0);
251  for (int i = 0; i < 5; ++i) {
252  BOOST_CHECK_EQUAL(cache.Get(i)->NumBytes(), i);
253  BOOST_CHECK_EQUAL(cache.NumElems(), i + 1);
254  BOOST_CHECK(cache.Exists(i));
255  }
256 
257  BOOST_CHECK_EQUAL(cache.NumBytes(), 10);
258 
259  cache.Get(4)->num_bytes = 3;
260  BOOST_CHECK_EQUAL(cache.NumBytes(), 10);
261  cache.UpdateNumBytes(4);
262  BOOST_CHECK_EQUAL(cache.NumBytes(), 9);
263 
264  cache.Get(2)->num_bytes = 3;
265  BOOST_CHECK_EQUAL(cache.NumBytes(), 9);
266  cache.UpdateNumBytes(2);
267  BOOST_CHECK_EQUAL(cache.NumBytes(), 10);
268 
269  cache.Get(0)->num_bytes = 40;
270  BOOST_CHECK_EQUAL(cache.NumBytes(), 10);
271  cache.UpdateNumBytes(0);
272  BOOST_CHECK_EQUAL(cache.NumBytes(), 50);
273 
274  cache.Clear();
275  BOOST_CHECK_EQUAL(cache.NumBytes(), 0);
276  BOOST_CHECK_EQUAL(cache.Get(2)->NumBytes(), 2);
277  BOOST_CHECK_EQUAL(cache.NumBytes(), 2);
278 }
BOOST_AUTO_TEST_CASE(TestLRUCacheEmpty)
Definition: cache_test.cc:39
size_t NumBytes() const
Definition: cache_test.cc:177
size_t num_bytes
Definition: cache_test.cc:178
SizedElem(const size_t num_bytes_)
Definition: cache_test.cc:176