blob: dbee13bb2ef47d31114d76dc84ca5019b49deab6 [file] [log] [blame]
Cody Northrop6cca6c22023-02-08 20:23:13 -07001/*
2 ** Copyright 2023, 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 "MultifileBlobCache.h"
18
19#include <android-base/test_utils.h>
20#include <fcntl.h>
21#include <gtest/gtest.h>
22#include <stdio.h>
23
24#include <memory>
25
26namespace android {
27
28template <typename T>
29using sp = std::shared_ptr<T>;
30
Cody Northrop5dbcfa72023-03-24 15:34:09 -060031constexpr size_t kMaxKeySize = 2 * 1024;
32constexpr size_t kMaxValueSize = 6 * 1024;
Cody Northrop6cca6c22023-02-08 20:23:13 -070033constexpr size_t kMaxTotalSize = 32 * 1024;
Cody Northrop6cca6c22023-02-08 20:23:13 -070034
35class MultifileBlobCacheTest : public ::testing::Test {
36protected:
37 virtual void SetUp() {
38 mTempFile.reset(new TemporaryFile());
Cody Northrop5dbcfa72023-03-24 15:34:09 -060039 mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize,
40 &mTempFile->path[0]));
Cody Northrop6cca6c22023-02-08 20:23:13 -070041 }
42
43 virtual void TearDown() { mMBC.reset(); }
44
45 std::unique_ptr<TemporaryFile> mTempFile;
46 std::unique_ptr<MultifileBlobCache> mMBC;
47};
48
49TEST_F(MultifileBlobCacheTest, CacheSingleValueSucceeds) {
50 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
51 mMBC->set("abcd", 4, "efgh", 4);
52 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
53 ASSERT_EQ('e', buf[0]);
54 ASSERT_EQ('f', buf[1]);
55 ASSERT_EQ('g', buf[2]);
56 ASSERT_EQ('h', buf[3]);
57}
58
59TEST_F(MultifileBlobCacheTest, CacheTwoValuesSucceeds) {
60 unsigned char buf[2] = {0xee, 0xee};
61 mMBC->set("ab", 2, "cd", 2);
62 mMBC->set("ef", 2, "gh", 2);
63 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
64 ASSERT_EQ('c', buf[0]);
65 ASSERT_EQ('d', buf[1]);
66 ASSERT_EQ(size_t(2), mMBC->get("ef", 2, buf, 2));
67 ASSERT_EQ('g', buf[0]);
68 ASSERT_EQ('h', buf[1]);
69}
70
71TEST_F(MultifileBlobCacheTest, GetSetTwiceSucceeds) {
72 unsigned char buf[2] = {0xee, 0xee};
73 mMBC->set("ab", 2, "cd", 2);
74 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
75 ASSERT_EQ('c', buf[0]);
76 ASSERT_EQ('d', buf[1]);
77 // Use the same key, but different value
78 mMBC->set("ab", 2, "ef", 2);
79 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
80 ASSERT_EQ('e', buf[0]);
81 ASSERT_EQ('f', buf[1]);
82}
83
84TEST_F(MultifileBlobCacheTest, GetOnlyWritesInsideBounds) {
85 unsigned char buf[6] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};
86 mMBC->set("abcd", 4, "efgh", 4);
87 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf + 1, 4));
88 ASSERT_EQ(0xee, buf[0]);
89 ASSERT_EQ('e', buf[1]);
90 ASSERT_EQ('f', buf[2]);
91 ASSERT_EQ('g', buf[3]);
92 ASSERT_EQ('h', buf[4]);
93 ASSERT_EQ(0xee, buf[5]);
94}
95
96TEST_F(MultifileBlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
97 unsigned char buf[3] = {0xee, 0xee, 0xee};
98 mMBC->set("abcd", 4, "efgh", 4);
99 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 3));
100 ASSERT_EQ(0xee, buf[0]);
101 ASSERT_EQ(0xee, buf[1]);
102 ASSERT_EQ(0xee, buf[2]);
103}
104
105TEST_F(MultifileBlobCacheTest, GetDoesntAccessNullBuffer) {
106 mMBC->set("abcd", 4, "efgh", 4);
107 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, nullptr, 0));
108}
109
110TEST_F(MultifileBlobCacheTest, MultipleSetsCacheLatestValue) {
111 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
112 mMBC->set("abcd", 4, "efgh", 4);
113 mMBC->set("abcd", 4, "ijkl", 4);
114 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
115 ASSERT_EQ('i', buf[0]);
116 ASSERT_EQ('j', buf[1]);
117 ASSERT_EQ('k', buf[2]);
118 ASSERT_EQ('l', buf[3]);
119}
120
121TEST_F(MultifileBlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
122 unsigned char buf[kMaxValueSize + 1] = {0xee, 0xee, 0xee, 0xee};
123 mMBC->set("abcd", 4, "efgh", 4);
124 mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
125 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
126 ASSERT_EQ('e', buf[0]);
127 ASSERT_EQ('f', buf[1]);
128 ASSERT_EQ('g', buf[2]);
129 ASSERT_EQ('h', buf[3]);
130}
131
132TEST_F(MultifileBlobCacheTest, DoesntCacheIfKeyIsTooBig) {
133 char key[kMaxKeySize + 1];
134 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
135 for (int i = 0; i < kMaxKeySize + 1; i++) {
136 key[i] = 'a';
137 }
138 mMBC->set(key, kMaxKeySize + 1, "bbbb", 4);
139 ASSERT_EQ(size_t(0), mMBC->get(key, kMaxKeySize + 1, buf, 4));
140 ASSERT_EQ(0xee, buf[0]);
141 ASSERT_EQ(0xee, buf[1]);
142 ASSERT_EQ(0xee, buf[2]);
143 ASSERT_EQ(0xee, buf[3]);
144}
145
146TEST_F(MultifileBlobCacheTest, DoesntCacheIfValueIsTooBig) {
147 char buf[kMaxValueSize + 1];
148 for (int i = 0; i < kMaxValueSize + 1; i++) {
149 buf[i] = 'b';
150 }
151 mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
152 for (int i = 0; i < kMaxValueSize + 1; i++) {
153 buf[i] = 0xee;
154 }
155 ASSERT_EQ(size_t(0), mMBC->get("abcd", 4, buf, kMaxValueSize + 1));
156 for (int i = 0; i < kMaxValueSize + 1; i++) {
157 SCOPED_TRACE(i);
158 ASSERT_EQ(0xee, buf[i]);
159 }
160}
161
162TEST_F(MultifileBlobCacheTest, CacheMaxKeySizeSucceeds) {
163 char key[kMaxKeySize];
164 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
165 for (int i = 0; i < kMaxKeySize; i++) {
166 key[i] = 'a';
167 }
168 mMBC->set(key, kMaxKeySize, "wxyz", 4);
169 ASSERT_EQ(size_t(4), mMBC->get(key, kMaxKeySize, 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(MultifileBlobCacheTest, CacheMaxValueSizeSucceeds) {
177 char buf[kMaxValueSize];
178 for (int i = 0; i < kMaxValueSize; i++) {
179 buf[i] = 'b';
180 }
181 mMBC->set("abcd", 4, buf, kMaxValueSize);
182 for (int i = 0; i < kMaxValueSize; i++) {
183 buf[i] = 0xee;
184 }
185 mMBC->get("abcd", 4, buf, kMaxValueSize);
186 for (int i = 0; i < kMaxValueSize; i++) {
187 SCOPED_TRACE(i);
188 ASSERT_EQ('b', buf[i]);
189 }
190}
191
Cody Northropbe163732023-03-22 10:14:26 -0600192TEST_F(MultifileBlobCacheTest, CacheMaxKeyAndValueSizeSucceeds) {
193 char key[kMaxKeySize];
194 for (int i = 0; i < kMaxKeySize; i++) {
195 key[i] = 'a';
196 }
197 char buf[kMaxValueSize];
198 for (int i = 0; i < kMaxValueSize; i++) {
199 buf[i] = 'b';
200 }
201 mMBC->set(key, kMaxKeySize, buf, kMaxValueSize);
202 for (int i = 0; i < kMaxValueSize; i++) {
203 buf[i] = 0xee;
204 }
205 mMBC->get(key, kMaxKeySize, buf, kMaxValueSize);
206 for (int i = 0; i < kMaxValueSize; i++) {
207 SCOPED_TRACE(i);
208 ASSERT_EQ('b', buf[i]);
209 }
210}
211
Cody Northrop6cca6c22023-02-08 20:23:13 -0700212TEST_F(MultifileBlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
213 unsigned char buf[1] = {0xee};
214 mMBC->set("x", 1, "y", 1);
215 ASSERT_EQ(size_t(1), mMBC->get("x", 1, buf, 1));
216 ASSERT_EQ('y', buf[0]);
217}
218
219} // namespace android