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 32namespace OHOS { 33bool CompareTools::enableLog_ = false; 34char* CompareTools::logPath_ = nullptr; 35 36void 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 46bool 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 65bool 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 107bool 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 158bool 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 203bool 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 240bool 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 269void 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 278bool 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 296bool 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 309void 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 324void CompareTools::UnsetLogPath() 325{ 326 if (logPath_ != nullptr) { 327 delete[] logPath_; 328 logPath_ = nullptr; 329 enableLog_ = false; 330 } 331} 332 333bool 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