Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/tests/gtest/TestMruCache.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
8
#include "gtest/gtest.h"
9
10
#include "mozilla/MruCache.h"
11
#include "nsString.h"
12
13
using namespace mozilla;
14
15
// A few MruCache implementations to use during testing.
16
struct IntMap : public MruCache<int, int, IntMap>
17
{
18
0
  static HashNumber Hash(const KeyType& aKey) { return aKey - 1; }
19
0
  static bool Match(const KeyType& aKey, const ValueType& aVal) { return aKey == aVal; }
20
};
21
22
struct UintPtrMap : public MruCache<uintptr_t, int*, UintPtrMap>
23
{
24
0
  static HashNumber Hash(const KeyType& aKey) { return aKey - 1; }
25
0
  static bool Match(const KeyType& aKey, const ValueType& aVal) { return aKey == (KeyType)aVal; }
26
};
27
28
struct StringStruct
29
{
30
  nsCString mKey;
31
  nsCString mOther;
32
};
33
34
struct StringStructMap : public MruCache<nsCString, StringStruct, StringStructMap>
35
{
36
0
  static HashNumber Hash(const KeyType& aKey) { return *aKey.BeginReading() - 1; }
37
0
  static bool Match(const KeyType& aKey, const ValueType& aVal) { return aKey == aVal.mKey; }
38
};
39
40
// Helper for emulating convertable holders such as RefPtr.
41
template <typename T>
42
struct Convertable
43
{
44
  T mItem;
45
0
  operator T() const { return mItem; }
Unexecuted instantiation: Convertable<int*>::operator int*() const
Unexecuted instantiation: Convertable<int>::operator int() const
46
};
47
48
// Helper to create a StringStructMap key.
49
nsCString MakeStringKey(char aKey)
50
0
{
51
0
  nsCString key;
52
0
  key.Append(aKey);
53
0
  return key;
54
0
}
55
56
TEST(MruCache, TestNullChecker)
57
0
{
58
0
  using mozilla::detail::EmptyChecker;
59
0
60
0
  {
61
0
    int test = 0;
62
0
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
63
0
64
0
    test = 42;
65
0
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
66
0
  }
67
0
68
0
  {
69
0
    const char* test = "abc";
70
0
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
71
0
72
0
    test = nullptr;
73
0
    EXPECT_FALSE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
74
0
  }
75
0
76
0
  {
77
0
    int foo = 42;
78
0
    int* test = &foo;
79
0
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
80
0
81
0
    test = nullptr;
82
0
    EXPECT_FALSE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
83
0
  }
84
0
}
85
86
TEST(MruCache, TestEmptyCache)
87
0
{
88
0
  {
89
0
    // Test a basic empty cache.
90
0
    IntMap mru;
91
0
92
0
    // Make sure the default values are set.
93
0
    for (int i = 1; i < 32; i++) {
94
0
      auto p = mru.Lookup(i);
95
0
96
0
      // Shouldn't be found.
97
0
      EXPECT_FALSE(p);
98
0
    }
99
0
  }
100
0
101
0
  {
102
0
    // Test an empty cache with pointer values.
103
0
    UintPtrMap mru;
104
0
105
0
    // Make sure the default values are set.
106
0
    for (uintptr_t i = 1; i < 32; i++) {
107
0
      auto p = mru.Lookup(i);
108
0
109
0
      // Shouldn't be found.
110
0
      EXPECT_FALSE(p);
111
0
    }
112
0
  }
113
0
114
0
  {
115
0
    // Test an empty cache with more complex structure.
116
0
    StringStructMap mru;
117
0
118
0
    // Make sure the default values are set.
119
0
    for (char i = 1; i < 32; i++) {
120
0
      const nsCString key = MakeStringKey(i);
121
0
      auto p = mru.Lookup(key);
122
0
123
0
      // Shouldn't be found.
124
0
      EXPECT_FALSE(p);
125
0
    }
126
0
  }
127
0
}
128
129
TEST(MruCache, TestPut)
130
0
{
131
0
  IntMap mru;
132
0
133
0
  // Fill it up.
134
0
  for (int i = 1; i < 32; i++) {
135
0
    mru.Put(i, i);
136
0
  }
137
0
138
0
  // Now check each value.
139
0
  for (int i = 1; i < 32; i++) {
140
0
    auto p = mru.Lookup(i);
141
0
142
0
    // Should be found.
143
0
    EXPECT_TRUE(p);
144
0
    EXPECT_EQ(p.Data(), i);
145
0
  }
146
0
}
147
148
TEST(MruCache, TestPutConvertable)
149
0
{
150
0
  UintPtrMap mru;
151
0
152
0
  // Fill it up.
153
0
  for (uintptr_t i = 1; i < 32; i++) {
154
0
    Convertable<int*> val{(int*)i};
155
0
    mru.Put(i, val);
156
0
  }
157
0
158
0
  // Now check each value.
159
0
  for (uintptr_t i = 1; i < 32; i++) {
160
0
    auto p = mru.Lookup(i);
161
0
162
0
    // Should be found.
163
0
    EXPECT_TRUE(p);
164
0
    EXPECT_EQ(p.Data(), (int*)i);
165
0
  }
166
0
}
167
168
TEST(MruCache, TestOverwriting)
169
0
{
170
0
  // Test overwrting
171
0
  IntMap mru;
172
0
173
0
  // 1-31 should be overwritten by 32-63
174
0
  for (int i = 1; i < 63; i++) {
175
0
    mru.Put(i, i);
176
0
  }
177
0
178
0
  // Look them up.
179
0
  for (int i = 32; i < 63; i++) {
180
0
    auto p = mru.Lookup(i);
181
0
182
0
    // Should be found.
183
0
    EXPECT_TRUE(p);
184
0
    EXPECT_EQ(p.Data(), i);
185
0
  }
186
0
}
187
188
TEST(MruCache, TestRemove)
189
0
{
190
0
  {
191
0
    IntMap mru;
192
0
193
0
    // Fill it up.
194
0
    for (int i = 1; i < 32; i++) {
195
0
      mru.Put(i, i);
196
0
    }
197
0
198
0
    // Now remove each value.
199
0
    for (int i = 1; i < 32; i++) {
200
0
      // Should be present.
201
0
      auto p = mru.Lookup(i);
202
0
      EXPECT_TRUE(p);
203
0
204
0
      mru.Remove(i);
205
0
206
0
      // Should no longer match.
207
0
      p = mru.Lookup(i);
208
0
      EXPECT_FALSE(p);
209
0
    }
210
0
  }
211
0
212
0
  {
213
0
    UintPtrMap mru;
214
0
215
0
    // Fill it up.
216
0
    for (uintptr_t i = 1; i < 32; i++) {
217
0
      mru.Put(i, (int*)i);
218
0
    }
219
0
220
0
    // Now remove each value.
221
0
    for (uintptr_t i = 1; i < 32; i++) {
222
0
      // Should be present.
223
0
      auto p = mru.Lookup(i);
224
0
      EXPECT_TRUE(p);
225
0
226
0
      mru.Remove(i);
227
0
228
0
      // Should no longer match.
229
0
      p = mru.Lookup(i);
230
0
      EXPECT_FALSE(p);
231
0
    }
232
0
  }
233
0
234
0
  {
235
0
    StringStructMap mru;
236
0
237
0
    // Fill it up.
238
0
    for (char i = 1; i < 32; i++) {
239
0
      const nsCString key = MakeStringKey(i);
240
0
      mru.Put(key, StringStruct{key, NS_LITERAL_CSTRING("foo")});
241
0
    }
242
0
243
0
    // Now remove each value.
244
0
    for (char i = 1; i < 32; i++) {
245
0
      const nsCString key = MakeStringKey(i);
246
0
247
0
      // Should be present.
248
0
      auto p = mru.Lookup(key);
249
0
      EXPECT_TRUE(p);
250
0
251
0
      mru.Remove(key);
252
0
253
0
      // Should no longer match.
254
0
      p = mru.Lookup(key);
255
0
      EXPECT_FALSE(p);
256
0
    }
257
0
  }
258
0
}
259
260
TEST(MruCache, TestClear)
261
0
{
262
0
  IntMap mru;
263
0
264
0
  // Fill it up.
265
0
  for (int i = 1; i < 32; i++) {
266
0
    mru.Put(i, i);
267
0
  }
268
0
269
0
  // Empty it.
270
0
  mru.Clear();
271
0
272
0
  // Now check each value.
273
0
  for (int i = 1; i < 32; i++) {
274
0
    auto p = mru.Lookup(i);
275
0
276
0
    // Should not be found.
277
0
    EXPECT_FALSE(p);
278
0
  }
279
0
}
280
281
TEST(MruCache, TestLookupMissingAndSet)
282
0
{
283
0
  IntMap mru;
284
0
285
0
  // Value not found.
286
0
  auto p = mru.Lookup(1);
287
0
  EXPECT_FALSE(p);
288
0
289
0
  // Set it.
290
0
  p.Set(1);
291
0
  EXPECT_TRUE(p);
292
0
  EXPECT_EQ(p.Data(), 1);
293
0
294
0
  // Look it up again.
295
0
  p = mru.Lookup(1);
296
0
  EXPECT_TRUE(p);
297
0
  EXPECT_EQ(p.Data(), 1);
298
0
299
0
  // Test w/ a convertable value.
300
0
  p = mru.Lookup(2);
301
0
  EXPECT_FALSE(p);
302
0
303
0
  // Set it.
304
0
  Convertable<int> val{2};
305
0
  p.Set(val);
306
0
  EXPECT_TRUE(p);
307
0
  EXPECT_EQ(p.Data(), 2);
308
0
309
0
  // Look it up again.
310
0
  p = mru.Lookup(2);
311
0
  EXPECT_TRUE(p);
312
0
  EXPECT_EQ(p.Data(), 2);
313
0
}
314
315
TEST(MruCache, TestLookupAndOverwrite)
316
0
{
317
0
  IntMap mru;
318
0
319
0
  // Set 1.
320
0
  mru.Put(1, 1);
321
0
322
0
  // Lookup a key that maps the 1's entry.
323
0
  auto p = mru.Lookup(32);
324
0
  EXPECT_FALSE(p); // not a match
325
0
326
0
  // Now overwrite the entry.
327
0
  p.Set(32);
328
0
  EXPECT_TRUE(p);
329
0
  EXPECT_EQ(p.Data(), 32);
330
0
331
0
  // 1 should be gone now.
332
0
  p = mru.Lookup(1);
333
0
  EXPECT_FALSE(p);
334
0
335
0
  // 32 should be found.
336
0
  p = mru.Lookup(32);
337
0
  EXPECT_TRUE(p);
338
0
  EXPECT_EQ(p.Data(), 32);
339
0
}
340
341
TEST(MruCache, TestLookupAndRemove)
342
0
{
343
0
  IntMap mru;
344
0
345
0
  // Set 1.
346
0
  mru.Put(1, 1);
347
0
348
0
  auto p = mru.Lookup(1);
349
0
  EXPECT_TRUE(p);
350
0
  EXPECT_EQ(p.Data(), 1);
351
0
352
0
  // Now remove it.
353
0
  p.Remove();
354
0
  EXPECT_FALSE(p);
355
0
356
0
  p = mru.Lookup(1);
357
0
  EXPECT_FALSE(p);
358
0
}
359
360
TEST(MruCache, TestLookupNotMatchedAndRemove)
361
0
{
362
0
  IntMap mru;
363
0
364
0
  // Set 1.
365
0
  mru.Put(1, 1);
366
0
367
0
  // Lookup a key that matches 1's entry.
368
0
  auto p = mru.Lookup(32);
369
0
  EXPECT_FALSE(p);
370
0
371
0
  // Now attempt to remove it.
372
0
  p.Remove();
373
0
374
0
  // Make sure 1 is still there.
375
0
  p = mru.Lookup(1);
376
0
  EXPECT_TRUE(p);
377
0
  EXPECT_EQ(p.Data(), 1);
378
0
}
379
380
TEST(MruCache, TestLookupAndSetWithMove)
381
0
{
382
0
  StringStructMap mru;
383
0
384
0
  const nsCString key = MakeStringKey((char)1);
385
0
  StringStruct val{key, NS_LITERAL_CSTRING("foo")};
386
0
387
0
  auto p = mru.Lookup(key);
388
0
  EXPECT_FALSE(p);
389
0
  p.Set(std::move(val));
390
0
391
0
  EXPECT_TRUE(p.Data().mKey == key);
392
0
  EXPECT_TRUE(p.Data().mOther == NS_LITERAL_CSTRING("foo"));
393
0
}