1 /* 2 * Copyright (c) 2021-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 #include "core/image/test/unittest/image_cache_test.h" 17 18 #include "gtest/gtest.h" 19 #include "core/image/image_cache.h" 20 #include "core/components_ng/image_provider/adapter/skia_image_data.h" 21 22 using namespace testing; 23 using namespace testing::ext; 24 25 namespace OHOS::Ace { 26 const int32_t FILE_SIZE = 15; 27 const std::string CACHE_FILE_PATH = "/data/test/resource/imagecache/images"; 28 const std::string CACHE_IMAGE_FILE_1 = "/data/test/resource/imagecache/images/748621363886323660"; 29 const std::string CACHE_IMAGE_FILE_2 = "/data/test/resource/imagecache/images/8819493328252140263"; 30 const std::string CACHE_IMAGE_FILE_3 = "/data/test/resource/imagecache/images/1008157312073340586"; 31 const std::string CACHE_IMAGE_FILE_4 = "/data/test/resource/imagecache/images/13610839755484614436"; 32 const std::string CACHE_IMAGE_FILE_5 = "/data/test/resource/imagecache/images/5841967474238710136"; 33 const std::vector<std::string> CACHE_FILES = { CACHE_IMAGE_FILE_1, CACHE_IMAGE_FILE_2, CACHE_IMAGE_FILE_3, 34 CACHE_IMAGE_FILE_4, CACHE_IMAGE_FILE_5 }; 35 const size_t TEST_COUNT = CACHE_FILES.size(); 36 37 const std::string KEY_1 = "key1"; 38 const std::string KEY_2 = "key2"; 39 const std::string KEY_3 = "key3"; 40 const std::string KEY_4 = "key4"; 41 const std::string KEY_5 = "key5"; 42 const std::string KEY_6 = "key6"; 43 const std::vector<std::string> FILE_KEYS = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5 }; 44 45 46 class ImageCacheTest : public testing::Test { 47 public: SetUpTestCase()48 static void SetUpTestCase() {} TearDownTestCase()49 static void TearDownTestCase() {} SetUp()50 void SetUp() 51 { 52 imageCache->SetCapacity(80); 53 } TearDown()54 void TearDown() {} 55 56 RefPtr<ImageCache> imageCache = ImageCache::Create(); 57 }; 58 59 /** 60 * @tc.name: MemoryCache001 61 * @tc.desc: new image success insert into cache with LRU. 62 * @tc.type: FUNC 63 */ 64 HWTEST_F(ImageCacheTest, MemoryCache001, TestSize.Level1) 65 { 66 /** 67 * @tc.steps: step1. cache images one by one. 68 * @tc.expected: new item should at begin of cacheList_ and imagCache has right iters. 69 */ 70 for (size_t i = 0; i < CACHE_FILES.size(); i++) { 71 imageCache->CacheImage(FILE_KEYS[i], std::make_shared<CachedImage>(nullptr)); 72 std::string frontKey = (imageCache->cacheList_).front().cacheKey; 73 ASSERT_EQ(frontKey, FILE_KEYS[i]); 74 ASSERT_EQ(frontKey, imageCache->imageCache_[FILE_KEYS[i]]->cacheKey); 75 } 76 77 /** 78 * @tc.steps: step2. cache a image already in cache for example FILE_KEYS[3] e.t. "key4". 79 * @tc.expected: the cached item should at begin of cacheList_ and imagCache has right iters. 80 */ 81 imageCache->CacheImage(FILE_KEYS[3], std::make_shared<CachedImage>(nullptr)); 82 ASSERT_EQ(imageCache->cacheList_.front().cacheKey, FILE_KEYS[3]); 83 ASSERT_EQ(imageCache->imageCache_[FILE_KEYS[3]]->cacheKey, FILE_KEYS[3]); 84 } 85 86 /** 87 * @tc.name: MemoryCache002 88 * @tc.desc: get image success in cache with LRU. 89 * @tc.type: FUNC 90 */ 91 HWTEST_F(ImageCacheTest, MemoryCache002, TestSize.Level1) 92 { 93 /** 94 * @tc.steps: step1. cache images one by one. 95 */ 96 for (size_t i = 0; i < CACHE_FILES.size(); i++) { 97 imageCache->CacheImage(FILE_KEYS[i], std::make_shared<CachedImage>(nullptr)); 98 std::string frontKey = (imageCache->cacheList_).front().cacheKey; 99 } 100 /** 101 * @tc.steps: step2. find a image already in cache for example FILE_KEYS[2] e.t. "key3". 102 * @tc.expected: the cached iterator should not at end() of cacheList_ and imagCache. 103 * after GetImageCache(), the item should at begin() of cacheList_. 104 */ 105 auto iter = (imageCache->imageCache_).find(FILE_KEYS[2]); 106 ASSERT_NE(iter, imageCache->imageCache_.end()); 107 imageCache->GetCacheImage(FILE_KEYS[2]); 108 ASSERT_EQ(imageCache->cacheList_.front().cacheKey, FILE_KEYS[2]); 109 ASSERT_EQ(imageCache->imageCache_[FILE_KEYS[2]]->cacheKey, FILE_KEYS[2]); 110 111 /** 112 * @tc.steps: step3. find a image not in cache for example "key8". 113 * @tc.expected: return null. 114 */ 115 auto image = imageCache->GetCacheImage("key8"); 116 ASSERT_EQ(image, nullptr); 117 } 118 119 /** 120 * @tc.name: MemoryCache003 121 * @tc.desc: Set memory cache capacity success. 122 * @tc.type: FUNC 123 */ 124 HWTEST_F(ImageCacheTest, MemoryCache003, TestSize.Level1) 125 { 126 /** 127 * @tc.steps: step1. call set capacity. 128 * @tc.expected: capacity set to 1000. 129 */ 130 imageCache->SetCapacity(1000); 131 ASSERT_EQ(static_cast<int32_t>(imageCache->capacity_), 1000); 132 } 133 134 /** 135 * @tc.name: MemoryCache004 136 * @tc.desc: memory cache of image data. 137 * @tc.type: FUNC 138 */ 139 HWTEST_F(ImageCacheTest, MemoryCache004, TestSize.Level1) 140 { 141 /** 142 * @tc.steps: step1. set data limit to 10 bytes, cache some data.check result 143 * @tc.expected: result is right. 144 */ 145 imageCache->dataSizeLimit_ = 10; 146 147 // create 3 bytes data, cache it, current size is 3 148 const uint8_t data1[] = {'a', 'b', 'c' }; 149 sk_sp<SkData> skData1 = SkData::MakeWithCopy(data1, 3); 150 auto cachedData1 = AceType::MakeRefPtr<NG::SkiaImageData>(skData1); 151 imageCache->CacheImageData(KEY_1, cachedData1); 152 ASSERT_EQ(imageCache->curDataSize_, 3u); 153 154 // create 2 bytes data, cache it, current size is 5. {abc} {de} 155 const uint8_t data2[] = {'d', 'e' }; 156 sk_sp<SkData> skData2 = SkData::MakeWithCopy(data2, 2); 157 auto cachedData2 = AceType::MakeRefPtr<NG::SkiaImageData>(skData2); 158 imageCache->CacheImageData(KEY_2, cachedData2); 159 ASSERT_EQ(imageCache->curDataSize_, 5u); 160 161 // create 7 bytes data, cache it, current size is 5. new data not cached. 162 const uint8_t data3[] = { 'f', 'g', 'h', 'i', 'j', 'k', 'l' }; 163 sk_sp<SkData> skData3 = SkData::MakeWithCopy(data3, 7); 164 auto cachedData3 = AceType::MakeRefPtr<NG::SkiaImageData>(skData3); 165 imageCache->CacheImageData(KEY_3, cachedData3); 166 ASSERT_EQ(imageCache->curDataSize_, 5u); 167 auto data = imageCache->GetCacheImageData(KEY_3); 168 ASSERT_EQ(data, nullptr); 169 170 // create 5 bytes data, cache it, current size is 10 {abc} {de} {mnopq} 171 const uint8_t data4[] = { 'm', 'n', 'o', 'p', 'q' }; 172 sk_sp<SkData> skData4 = SkData::MakeWithCopy(data4, 5); 173 auto cachedData4 = AceType::MakeRefPtr<NG::SkiaImageData>(skData4); 174 imageCache->CacheImageData(KEY_4, cachedData4); 175 ASSERT_EQ(imageCache->curDataSize_, 10u); 176 177 // create 2 bytes data, cache it, current size is 9 {de}{mnopq}{rs} 178 const uint8_t data5[] = { 'r', 's' }; 179 sk_sp<SkData> skData5 = SkData::MakeWithCopy(data5, 2); 180 auto cachedData5 = AceType::MakeRefPtr<NG::SkiaImageData>(skData5); 181 imageCache->CacheImageData(KEY_5, cachedData5); 182 ASSERT_EQ(imageCache->curDataSize_, 9u); 183 184 // create 5 bytes, cache it, current size is 7 {rs}{tuvwx} 185 const uint8_t data6[] = { 't', 'u', 'v', 'w', 'x' }; 186 sk_sp<SkData> skData6 = SkData::MakeWithCopy(data6, 5); 187 auto cachedData6 = AceType::MakeRefPtr<NG::SkiaImageData>(skData6); 188 imageCache->CacheImageData(KEY_6, cachedData6); 189 ASSERT_EQ(imageCache->curDataSize_, 7u); 190 191 // cache data witch is already cached. {rs}{y} 192 const uint8_t data7[] = { 'y' }; 193 sk_sp<SkData> skData7 = SkData::MakeWithCopy(data7, 1); 194 auto cachedData7 = AceType::MakeRefPtr<NG::SkiaImageData>(skData7); 195 imageCache->CacheImageData(KEY_6, cachedData7); 196 ASSERT_EQ(imageCache->curDataSize_, 3u); 197 198 // cache data witch is already cached. {y}{fg} 199 const uint8_t data8[] = { 'f', 'g' }; 200 sk_sp<SkData> skData8 = SkData::MakeWithCopy(data8, 2); 201 auto cachedData8 = AceType::MakeRefPtr<NG::SkiaImageData>(skData8); 202 imageCache->CacheImageData(KEY_5, cachedData8); 203 ASSERT_EQ(imageCache->curDataSize_, 3u); 204 auto dataFront = imageCache->dataCacheList_.front().imageDataPtr->GetData(); 205 for (int i = 0; i < 2; ++i) { 206 ASSERT_EQ(dataFront[i], data8[i]); 207 } 208 auto dataKey5 = imageCache->GetCacheImageData(KEY_5); 209 auto dataRaw5 = dataKey5->GetData(); 210 ASSERT_EQ(dataFront, dataRaw5); 211 212 // Get key6 213 auto dataKey6 = imageCache->GetCacheImageData(KEY_6); 214 auto dataRaw6 = dataKey6->GetData(); 215 ASSERT_EQ(dataRaw6[0], 'y'); 216 dataFront = imageCache->dataCacheList_.front().imageDataPtr->GetData(); 217 ASSERT_EQ(dataFront, dataRaw6); 218 } 219 220 /** 221 * @tc.name: FileCache001 222 * @tc.desc: init cacheFilePath and cacheFileInfo success. 223 * @tc.type: FUNC 224 */ 225 HWTEST_F(ImageCacheTest, FileCache001, TestSize.Level1) 226 { 227 /** 228 * @tc.steps: step1.call SetImageCacheFilePath(). 229 * @tc.expected: cache file size init right and cache file Info init right. 230 */ 231 ImageCache::SetImageCacheFilePath(CACHE_FILE_PATH); 232 ASSERT_EQ(ImageCache::cacheFilePath_, CACHE_FILE_PATH); 233 234 /** 235 * @tc.steps: step2. call SetCacheFileInfo(). 236 * @tc.expected: file info init right. 237 */ 238 ImageCache::SetCacheFileInfo(); 239 ASSERT_EQ(ImageCache::cacheFileSize_, FILE_SIZE); 240 ASSERT_EQ(static_cast<int32_t>(ImageCache::cacheFileInfo_.size()), 5); 241 size_t i = 0; 242 auto iter = ImageCache::cacheFileInfo_.begin(); 243 while (i < TEST_COUNT - 1) { 244 ASSERT_LE(iter->accessTime, (++iter)->accessTime); 245 i++; 246 } 247 } 248 249 /** 250 * @tc.name: FileCache002 251 * @tc.desc: write data into cacheFilePath success. 252 * @tc.type: FUNC 253 */ 254 HWTEST_F(ImageCacheTest, FileCache002, TestSize.Level1) 255 { 256 /** 257 * @tc.steps: step1.construct a data. 258 */ 259 std::vector<uint8_t> imageData = { 1, 2, 3, 4, 5, 6 }; 260 std::string url = "http:/testfilecache002/image"; 261 262 /** 263 * @tc.steps: step2. call WriteCacheFile(). 264 * @tc.expected: file write into filePath and file info update right. 265 */ 266 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size()); 267 ASSERT_EQ(ImageCache::cacheFileSize_, static_cast<int32_t>(FILE_SIZE + imageData.size())); 268 ASSERT_EQ(ImageCache::cacheFileInfo_.size(), TEST_COUNT + 1); 269 auto iter = ImageCache::cacheFileInfo_.rbegin(); 270 271 ASSERT_EQ(iter->filePath, ImageFileCache::GetInstance().GetImageCacheFilePath(url)); 272 } 273 274 /** 275 * @tc.name: FileCache003 276 * @tc.desc: Get data from cacheFilePath success with right url. but null with wrong url. 277 * @tc.type: FUNC 278 */ 279 HWTEST_F(ImageCacheTest, FileCache003, TestSize.Level1) 280 { 281 /** 282 * @tc.steps: step1.set cacheFileLimit_ to 0. 283 */ 284 std::string wrongFilePath = "/data/wrong_data"; 285 /** 286 * @tc.steps: step2. call GetFromCacheFile(). 287 * @tc.expected:data != nullptr. 288 */ 289 auto data = ImageCache::GetFromCacheFile(CACHE_IMAGE_FILE_2); 290 ASSERT_TRUE(data); 291 auto nullData = ImageCache::GetFromCacheFile(wrongFilePath); 292 ASSERT_TRUE(!nullData); 293 } 294 295 /** 296 * @tc.name: FileCache004 297 * @tc.desc: clear files from cacheFilePath success while write file exceed limit. 298 * @tc.type: FUNC 299 */ 300 HWTEST_F(ImageCacheTest, FileCache004, TestSize.Level1) 301 { 302 /** 303 * @tc.steps: step1.set cacheFileLimit_ to 0. 304 */ 305 ImageCache::SetCacheFileLimit(0); 306 ASSERT_EQ(static_cast<int32_t>(ImageCache::cacheFileLimit_), 0); 307 308 /** 309 * @tc.steps: step2. call WriteCacheFile(). 310 * @tc.expected: file write into filePath and file info update right. 311 */ 312 std::vector<uint8_t> imageData = { 1, 2, 3 }; 313 std::string url = "http:/testfilecache003/image"; 314 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size()); 315 float ratio = ImageCache::clearCacheFileRatio_; 316 ASSERT_EQ(ImageCache::cacheFileInfo_.size(), static_cast<size_t>((TEST_COUNT + 2) * ratio + 1)); 317 ASSERT_LE(ImageCache::cacheFileSize_, FILE_SIZE); 318 } 319 320 } // namespace OHOS::Ace