1 /*
2 * Copyright (c) 2024 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 <vector>
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19
20 #define protected public
21 #define private public
22
23 #include "core/image/image_file_cache.h"
24 #include "base/utils/system_properties.h"
25
26 #include "test/mock/base/mock_image_packer.h"
27 #include "test/mock/base/mock_image_source.h"
28 #include "test/mock/base/mock_pixel_map.h"
29
30 using namespace testing;
31 using namespace testing::ext;
32
33 namespace OHOS::Ace::NG {
34 const std::string ASTC_SUFFIX = ".astc";
35 const std::string CACHE_FILE_PATH = "/data/test/resource/imagecache/images";
36 const std::string SVG_FORMAT = "image/svg+xml";
37 class ImageFileCacheTestNg : public testing::Test {
38 public:
39 static void SetUpTestSuite();
40 static void TearDownTestSuite();
41 static void WaitForAsyncTasks();
42
43 void SetUp() override;
44 void TearDown() override;
45 };
46
SetUpTestSuite()47 void ImageFileCacheTestNg::SetUpTestSuite()
48 {
49 ImageFileCache::GetInstance().SetImageCacheFilePath(CACHE_FILE_PATH);
50 }
51
SetUp()52 void ImageFileCacheTestNg::SetUp()
53 {
54 SystemProperties::imageFileCacheConvertAstc_ = true;
55 ImageFileCache::GetInstance().fileNameToFileInfoPos_.clear();
56 ImageFileCache::GetInstance().cacheFileInfo_.clear();
57 ImageFileCache::GetInstance().cacheFileSize_ = 0;
58 }
59
TearDown()60 void ImageFileCacheTestNg::TearDown()
61 {
62 }
63
TearDownTestSuite()64 void ImageFileCacheTestNg::TearDownTestSuite()
65 {
66 MockImagePacker::mockImagePacker_ = nullptr;
67 MockImageSource::mockImageSource_ = nullptr;
68 }
69
70 // wait for load task to finish
WaitForAsyncTasks()71 void ImageFileCacheTestNg::WaitForAsyncTasks()
72 {
73 }
74
75 /**
76 * @tc.name: WriteCacheFileFunc001
77 * @tc.desc: Test WriteCacheFileFun with convert astc enabled.
78 * @tc.type: FUNC
79 */
80 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc001, TestSize.Level1)
81 {
82 RefPtr<MockImagePacker> mockImagePacker = AceType::MakeRefPtr<MockImagePacker>();
83 RefPtr<MockImageSource> mockImageSource = AceType::MakeRefPtr<MockImageSource>();
84 RefPtr<MockPixelMap> mockPixelMap = AceType::MakeRefPtr<MockPixelMap>();
85 MockImagePacker::mockImagePacker_ = mockImagePacker;
86 MockImageSource::mockImageSource_ = mockImageSource;
87 /**
88 * @tc.steps: step1. construct a data.
89 */
90 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
91 std::string url = "http:/testfilecache002/image";
92 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
93
94 /**
95 * @tc.steps: step2. call WriteCacheFile().
96 */
97 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
98 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
99 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
100 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
101 size_t accessCount = fileInfo.accessCount;
102 ASSERT_EQ(accessCount, 1);
103
104 /**
105 * @tc.steps: step3. call GetCacheFilePathInner(), each call will increase accessCount by one,
106 * when accessCount reaches convertAstcThreshold, ConvertToAstcAndWriteToFile() will be called.
107 * @tc.expected: after ConvertToAstcAndWriteToFile() is called, fileInfo get updated, fileName contains ASTC_SUFFIX.
108 */
109 std::string filePath;
110 auto convertAstcThreshold = SystemProperties::GetImageFileCacheConvertAstcThreshold();
111 while (accessCount < convertAstcThreshold) {
112 accessCount++;
113 bool convertToAstc = accessCount == convertAstcThreshold;
114 if (convertToAstc) {
115 EXPECT_CALL(*mockImageSource, GetFrameCount()).WillOnce(Return(1));
116 uint32_t errorCode = 0;
117 PixelMapConfig pixelMapConfig;
118 pixelMapConfig.imageQuality = AIImageQuality::NONE;
119 pixelMapConfig.isHdrDecoderNeed = false;
120 pixelMapConfig.photoDecodeFormat = PixelFormat::UNKNOWN;
121 EXPECT_CALL(*mockImageSource, CreatePixelMap(_, errorCode, pixelMapConfig)).WillOnce(Return(mockPixelMap));
122 EXPECT_CALL(*mockImagePacker, FinalizePacking(_))
123 .WillOnce(DoAll(SetArgReferee<0>(imageData.size()), Return(0)));
124 }
125 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
126 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
127 if (convertToAstc) {
128 sleep(1);
129 }
130 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
131 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
132 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
133 ASSERT_EQ(fileInfo.fileName, convertToAstc ? fileCacheKey + ASTC_SUFFIX : fileCacheKey);
134 ASSERT_EQ(fileInfo.accessCount, accessCount);
135 }
136 }
137
138 /**
139 * @tc.name: WriteCacheFileFunc002
140 * @tc.desc: Test WriteCacheFileFun with convert astc disabled.
141 * @tc.type: FUNC
142 */
143 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc002, TestSize.Level1)
144 {
145 SystemProperties::imageFileCacheConvertAstc_ = false;
146
147 /**
148 * @tc.steps: step1. construct a data.
149 */
150 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
151 std::string url = "http:/testfilecache002/image";
152 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
153
154 /**
155 * @tc.steps: step2. call WriteCacheFile().
156 */
157 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
158 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
159 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
160 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
161 size_t accessCount = fileInfo.accessCount;
162 ASSERT_EQ(accessCount, 1);
163
164 /**
165 * @tc.steps: step3. call GetCacheFilePathInner(), each call will increase accessCount by one,
166 * when accessCount reaches convertAstcThreshold, ConvertToAstcAndWriteToFile() will not be called.
167 * @tc.expected: fileInfo will not update, fileName does not contain ASTC_SUFFIX.
168 */
169 std::string filePath;
170 auto convertAstcThreshold = SystemProperties::GetImageFileCacheConvertAstcThreshold();
171 while (accessCount < convertAstcThreshold) {
172 accessCount++;
173 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
174 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
175 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
176 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
177 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
178 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
179 ASSERT_EQ(fileInfo.accessCount, accessCount);
180 }
181 }
182
183 /**
184 * @tc.name: WriteCacheFileFunc003
185 * @tc.desc: Test WriteCacheFileFun with suffix.
186 * @tc.type: FUNC
187 */
188 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc003, TestSize.Level1)
189 {
190 /**
191 * @tc.steps: step1. construct a data.
192 */
193 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
194 std::vector<uint8_t> imageDataWithSuffix = {1, 2, 3, 4, 5, 6, 7};
195 std::string url = "http:/testfilecache002/image";
196 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
197
198 /**
199 * @tc.steps: step2. call WriteCacheFile().
200 */
201 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
202 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
203 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
204 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
205 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
206 ASSERT_EQ(fileInfo.accessCount, 1);
207
208 /**
209 * @tc.steps: step3. call WriteCacheFile() with suffix.
210 * @tc.expected: fileInfo will update to imageDataWithSuffix.
211 */
212 std::string suffix = ".jpg";
213 ImageFileCache::GetInstance().WriteCacheFile(url, imageDataWithSuffix.data(), imageDataWithSuffix.size(), suffix);
214 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageDataWithSuffix.size()));
215 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
216 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
217 ASSERT_EQ(fileInfo.fileName, fileCacheKey + suffix);
218 ASSERT_EQ(fileInfo.accessCount, 1);
219 }
220
221 /**
222 * @tc.name: WriteCacheFileFunc004
223 * @tc.desc: Test WriteCacheFileFun with svg.
224 * @tc.type: FUNC
225 */
226 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc004, TestSize.Level1)
227 {
228 RefPtr<MockImageSource> mockImageSource = AceType::MakeRefPtr<MockImageSource>();
229 MockImageSource::mockImageSource_ = mockImageSource;
230 /**
231 * @tc.steps: step1. construct a data.
232 */
233 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
234 std::string url = "http:/testfilecache002/image";
235 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
236
237 /**
238 * @tc.steps: step2. call WriteCacheFile().
239 */
240 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
241 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
242 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
243 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
244 size_t accessCount = fileInfo.accessCount;
245 ASSERT_EQ(accessCount, 1);
246
247 /**
248 * @tc.steps: step3. call GetCacheFilePathInner(), each call will increase accessCount by one,
249 * when accessCount reaches convertAstcThreshold, ConvertToAstcAndWriteToFile() will be called.
250 * @tc.expected: because image is svg format, will not do the convert, fileInfo will not update,
251 * fileName does not contain ASTC_SUFFIX.
252 */
253 std::string filePath;
254 auto convertAstcThreshold = SystemProperties::GetImageFileCacheConvertAstcThreshold();
255 while (accessCount <= convertAstcThreshold) {
256 accessCount++;
257 bool convertToAstc = accessCount == convertAstcThreshold;
258 if (convertToAstc) {
259 EXPECT_CALL(*mockImageSource, GetFrameCount()).WillOnce(Return(1));
260 EXPECT_CALL(*mockImageSource, GetEncodedFormat()).WillOnce(Return(SVG_FORMAT));
261 }
262 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
263 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
264 if (convertToAstc) {
265 sleep(1);
266 }
267 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
268 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
269 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
270 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
271 ASSERT_EQ(fileInfo.accessCount, accessCount);
272 }
273 }
274 } // namespace OHOS::Ace::NG
275