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