1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // BlobCache_unittest.h: Unit tests for the blob cache.
7
8 #include <gtest/gtest.h>
9
10 #include "libANGLE/BlobCache.h"
11
12 namespace egl
13 {
14
15 // Note: this is fairly similar to SizedMRUCache_unittest, and makes sure the
16 // BlobCache usage of SizedMRUCache is not broken.
17
18 using BlobPut = angle::MemoryBuffer;
19 using Blob = BlobCache::Value;
20 using Key = BlobCache::Key;
21
22 template <typename T>
MakeSequence(T & seq,uint8_t start)23 void MakeSequence(T &seq, uint8_t start)
24 {
25 for (uint8_t i = 0; i < seq.size(); ++i)
26 {
27 seq[i] = i + start;
28 }
29 }
30
MakeBlob(size_t size,uint8_t start=0)31 BlobPut MakeBlob(size_t size, uint8_t start = 0)
32 {
33 BlobPut blob;
34 EXPECT_TRUE(blob.resize(size));
35 MakeSequence(blob, start);
36 return blob;
37 }
38
MakeKey(uint8_t start=0)39 Key MakeKey(uint8_t start = 0)
40 {
41 Key key;
42 MakeSequence(key, start);
43 return key;
44 }
45
46 // Test a cache with a value that takes up maximum size.
TEST(BlobCacheTest,MaxSizedValue)47 TEST(BlobCacheTest, MaxSizedValue)
48 {
49 constexpr size_t kSize = 32;
50 BlobCache blobCache(kSize);
51
52 blobCache.populate(MakeKey(0), MakeBlob(kSize));
53 EXPECT_EQ(32u, blobCache.size());
54 EXPECT_FALSE(blobCache.empty());
55
56 blobCache.populate(MakeKey(1), MakeBlob(kSize));
57 EXPECT_EQ(32u, blobCache.size());
58 EXPECT_FALSE(blobCache.empty());
59
60 Blob blob;
61 size_t blobSize;
62 EXPECT_FALSE(blobCache.get(nullptr, MakeKey(0), &blob, &blobSize));
63
64 blobCache.clear();
65 EXPECT_TRUE(blobCache.empty());
66 }
67
68 // Test a cache with many small values, that it can handle unlimited inserts.
TEST(BlobCacheTest,ManySmallValues)69 TEST(BlobCacheTest, ManySmallValues)
70 {
71 constexpr size_t kSize = 32;
72 BlobCache blobCache(kSize);
73
74 for (size_t value = 0; value < kSize; ++value)
75 {
76 blobCache.populate(MakeKey(value), MakeBlob(1, value));
77
78 Blob qvalue;
79 size_t blobSize;
80 EXPECT_TRUE(blobCache.get(nullptr, MakeKey(value), &qvalue, &blobSize));
81 if (qvalue.size() > 0)
82 {
83 EXPECT_EQ(value, qvalue[0]);
84 }
85 }
86
87 EXPECT_EQ(32u, blobCache.size());
88 EXPECT_FALSE(blobCache.empty());
89
90 // Putting one element evicts the first element.
91 blobCache.populate(MakeKey(kSize), MakeBlob(1, kSize));
92
93 Blob qvalue;
94 size_t blobSize;
95 EXPECT_FALSE(blobCache.get(nullptr, MakeKey(0), &qvalue, &blobSize));
96
97 // Putting one large element cleans out the whole stack.
98 blobCache.populate(MakeKey(kSize + 1), MakeBlob(kSize, kSize + 1));
99 EXPECT_EQ(32u, blobCache.size());
100 EXPECT_FALSE(blobCache.empty());
101
102 for (size_t value = 0; value <= kSize; ++value)
103 {
104 EXPECT_FALSE(blobCache.get(nullptr, MakeKey(value), &qvalue, &blobSize));
105 }
106 EXPECT_TRUE(blobCache.get(nullptr, MakeKey(kSize + 1), &qvalue, &blobSize));
107 if (qvalue.size() > 0)
108 {
109 EXPECT_EQ(kSize + 1, qvalue[0]);
110 }
111
112 // Put a bunch of items in the cache sequentially.
113 for (size_t value = 0; value < kSize * 10; ++value)
114 {
115 blobCache.populate(MakeKey(value), MakeBlob(1, value));
116 }
117
118 EXPECT_EQ(32u, blobCache.size());
119 }
120
121 // Tests putting an oversize element.
TEST(BlobCacheTest,OversizeValue)122 TEST(BlobCacheTest, OversizeValue)
123 {
124 constexpr size_t kSize = 32;
125 BlobCache blobCache(kSize);
126
127 blobCache.populate(MakeKey(5), MakeBlob(100));
128
129 Blob qvalue;
130 size_t blobSize;
131 EXPECT_FALSE(blobCache.get(nullptr, MakeKey(5), &qvalue, &blobSize));
132 }
133
134 } // namespace egl
135