blob: 1a55a4fcdd06d86839cfc6049374df6b3c5c5d96 [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
31constexpr size_t kMaxTotalSize = 32 * 1024;
32constexpr size_t kMaxPreloadSize = 8 * 1024;
33
34constexpr size_t kMaxKeySize = kMaxPreloadSize / 4;
35constexpr size_t kMaxValueSize = kMaxPreloadSize / 2;
36
37class MultifileBlobCacheTest : public ::testing::Test {
38protected:
39 virtual void SetUp() {
40 mTempFile.reset(new TemporaryFile());
41 mMBC.reset(new MultifileBlobCache(kMaxTotalSize, kMaxPreloadSize, &mTempFile->path[0]));
42 }
43
44 virtual void TearDown() { mMBC.reset(); }
45
46 std::unique_ptr<TemporaryFile> mTempFile;
47 std::unique_ptr<MultifileBlobCache> mMBC;
48};
49
50TEST_F(MultifileBlobCacheTest, CacheSingleValueSucceeds) {
51 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
52 mMBC->set("abcd", 4, "efgh", 4);
53 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
54 ASSERT_EQ('e', buf[0]);
55 ASSERT_EQ('f', buf[1]);
56 ASSERT_EQ('g', buf[2]);
57 ASSERT_EQ('h', buf[3]);
58}
59
60TEST_F(MultifileBlobCacheTest, CacheTwoValuesSucceeds) {
61 unsigned char buf[2] = {0xee, 0xee};
62 mMBC->set("ab", 2, "cd", 2);
63 mMBC->set("ef", 2, "gh", 2);
64 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
65 ASSERT_EQ('c', buf[0]);
66 ASSERT_EQ('d', buf[1]);
67 ASSERT_EQ(size_t(2), mMBC->get("ef", 2, buf, 2));
68 ASSERT_EQ('g', buf[0]);
69 ASSERT_EQ('h', buf[1]);
70}
71
72TEST_F(MultifileBlobCacheTest, GetSetTwiceSucceeds) {
73 unsigned char buf[2] = {0xee, 0xee};
74 mMBC->set("ab", 2, "cd", 2);
75 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
76 ASSERT_EQ('c', buf[0]);
77 ASSERT_EQ('d', buf[1]);
78 // Use the same key, but different value
79 mMBC->set("ab", 2, "ef", 2);
80 ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
81 ASSERT_EQ('e', buf[0]);
82 ASSERT_EQ('f', buf[1]);
83}
84
85TEST_F(MultifileBlobCacheTest, GetOnlyWritesInsideBounds) {
86 unsigned char buf[6] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};
87 mMBC->set("abcd", 4, "efgh", 4);
88 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf + 1, 4));
89 ASSERT_EQ(0xee, buf[0]);
90 ASSERT_EQ('e', buf[1]);
91 ASSERT_EQ('f', buf[2]);
92 ASSERT_EQ('g', buf[3]);
93 ASSERT_EQ('h', buf[4]);
94 ASSERT_EQ(0xee, buf[5]);
95}
96
97TEST_F(MultifileBlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
98 unsigned char buf[3] = {0xee, 0xee, 0xee};
99 mMBC->set("abcd", 4, "efgh", 4);
100 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 3));
101 ASSERT_EQ(0xee, buf[0]);
102 ASSERT_EQ(0xee, buf[1]);
103 ASSERT_EQ(0xee, buf[2]);
104}
105
106TEST_F(MultifileBlobCacheTest, GetDoesntAccessNullBuffer) {
107 mMBC->set("abcd", 4, "efgh", 4);
108 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, nullptr, 0));
109}
110
111TEST_F(MultifileBlobCacheTest, MultipleSetsCacheLatestValue) {
112 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
113 mMBC->set("abcd", 4, "efgh", 4);
114 mMBC->set("abcd", 4, "ijkl", 4);
115 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
116 ASSERT_EQ('i', buf[0]);
117 ASSERT_EQ('j', buf[1]);
118 ASSERT_EQ('k', buf[2]);
119 ASSERT_EQ('l', buf[3]);
120}
121
122TEST_F(MultifileBlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
123 unsigned char buf[kMaxValueSize + 1] = {0xee, 0xee, 0xee, 0xee};
124 mMBC->set("abcd", 4, "efgh", 4);
125 mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
126 ASSERT_EQ(size_t(4), mMBC->get("abcd", 4, buf, 4));
127 ASSERT_EQ('e', buf[0]);
128 ASSERT_EQ('f', buf[1]);
129 ASSERT_EQ('g', buf[2]);
130 ASSERT_EQ('h', buf[3]);
131}
132
133TEST_F(MultifileBlobCacheTest, DoesntCacheIfKeyIsTooBig) {
134 char key[kMaxKeySize + 1];
135 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
136 for (int i = 0; i < kMaxKeySize + 1; i++) {
137 key[i] = 'a';
138 }
139 mMBC->set(key, kMaxKeySize + 1, "bbbb", 4);
140 ASSERT_EQ(size_t(0), mMBC->get(key, kMaxKeySize + 1, buf, 4));
141 ASSERT_EQ(0xee, buf[0]);
142 ASSERT_EQ(0xee, buf[1]);
143 ASSERT_EQ(0xee, buf[2]);
144 ASSERT_EQ(0xee, buf[3]);
145}
146
147TEST_F(MultifileBlobCacheTest, DoesntCacheIfValueIsTooBig) {
148 char buf[kMaxValueSize + 1];
149 for (int i = 0; i < kMaxValueSize + 1; i++) {
150 buf[i] = 'b';
151 }
152 mMBC->set("abcd", 4, buf, kMaxValueSize + 1);
153 for (int i = 0; i < kMaxValueSize + 1; i++) {
154 buf[i] = 0xee;
155 }
156 ASSERT_EQ(size_t(0), mMBC->get("abcd", 4, buf, kMaxValueSize + 1));
157 for (int i = 0; i < kMaxValueSize + 1; i++) {
158 SCOPED_TRACE(i);
159 ASSERT_EQ(0xee, buf[i]);
160 }
161}
162
163TEST_F(MultifileBlobCacheTest, CacheMaxKeySizeSucceeds) {
164 char key[kMaxKeySize];
165 unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
166 for (int i = 0; i < kMaxKeySize; i++) {
167 key[i] = 'a';
168 }
169 mMBC->set(key, kMaxKeySize, "wxyz", 4);
170 ASSERT_EQ(size_t(4), mMBC->get(key, kMaxKeySize, buf, 4));
171 ASSERT_EQ('w', buf[0]);
172 ASSERT_EQ('x', buf[1]);
173 ASSERT_EQ('y', buf[2]);
174 ASSERT_EQ('z', buf[3]);
175}
176
177TEST_F(MultifileBlobCacheTest, CacheMaxValueSizeSucceeds) {
178 char buf[kMaxValueSize];
179 for (int i = 0; i < kMaxValueSize; i++) {
180 buf[i] = 'b';
181 }
182 mMBC->set("abcd", 4, buf, kMaxValueSize);
183 for (int i = 0; i < kMaxValueSize; i++) {
184 buf[i] = 0xee;
185 }
186 mMBC->get("abcd", 4, buf, kMaxValueSize);
187 for (int i = 0; i < kMaxValueSize; i++) {
188 SCOPED_TRACE(i);
189 ASSERT_EQ('b', buf[i]);
190 }
191}
192
193TEST_F(MultifileBlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
194 unsigned char buf[1] = {0xee};
195 mMBC->set("x", 1, "y", 1);
196 ASSERT_EQ(size_t(1), mMBC->get("x", 1, buf, 1));
197 ASSERT_EQ('y', buf[0]);
198}
199
200} // namespace android