1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define LOG_TAG "LRUBucketTest"
17 
18 #include "lru_bucket.h"
19 #include "gtest/gtest.h"
20 namespace OHOS::Test {
21 using namespace testing::ext;
22 template<typename _Key, typename _Tp> using LRUBucket = OHOS::LRUBucket<_Key, _Tp>;
23 
24 class LRUBucketTest : public testing::Test {
25 public:
26     struct TestValue {
27         std::string id;
28         std::string name;
29         std::string testCase;
30     };
31     static constexpr size_t TEST_CAPACITY = 10;
32 
SetUpTestCase(void)33     static void SetUpTestCase(void) {}
34 
TearDownTestCase(void)35     static void TearDownTestCase(void) {}
36 
37 protected:
SetUp()38     void SetUp()
39     {
40         bucket_.ResetCapacity(0);
41         bucket_.ResetCapacity(TEST_CAPACITY);
42         for (size_t i = 0; i < TEST_CAPACITY; ++i) {
43             std::string key = std::string("test_") + std::to_string(i);
44             TestValue value = {key, key, "case"};
45             bucket_.Set(key, value);
46         }
47     }
48 
TearDown()49     void TearDown() {}
50 
51     LRUBucket<std::string, TestValue> bucket_{TEST_CAPACITY};
52 };
53 
54 /**
55 * @tc.name: insert
56 * @tc.desc: Set the value to the lru bucket, whose capacity is more than one.
57 * @tc.type: FUNC
58 * @tc.require:
59 * @tc.author: Sven Wang
60 */
61 HWTEST_F(LRUBucketTest, insert, TestSize.Level0)
62 {
63     bucket_.Set("test_10", {"test_10", "test_10", "case"});
64     TestValue value;
65     ASSERT_TRUE(!bucket_.Get("test_0", value));
66     ASSERT_TRUE(bucket_.Get("test_6", value));
67     ASSERT_TRUE(bucket_.ResetCapacity(1));
68     ASSERT_TRUE(bucket_.Capacity() == 1);
69     ASSERT_TRUE(bucket_.Size() <= 1);
70     ASSERT_TRUE(bucket_.Get("test_6", value));
71 }
72 
73 /**
74 * @tc.name: cap_one_insert
75 * @tc.desc: Set the value to the lru bucket, whose capacity is one.
76 * @tc.type: FUNC
77 * @tc.require:
78 * @tc.author: Sven Wang
79 */
80 HWTEST_F(LRUBucketTest, cap_one_insert, TestSize.Level0)
81 {
82     bucket_.ResetCapacity(1);
83     for (size_t i = 0; i <= TEST_CAPACITY; ++i) {
84         std::string key = std::string("test_") + std::to_string(i);
85         TestValue value = {key, key, "find"};
86         bucket_.Set(key, value);
87     }
88     TestValue value;
89     ASSERT_TRUE(!bucket_.Get("test_0", value));
90     ASSERT_TRUE(bucket_.Get("test_10", value));
91 }
92 
93 /**
94 * @tc.name: cap_zero_insert
95 * @tc.desc: Set the value to the lru bucket, whose capacity is zero.
96 * @tc.type: FUNC
97 * @tc.require:
98 * @tc.author: Sven Wang
99 */
100 HWTEST_F(LRUBucketTest, cap_zero_insert, TestSize.Level0)
101 {
102     bucket_.ResetCapacity(0);
103     for (size_t i = 0; i <= TEST_CAPACITY; ++i) {
104         std::string key = std::string("test_") + std::to_string(i);
105         TestValue value = {key, key, "find"};
106         bucket_.Set(key, value);
107     }
108     TestValue value;
109     ASSERT_TRUE(!bucket_.Get("test_10", value));
110 }
111 
112 /**
113 * @tc.name: find_head
114 * @tc.desc: find the head element from the lru bucket.
115 * @tc.type: FUNC
116 * @tc.require:
117 * @tc.author: Sven Wang
118 */
119 HWTEST_F(LRUBucketTest, find_head, TestSize.Level0)
120 {
121     TestValue value;
122     ASSERT_TRUE(bucket_.ResetCapacity(1));
123     ASSERT_TRUE(bucket_.Capacity() == 1);
124     ASSERT_TRUE(bucket_.Size() <= 1);
125     ASSERT_TRUE(bucket_.Get("test_9", value));
126 }
127 
128 /**
129 * @tc.name: find_tail
130 * @tc.desc: find the tail element, then the element will move to head.
131 * @tc.type: FUNC
132 * @tc.require:
133 * @tc.author: Sven Wang
134 */
135 HWTEST_F(LRUBucketTest, find_tail, TestSize.Level0)
136 {
137     TestValue value;
138     ASSERT_TRUE(bucket_.Get("test_0", value));
139     ASSERT_TRUE(bucket_.ResetCapacity(1));
140     ASSERT_TRUE(bucket_.Capacity() == 1);
141     ASSERT_TRUE(bucket_.Size() <= 1);
142     ASSERT_TRUE(bucket_.Get("test_0", value));
143 }
144 
145 /**
146 * @tc.name: find_mid
147 * @tc.desc: find the mid element, then the element will move to head.
148 * @tc.type: FUNC
149 * @tc.require:
150 * @tc.author: Sven Wang
151 */
152 HWTEST_F(LRUBucketTest, find_mid, TestSize.Level0)
153 {
154     TestValue value;
155     ASSERT_TRUE(bucket_.Get("test_5", value));
156     ASSERT_TRUE(bucket_.ResetCapacity(1));
157     ASSERT_TRUE(bucket_.Capacity() == 1);
158     ASSERT_TRUE(bucket_.Size() <= 1);
159     ASSERT_TRUE(bucket_.Get("test_5", value));
160 }
161 
162 /**
163 * @tc.name: find_and_insert
164 * @tc.desc: find the tail element, then the element will move to head.
165 * @tc.type: FUNC
166 * @tc.require:
167 * @tc.author: Sven Wang
168 */
169 HWTEST_F(LRUBucketTest, find_and_insert, TestSize.Level0)
170 {
171     TestValue value;
172     if (!bucket_.Get("MyTest", value)) {
173         bucket_.Set("MyTest", {"MyTest", "MyTest", "case"});
174     }
175     ASSERT_TRUE(bucket_.Get("MyTest", value));
176 
177     if (!bucket_.Get("test_0", value)) {
178         bucket_.Set("test_0", {"test_0", "test_0", "case"});
179     }
180     ASSERT_TRUE(bucket_.Get("test_0", value));
181     ASSERT_TRUE(bucket_.Get("test_5", value));
182     ASSERT_TRUE(bucket_.Get("test_4", value));
183     ASSERT_TRUE(!bucket_.Get("test_1", value));
184     ASSERT_TRUE(bucket_.Get("test_2", value));
185 }
186 
187 /**
188 * @tc.name: del_head
189 * @tc.desc: delete the head element, then the next element will move to head.
190 * @tc.type: FUNC
191 * @tc.require:
192 * @tc.author: Sven Wang
193 */
194 HWTEST_F(LRUBucketTest, del_head, TestSize.Level0)
195 {
196     TestValue value;
197     ASSERT_TRUE(bucket_.Delete("test_9"));
198     ASSERT_TRUE(!bucket_.Get("test_9", value));
199     ASSERT_TRUE(bucket_.ResetCapacity(1));
200     ASSERT_TRUE(bucket_.Capacity() == 1);
201     ASSERT_TRUE(bucket_.Size() <= 1);
202     ASSERT_TRUE(bucket_.Get("test_8", value));
203 }
204 
205 /**
206 * @tc.name: del_head
207 * @tc.desc: delete the tail element, then the lru chain keep valid.
208 * @tc.type: FUNC
209 * @tc.require:
210 * @tc.author: Sven Wang
211 */
212 HWTEST_F(LRUBucketTest, del_tail, TestSize.Level0)
213 {
214     TestValue value;
215     ASSERT_TRUE(bucket_.Delete("test_0"));
216     ASSERT_TRUE(!bucket_.Get("test_0", value));
217     ASSERT_TRUE(bucket_.Get("test_4", value));
218     ASSERT_TRUE(bucket_.ResetCapacity(1));
219     ASSERT_TRUE(bucket_.Capacity() == 1);
220     ASSERT_TRUE(bucket_.Size() <= 1);
221     ASSERT_TRUE(bucket_.Get("test_4", value));
222 }
223 
224 /**
225 * @tc.name: del_mid
226 * @tc.desc: delete the mid element, then the lru chain keep valid.
227 * @tc.type: FUNC
228 * @tc.require:
229 * @tc.author: Sven Wang
230 */
231 HWTEST_F(LRUBucketTest, del_mid, TestSize.Level0)
232 {
233     TestValue value;
234     ASSERT_TRUE(bucket_.Delete("test_5"));
235     ASSERT_TRUE(!bucket_.Get("test_5", value));
236     ASSERT_TRUE(bucket_.Get("test_4", value));
237     ASSERT_TRUE(bucket_.Get("test_6", value));
238     ASSERT_TRUE(bucket_.ResetCapacity(2));
239     ASSERT_TRUE(bucket_.Capacity() == 2);
240     ASSERT_TRUE(bucket_.Size() <= 2);
241     ASSERT_TRUE(bucket_.Get("test_4", value));
242     ASSERT_TRUE(bucket_.Get("test_6", value));
243 }
244 
245 /**
246 * @tc.name: del_mid
247 * @tc.desc: the lru bucket has only one element, then delete it.
248 * @tc.type: FUNC
249 * @tc.require:
250 * @tc.author: Sven Wang
251 */
252 HWTEST_F(LRUBucketTest, cap_one_del, TestSize.Level0)
253 {
254     TestValue value;
255     bucket_.ResetCapacity(1);
256     ASSERT_TRUE(bucket_.Delete("test_9"));
257     ASSERT_TRUE(!bucket_.Get("test_9", value));
258 }
259 
260 /**
261 * @tc.name: del_mid
262 * @tc.desc: the lru bucket has no element.
263 * @tc.type: FUNC
264 * @tc.require:
265 * @tc.author: Sven Wang
266 */
267 HWTEST_F(LRUBucketTest, cap_zero_del, TestSize.Level0)
268 {
269     TestValue value;
270     bucket_.ResetCapacity(0);
271     ASSERT_TRUE(!bucket_.Delete("test_9"));
272     ASSERT_TRUE(!bucket_.Get("test_9", value));
273 }
274 
275 /**
276 * @tc.name: update_one
277 * @tc.desc: update the value and the lru chain won't change.
278 * @tc.type: FUNC
279 * @tc.require:
280 * @tc.author: Sven Wang
281 */
282 HWTEST_F(LRUBucketTest, update_one, TestSize.Level0)
283 {
284     TestValue value;
285     ASSERT_TRUE(bucket_.Update("test_4", {"test_4", "test_4", "update"}));
286     ASSERT_TRUE(bucket_.Get("test_4", value));
287     ASSERT_TRUE(value.testCase == "update");
288     ASSERT_TRUE(bucket_.Update("test_9", {"test_9", "test_9", "update"}));
289     ASSERT_TRUE(bucket_.ResetCapacity(1));
290     ASSERT_TRUE(bucket_.Capacity() == 1);
291     ASSERT_TRUE(bucket_.Size() <= 1);
292     ASSERT_TRUE(bucket_.Get("test_4", value));
293     ASSERT_TRUE(!bucket_.Get("test_9", value));
294 }
295 
296 /**
297 * @tc.name: update_several
298 * @tc.desc: update several values and the lru chain won't change.
299 * @tc.type: FUNC
300 * @tc.require:
301 * @tc.author: Sven Wang
302 */
303 HWTEST_F(LRUBucketTest, update_several, TestSize.Level0)
304 {
305     TestValue value;
306     std::map<std::string, TestValue> values = {{"test_2", {"test_2", "test_2", "update"}},
307                                                {"test_3", {"test_3", "test_3", "update"}},
308                                                {"test_6", {"test_6", "test_6", "update"}}};
309     ASSERT_TRUE(bucket_.Update(values));
310     ASSERT_TRUE(bucket_.ResetCapacity(3));
311     ASSERT_TRUE(bucket_.Capacity() == 3);
312     ASSERT_TRUE(bucket_.Size() <= 3);
313     ASSERT_TRUE(!bucket_.Get("test_2", value));
314     ASSERT_TRUE(!bucket_.Get("test_3", value));
315     ASSERT_TRUE(!bucket_.Get("test_6", value));
316     ASSERT_TRUE(bucket_.Get("test_9", value));
317     ASSERT_TRUE(bucket_.Get("test_8", value));
318     ASSERT_TRUE(bucket_.Get("test_7", value));
319 }
320 } // namespace OHOS::Test