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 EXPECT_CALL(*mockImageSource, CreatePixelMap(_, AIImageQuality::NONE, false))
117 .WillOnce(Return(mockPixelMap));
118 EXPECT_CALL(*mockImagePacker, FinalizePacking(_))
119 .WillOnce(DoAll(SetArgReferee<0>(imageData.size()), Return(0)));
120 }
121 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
122 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
123 if (convertToAstc) {
124 sleep(1);
125 }
126 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
127 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
128 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
129 ASSERT_EQ(fileInfo.fileName, convertToAstc ? fileCacheKey + ASTC_SUFFIX : fileCacheKey);
130 ASSERT_EQ(fileInfo.accessCount, accessCount);
131 }
132 }
133
134 /**
135 * @tc.name: WriteCacheFileFunc002
136 * @tc.desc: Test WriteCacheFileFun with convert astc disabled.
137 * @tc.type: FUNC
138 */
139 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc002, TestSize.Level1)
140 {
141 SystemProperties::imageFileCacheConvertAstc_ = false;
142
143 /**
144 * @tc.steps: step1. construct a data.
145 */
146 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
147 std::string url = "http:/testfilecache002/image";
148 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
149
150 /**
151 * @tc.steps: step2. call WriteCacheFile().
152 */
153 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
154 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
155 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
156 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
157 size_t accessCount = fileInfo.accessCount;
158 ASSERT_EQ(accessCount, 1);
159
160 /**
161 * @tc.steps: step3. call GetCacheFilePathInner(), each call will increase accessCount by one,
162 * when accessCount reaches convertAstcThreshold, ConvertToAstcAndWriteToFile() will not be called.
163 * @tc.expected: fileInfo will not update, fileName does not contain ASTC_SUFFIX.
164 */
165 std::string filePath;
166 auto convertAstcThreshold = SystemProperties::GetImageFileCacheConvertAstcThreshold();
167 while (accessCount < convertAstcThreshold) {
168 accessCount++;
169 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
170 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
171 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
172 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
173 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
174 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
175 ASSERT_EQ(fileInfo.accessCount, accessCount);
176 }
177 }
178
179 /**
180 * @tc.name: WriteCacheFileFunc003
181 * @tc.desc: Test WriteCacheFileFun with suffix.
182 * @tc.type: FUNC
183 */
184 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc003, TestSize.Level1)
185 {
186 /**
187 * @tc.steps: step1. construct a data.
188 */
189 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
190 std::vector<uint8_t> imageDataWithSuffix = {1, 2, 3, 4, 5, 6, 7};
191 std::string url = "http:/testfilecache002/image";
192 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
193
194 /**
195 * @tc.steps: step2. call WriteCacheFile().
196 */
197 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
198 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
199 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
200 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
201 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
202 ASSERT_EQ(fileInfo.accessCount, 1);
203
204 /**
205 * @tc.steps: step3. call WriteCacheFile() with suffix.
206 * @tc.expected: fileInfo will update to imageDataWithSuffix.
207 */
208 std::string suffix = ".jpg";
209 ImageFileCache::GetInstance().WriteCacheFile(url, imageDataWithSuffix.data(), imageDataWithSuffix.size(), suffix);
210 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageDataWithSuffix.size()));
211 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
212 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
213 ASSERT_EQ(fileInfo.fileName, fileCacheKey + suffix);
214 ASSERT_EQ(fileInfo.accessCount, 1);
215 }
216
217 /**
218 * @tc.name: WriteCacheFileFunc004
219 * @tc.desc: Test WriteCacheFileFun with svg.
220 * @tc.type: FUNC
221 */
222 HWTEST_F(ImageFileCacheTestNg, WriteCacheFileFunc004, TestSize.Level1)
223 {
224 RefPtr<MockImageSource> mockImageSource = AceType::MakeRefPtr<MockImageSource>();
225 MockImageSource::mockImageSource_ = mockImageSource;
226 /**
227 * @tc.steps: step1. construct a data.
228 */
229 std::vector<uint8_t> imageData = {1, 2, 3, 4, 5, 6};
230 std::string url = "http:/testfilecache002/image";
231 std::string fileCacheKey = std::to_string(std::hash<std::string> {}(url));
232
233 /**
234 * @tc.steps: step2. call WriteCacheFile().
235 */
236 ImageFileCache::GetInstance().WriteCacheFile(url, imageData.data(), imageData.size());
237 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
238 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
239 FileInfo fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
240 size_t accessCount = fileInfo.accessCount;
241 ASSERT_EQ(accessCount, 1);
242
243 /**
244 * @tc.steps: step3. call GetCacheFilePathInner(), each call will increase accessCount by one,
245 * when accessCount reaches convertAstcThreshold, ConvertToAstcAndWriteToFile() will be called.
246 * @tc.expected: because image is svg format, will not do the convert, fileInfo will not update,
247 * fileName does not contain ASTC_SUFFIX.
248 */
249 std::string filePath;
250 auto convertAstcThreshold = SystemProperties::GetImageFileCacheConvertAstcThreshold();
251 while (accessCount <= convertAstcThreshold) {
252 accessCount++;
253 bool convertToAstc = accessCount == convertAstcThreshold;
254 if (convertToAstc) {
255 EXPECT_CALL(*mockImageSource, GetFrameCount()).WillOnce(Return(1));
256 EXPECT_CALL(*mockImageSource, GetEncodedFormat()).WillOnce(Return(SVG_FORMAT));
257 }
258 filePath = ImageFileCache::GetInstance().GetCacheFilePathInner(url, "");
259 ASSERT_EQ(filePath, ImageFileCache::GetInstance().ConstructCacheFilePath(fileCacheKey));
260 if (convertToAstc) {
261 sleep(1);
262 }
263 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileSize_, static_cast<int32_t>(imageData.size()));
264 ASSERT_EQ(ImageFileCache::GetInstance().cacheFileInfo_.size(), 1);
265 fileInfo = ImageFileCache::GetInstance().cacheFileInfo_.front();
266 ASSERT_EQ(fileInfo.fileName, fileCacheKey);
267 ASSERT_EQ(fileInfo.accessCount, accessCount);
268 }
269 }
270 } // namespace OHOS::Ace::NG
271