1 /*
2  * Copyright (c) 2020-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 "compare_tools.h"
17 #include <cstring>
18 #include "common/screen.h"
19 #include "dock/screen_device_proxy.h"
20 #include "draw/draw_utils.h"
21 #include "gfx_utils/file.h"
22 #include "gfx_utils/graphic_log.h"
23 #include "gfx_utils/graphic_math.h"
24 #include "graphic_config.h"
25 #include "securec.h"
26 
27 #ifdef _WIN32
28     #define STR(STRING) #STRING
29     #define STRPATH(STRING) STR(STRING)
30 #endif
31 
32 namespace OHOS {
33 bool CompareTools::enableLog_ = false;
34 char* CompareTools::logPath_ = nullptr;
35 
WaitSuspend(const uint16_t waitTime)36 void CompareTools::WaitSuspend(const uint16_t waitTime)
37 {
38     uint16_t sleepTime = waitTime == 0 ? DEFAULT_WAIT_TIME_MS : waitTime;
39 #ifdef _WIN32
40     Sleep(sleepTime);
41 #else
42     usleep(1000 * sleepTime); // 1000: us to ms
43 #endif // _WIN32
44 }
45 
StrnCatPath(char * filePath,size_t pathMax,const char * fileName,size_t count)46 bool CompareTools::StrnCatPath(char* filePath, size_t pathMax, const char* fileName, size_t count)
47 {
48     if ((filePath == nullptr) || (pathMax > DEFAULT_FILE_NAME_MAX_LENGTH)) {
49         return false;
50     }
51 #ifdef _WIN32
52     char dest[DEFAULT_FILE_NAME_MAX_LENGTH] = STRPATH(AUTO_TEST_RESOURCE_PATH);
53 #else
54     char dest[DEFAULT_FILE_NAME_MAX_LENGTH] = AUTO_TEST_RESOURCE_PATH;
55 #endif // _WIN32
56     if (strncat_s(dest, DEFAULT_FILE_NAME_MAX_LENGTH, fileName, count) != EOK) {
57         return false;
58     }
59     if (memcpy_s(static_cast<void *>(filePath), pathMax, dest, DEFAULT_FILE_NAME_MAX_LENGTH) != EOK) {
60         return false;
61     }
62     return true;
63 }
64 
CompareByBit(uint32_t fd)65 bool CompareTools::CompareByBit(uint32_t fd)
66 {
67     ImageInfo imageBit;
68     if (!(Screen::GetInstance().GetCurrentScreenBitmap(imageBit))) {
69         return false;
70     }
71     struct BitmapInfoHeader bitmapInfo = {0};
72     lseek(fd, sizeof(uint16_t), SEEK_SET);
73     if (read(fd, &bitmapInfo, sizeof(bitmapInfo)) < 0) {
74         ImageCacheFree(imageBit);
75         return false;
76     }
77     if (bitmapInfo.biSizeImage != imageBit.dataSize) {
78         ImageCacheFree(imageBit);
79         return false;
80     }
81     bool flag = true;
82     uint32_t buffSize = bitmapInfo.biSizeImage / MATH_ABS(bitmapInfo.biHeight);
83     auto buff = new uint8_t[buffSize];
84     for (uint32_t i = 0; i < MATH_ABS(bitmapInfo.biHeight); i++) {
85         if (flag && (memset_s(buff, buffSize, 0, buffSize) != EOK)) {
86             flag = false;
87             break;
88         }
89         int32_t ret = read(fd, buff, buffSize);
90         if (ret < 0) {
91             flag = false;
92             break;
93         }
94         for (uint32_t j = 0; j < ret; j++) {
95             if (buff[j] != imageBit.data[i * buffSize + j]) {
96                 flag = false;
97                 break;
98             }
99         }
100     }
101     ImageCacheFree(imageBit);
102     delete [] buff;
103     buff = nullptr;
104     return flag;
105 }
106 
CompareByBitmap(const BitmapInfoHeader bitmapInfoBase,const BitmapInfoHeader bitmapInfoRun,uint32_t fdBase,uint32_t fdRun)107 bool CompareTools::CompareByBitmap(const BitmapInfoHeader bitmapInfoBase,
108     const BitmapInfoHeader bitmapInfoRun, uint32_t fdBase, uint32_t fdRun)
109 {
110     bool flag = true;
111     uint32_t buffSizeBase = bitmapInfoBase.biSizeImage / MATH_ABS(bitmapInfoBase.biHeight);
112     auto buffBase = new uint8_t[buffSizeBase];
113 
114     uint32_t buffSizeRun = bitmapInfoRun.biSizeImage / MATH_ABS(bitmapInfoRun.biHeight);
115     auto buffRun = new uint8_t[buffSizeRun];
116 
117     for (uint32_t i = 0; i < MATH_ABS(bitmapInfoBase.biHeight); i++) {
118         if (flag && (memset_s(buffBase, buffSizeBase, 0, buffSizeBase) != EOK)) {
119             flag = false;
120             break;
121         }
122         if (flag && (memset_s(buffRun, buffSizeRun, 0, buffSizeRun) != EOK)) {
123             flag = false;
124             break;
125         }
126         int32_t retBase = read(fdBase, buffBase, buffSizeBase);
127         if (retBase < 0) {
128             flag = false;
129             break;
130         }
131         int32_t retRun = read(fdRun, buffRun, buffSizeBase);
132         if (retRun < 0) {
133             flag = false;
134             break;
135         }
136         if (retBase != retRun) {
137             flag = false;
138             break;
139         }
140 
141         for (uint32_t j = 0; j < retBase; j++) {
142             if (buffBase[j] != buffRun[j]) {
143                 flag = false;
144                 break;
145             }
146         }
147     }
148 
149     delete [] buffBase;
150     buffBase = nullptr;
151     delete [] buffRun;
152     buffRun = nullptr;
153 
154     return flag;
155 }
156 
157 
CompareFile(const char * fileBasePath,const char * fileRunPath)158 bool CompareTools::CompareFile(const char* fileBasePath, const char* fileRunPath)
159 {
160     if (fileBasePath == nullptr || fileRunPath == nullptr) {
161         return false;
162     }
163 #ifdef _WIN32
164     uint32_t fdBase = open(fileBasePath, O_RDONLY | O_BINARY);
165     uint32_t fdRun = open(fileRunPath, O_RDONLY | O_BINARY);
166 #else
167     uint32_t fdBase = open(fileBasePath, O_RDONLY);
168     uint32_t fdRun = open(fileRunPath, O_RDONLY);
169 #endif
170     struct BitmapInfoHeader bitmapInfoBase = {0};
171     lseek(fdBase, sizeof(uint16_t), SEEK_SET);
172     if (read(fdBase, &bitmapInfoBase, sizeof(bitmapInfoBase)) < 0) {
173         close(fdBase);
174         close(fdRun);
175         return false;
176     }
177 
178     struct BitmapInfoHeader bitmapInfoRun = {0};
179     lseek(fdRun, sizeof(uint16_t), SEEK_SET);
180     if (read(fdRun, &bitmapInfoRun, sizeof(bitmapInfoRun)) < 0) {
181         close(fdBase);
182         close(fdRun);
183         return false;
184     }
185 
186     if (bitmapInfoBase.biSizeImage != bitmapInfoRun.biSizeImage) {
187         close(fdBase);
188         close(fdRun);
189         return false;
190     }
191 
192     if (!CompareByBitmap(bitmapInfoBase, bitmapInfoRun, fdBase, fdRun)) {
193         close(fdBase);
194         close(fdRun);
195         return false;
196     }
197 
198     close(fdBase);
199     close(fdRun);
200     return true;
201 }
202 
CompareFile(const char * filePath,size_t length)203 bool CompareTools::CompareFile(const char* filePath, size_t length)
204 {
205     if ((filePath == nullptr) || (length > DEFAULT_FILE_NAME_MAX_LENGTH)) {
206         return false;
207     }
208 #ifdef _WIN32
209     uint32_t fd = open(filePath, O_RDONLY | O_BINARY);
210 #else
211     uint32_t fd = open(filePath, O_RDONLY);
212 #endif
213     if (fd == -1) {
214         return false;
215     }
216     bool flag = CompareByBit(fd);
217     close(fd);
218     if (flag) {
219         GRAPHIC_LOGI("[COMPARE_SUCCESS]:fileName=%s", filePath);
220         if (enableLog_) {
221             char logInfo[DEFAULT_FILE_NAME_MAX_LENGTH] = {0};
222             if (sprintf_s(logInfo, sizeof(logInfo), "[COMPARE_SUCCESS]:fileName=%s\n", filePath) < 0) {
223                 return false;
224             }
225             SaveLog(logInfo, strlen(logInfo));
226         }
227     } else {
228         GRAPHIC_LOGI("[COMPARE_FAILURE]:fileName=%s", filePath);
229         if (enableLog_) {
230             char logInfo[DEFAULT_FILE_NAME_MAX_LENGTH] = {0};
231             if (sprintf_s(logInfo, sizeof(logInfo), "[COMPARE_FAILURE]:fileName=%s\n", filePath) < 0) {
232                 return false;
233             }
234             SaveLog(logInfo, strlen(logInfo));
235         }
236     }
237     return flag;
238 }
239 
SaveByBit(uint32_t fd)240 bool CompareTools::SaveByBit(uint32_t fd)
241 {
242     ImageInfo imageBit;
243     if (!(Screen::GetInstance().GetCurrentScreenBitmap(imageBit))) {
244         return false;
245     }
246     bool flag = false;
247     uint8_t sizeByColorMode = DrawUtils::GetByteSizeByColorMode(ScreenDeviceProxy::GetInstance()->GetBufferMode());
248     uint16_t bfType = 0x4D42;
249     struct BitmapInfoHeader bitmapInfo = {0};
250     bitmapInfo.bfSize = imageBit.dataSize + BITMAP_HEADER_SIZE;
251     bitmapInfo.bfOffBits = BITMAP_HEADER_SIZE;
252     bitmapInfo.biSize = 40; // 40: bitmap information header size
253     bitmapInfo.biWidth = imageBit.header.width;
254     bitmapInfo.biHeight = -imageBit.header.height;
255     bitmapInfo.biPlanes = 1;
256     bitmapInfo.biBitCount = sizeByColorMode * 8; // 8: uint8_t bit
257     bitmapInfo.biSizeImage = imageBit.dataSize;
258     if (write(fd, &bfType, sizeof(bfType)) > 0) {
259         if (write(fd, &bitmapInfo, sizeof(bitmapInfo)) > 0) {
260             if (write(fd, imageBit.data, imageBit.dataSize) > 0) {
261                 flag = true;
262             }
263         }
264     }
265     ImageCacheFree(imageBit);
266     return flag;
267 }
268 
SaveResultLog(const char * filePath,const char * buff,size_t bufSize)269 void CompareTools::SaveResultLog(const char* filePath, const char* buff, size_t bufSize)
270 {
271     if (filePath == nullptr || buff == nullptr || bufSize <= 0) {
272         return;
273     }
274 
275     SaveLog(buff, bufSize, filePath);
276 }
277 
SaveFile(const char * filePath,size_t length)278 bool CompareTools::SaveFile(const char* filePath, size_t length)
279 {
280     if ((filePath == nullptr) || (length > DEFAULT_FILE_NAME_MAX_LENGTH)) {
281         return false;
282     }
283 #ifdef _WIN32
284     uint32_t fd = open(filePath, O_WRONLY | O_CREAT | O_BINARY, DEFAULT_FILE_PERMISSION);
285 #else
286     uint32_t fd = open(filePath, O_WRONLY | O_CREAT, DEFAULT_FILE_PERMISSION);
287 #endif
288     if (fd == -1) {
289         return false;
290     }
291     bool flag = SaveByBit(fd);
292     close(fd);
293     return flag;
294 }
295 
CheckFileExist(const char * filePath,size_t length)296 bool CompareTools::CheckFileExist(const char* filePath, size_t length)
297 {
298     if ((filePath == nullptr) || (length > DEFAULT_FILE_NAME_MAX_LENGTH)) {
299         return false;
300     }
301     uint32_t fd = open(filePath, O_RDONLY);
302     if (fd == -1) {
303         return false;
304     }
305     close(fd);
306     return true;
307 }
308 
SetLogPath(const char * filePath,size_t length)309 void CompareTools::SetLogPath(const char* filePath, size_t length)
310 {
311     if (logPath_ == nullptr) {
312         logPath_ = new char[length];
313         if (logPath_ == nullptr) {
314             return;
315         }
316         if (memcpy_s(logPath_, length, filePath, length) != EOK) {
317             GRAPHIC_LOGE("memcpy filepath failed");
318             return;
319         }
320         enableLog_ = true;
321     }
322 }
323 
UnsetLogPath()324 void CompareTools::UnsetLogPath()
325 {
326     if (logPath_ != nullptr) {
327         delete[] logPath_;
328         logPath_ = nullptr;
329         enableLog_ = false;
330     }
331 }
332 
SaveLog(const char * buff,size_t bufSize,const char * filePath)333 bool CompareTools::SaveLog(const char* buff, size_t bufSize, const char* filePath)
334 {
335     if (buff == nullptr) {
336         return false;
337     }
338 
339     const char* useLogPath = filePath == nullptr ? logPath_ : filePath;
340     if (useLogPath == nullptr) {
341         return false;
342     }
343 
344     uint32_t logFd = open(useLogPath, O_WRONLY | O_CREAT | O_APPEND, DEFAULT_FILE_PERMISSION);
345     if (logFd == -1) {
346         GRAPHIC_LOGE("open log failed");
347         return false;
348     }
349     if (write(logFd, buff, bufSize) < 0) {
350         close(logFd);
351         GRAPHIC_LOGE("write log failed");
352         return false;
353     }
354     close(logFd);
355     return true;
356 }
357 } // namespace OHOS
358