blob: 653ea5e91cde1ee261db2a5ee4540a441f655dca [file] [log] [blame]
Jamie Gennis1a209932011-04-28 16:19:45 -07001/*
2 ** Copyright 2011, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <utils/BlobCache.h>
20
21namespace android {
22
23class BlobCacheTest : public ::testing::Test {
24protected:
25 enum {
26 MAX_KEY_SIZE = 6,
27 MAX_VALUE_SIZE = 8,
28 MAX_TOTAL_SIZE = 13,
29 };
30
31 virtual void SetUp() {
32 mBC = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
33 }
34
35 virtual void TearDown() {
36 mBC.clear();
37 }
38
39 sp<BlobCache> mBC;
40};
41
42TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
43 char buf[4] = { 0xee, 0xee, 0xee, 0xee };
44 mBC->set("abcd", 4, "efgh", 4);
45 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
46 ASSERT_EQ('e', buf[0]);
47 ASSERT_EQ('f', buf[1]);
48 ASSERT_EQ('g', buf[2]);
49 ASSERT_EQ('h', buf[3]);
50}
51
52TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
53 char buf[2] = { 0xee, 0xee };
54 mBC->set("ab", 2, "cd", 2);
55 mBC->set("ef", 2, "gh", 2);
56 ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
57 ASSERT_EQ('c', buf[0]);
58 ASSERT_EQ('d', buf[1]);
59 ASSERT_EQ(size_t(2), mBC->get("ef", 2, buf, 2));
60 ASSERT_EQ('g', buf[0]);
61 ASSERT_EQ('h', buf[1]);
62}
63
64TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
65 char buf[6] = { 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };
66 mBC->set("abcd", 4, "efgh", 4);
67 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf+1, 4));
68 ASSERT_EQ(0xee, buf[0]);
69 ASSERT_EQ('e', buf[1]);
70 ASSERT_EQ('f', buf[2]);
71 ASSERT_EQ('g', buf[3]);
72 ASSERT_EQ('h', buf[4]);
73 ASSERT_EQ(0xee, buf[5]);
74}
75
76TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
77 char buf[3] = { 0xee, 0xee, 0xee };
78 mBC->set("abcd", 4, "efgh", 4);
79 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
80 ASSERT_EQ(0xee, buf[0]);
81 ASSERT_EQ(0xee, buf[1]);
82 ASSERT_EQ(0xee, buf[2]);
83}
84
85TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
86 mBC->set("abcd", 4, "efgh", 4);
87 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0));
88}
89
90TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
91 char buf[4] = { 0xee, 0xee, 0xee, 0xee };
92 mBC->set("abcd", 4, "efgh", 4);
93 mBC->set("abcd", 4, "ijkl", 4);
94 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
95 ASSERT_EQ('i', buf[0]);
96 ASSERT_EQ('j', buf[1]);
97 ASSERT_EQ('k', buf[2]);
98 ASSERT_EQ('l', buf[3]);
99}
100
101TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
102 char buf[MAX_VALUE_SIZE+1] = { 0xee, 0xee, 0xee, 0xee };
103 mBC->set("abcd", 4, "efgh", 4);
104 mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
105 ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
106 ASSERT_EQ('e', buf[0]);
107 ASSERT_EQ('f', buf[1]);
108 ASSERT_EQ('g', buf[2]);
109 ASSERT_EQ('h', buf[3]);
110}
111
112TEST_F(BlobCacheTest, DoesntCacheIfKeyIsTooBig) {
113 char key[MAX_KEY_SIZE+1];
114 char buf[4] = { 0xee, 0xee, 0xee, 0xee };
115 for (int i = 0; i < MAX_KEY_SIZE+1; i++) {
116 key[i] = 'a';
117 }
118 mBC->set(key, MAX_KEY_SIZE+1, "bbbb", 4);
119 ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE+1, buf, 4));
120 ASSERT_EQ(0xee, buf[0]);
121 ASSERT_EQ(0xee, buf[1]);
122 ASSERT_EQ(0xee, buf[2]);
123 ASSERT_EQ(0xee, buf[3]);
124}
125
126TEST_F(BlobCacheTest, DoesntCacheIfValueIsTooBig) {
127 char buf[MAX_VALUE_SIZE+1];
128 for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
129 buf[i] = 'b';
130 }
131 mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
132 for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
133 buf[i] = 0xee;
134 }
135 ASSERT_EQ(size_t(0), mBC->get("abcd", 4, buf, MAX_VALUE_SIZE+1));
136 for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
137 SCOPED_TRACE(i);
138 ASSERT_EQ(0xee, buf[i]);
139 }
140}
141
142TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) {
143 // Check a testing assumptions
144 ASSERT_TRUE(MAX_TOTAL_SIZE < MAX_KEY_SIZE + MAX_VALUE_SIZE);
145 ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
146
147 enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE + 1 };
148
149 char key[MAX_KEY_SIZE];
150 char buf[bufSize];
151 for (int i = 0; i < MAX_KEY_SIZE; i++) {
152 key[i] = 'a';
153 }
154 for (int i = 0; i < bufSize; i++) {
155 buf[i] = 'b';
156 }
157
158 mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
159 ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
160}
161
162TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) {
163 char key[MAX_KEY_SIZE];
164 char buf[4] = { 0xee, 0xee, 0xee, 0xee };
165 for (int i = 0; i < MAX_KEY_SIZE; i++) {
166 key[i] = 'a';
167 }
168 mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
169 ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
170 ASSERT_EQ('w', buf[0]);
171 ASSERT_EQ('x', buf[1]);
172 ASSERT_EQ('y', buf[2]);
173 ASSERT_EQ('z', buf[3]);
174}
175
176TEST_F(BlobCacheTest, CacheMaxValueSizeSucceeds) {
177 char buf[MAX_VALUE_SIZE];
178 for (int i = 0; i < MAX_VALUE_SIZE; i++) {
179 buf[i] = 'b';
180 }
181 mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
182 for (int i = 0; i < MAX_VALUE_SIZE; i++) {
183 buf[i] = 0xee;
184 }
185 ASSERT_EQ(size_t(MAX_VALUE_SIZE), mBC->get("abcd", 4, buf,
186 MAX_VALUE_SIZE));
187 for (int i = 0; i < MAX_VALUE_SIZE; i++) {
188 SCOPED_TRACE(i);
189 ASSERT_EQ('b', buf[i]);
190 }
191}
192
193TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) {
194 // Check a testing assumption
195 ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
196
197 enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
198
199 char key[MAX_KEY_SIZE];
200 char buf[bufSize];
201 for (int i = 0; i < MAX_KEY_SIZE; i++) {
202 key[i] = 'a';
203 }
204 for (int i = 0; i < bufSize; i++) {
205 buf[i] = 'b';
206 }
207
208 mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
209 ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
210}
211
212TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
213 char buf[1] = { 0xee };
214 mBC->set("x", 1, "y", 1);
215 ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
216 ASSERT_EQ('y', buf[0]);
217}
218
219TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) {
220 for (int i = 0; i < 256; i++) {
221 uint8_t k = i;
222 mBC->set(&k, 1, "x", 1);
223 }
224 int numCached = 0;
225 for (int i = 0; i < 256; i++) {
226 uint8_t k = i;
227 if (mBC->get(&k, 1, NULL, 0) == 1) {
228 numCached++;
229 }
230 }
231 ASSERT_GE(MAX_TOTAL_SIZE / 2, numCached);
232}
233
234TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) {
235 // Fill up the entire cache with 1 char key/value pairs.
236 const int maxEntries = MAX_TOTAL_SIZE / 2;
237 for (int i = 0; i < maxEntries; i++) {
238 uint8_t k = i;
239 mBC->set(&k, 1, "x", 1);
240 }
241 // Insert one more entry, causing a cache overflow.
242 {
243 uint8_t k = maxEntries;
244 mBC->set(&k, 1, "x", 1);
245 }
246 // Count the number of entries in the cache.
247 int numCached = 0;
248 for (int i = 0; i < maxEntries+1; i++) {
249 uint8_t k = i;
250 if (mBC->get(&k, 1, NULL, 0) == 1) {
251 numCached++;
252 }
253 }
254 ASSERT_EQ(maxEntries/2 + 1, numCached);
255}
256
257} // namespace android