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