* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "MockFile.h"
#include <filesystem>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include "zlib.h"
#include "contrib/minizip/zip.h"
using namespace testmock;
namespace fs = std::filesystem;
bool MockFile::SimulateFileLock(const std::string& filePath)
{
int fd = open(filePath.c_str(), O_RDWR | O_CREAT);
if (fd == -1) {
return false;
}
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
if (fcntl(fd, F_SETLK, &fl) == -1) {
close(fd);
return true;
}
close(fd);
return false;
}
bool MockFile::ReleaseFileLock(const std::string& filePath)
{
int fd = open(filePath.c_str(), O_RDWR | O_CREAT);
if (fd == -1) {
return false;
}
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
if (fcntl(fd, F_SETLK, &fl) == -1) {
close(fd);
return false;
}
close(fd);
return true;
}
bool MockFile::AddFileToZip(zipFile zip, const std::string& filePath, const std::string& entryName)
{
if (zipOpenNewFileInZip(zip, entryName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED,
Z_DEFAULT_COMPRESSION) != ZIP_OK) {
std::cerr << "Failed to create entry in zip file for " << filePath << std::endl;
return false;
}
FILE* file = fopen(filePath.c_str(), "rb");
if (!file) {
std::cerr << "Failed to open file " << filePath << std::endl;
zipCloseFileInZip(zip);
return false;
}
const int bufferSize = 1024;
void* buffer = malloc(bufferSize);
int size;
while ((size = fread(buffer, 1, bufferSize, file)) > 0) {
if (zipWriteInFileInZip(zip, buffer, size) < 0) {
std::cerr << "Failed to write to zip for " << filePath << std::endl;
free(buffer);
if (fclose(file) == EOF) {
std::cerr << "Failed to close file" << std::endl;
return false;
}
zipCloseFileInZip(zip);
return false;
}
}
free(buffer);
if (fclose(file) == EOF) {
std::cerr << "Failed to close file" << std::endl;
return false;
}
zipCloseFileInZip(zip);
return true;
}
bool MockFile::AddFolderToZip(zipFile zip, const std::string& folderPath, const std::string& entryName)
{
for (const auto& entry : fs::recursive_directory_iterator(folderPath)) {
std::string relativePath = entry.path().string().substr(folderPath.length() + 1);
if (fs::is_directory(entry)) {
if (zipOpenNewFileInZip(zip, (entryName + "/" + relativePath + "/").c_str(), NULL, NULL, 0,
NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) {
std::cerr << "Failed to create entry in zip file for " << entry.path() << std::endl;
return false;
}
zipCloseFileInZip(zip);
} else {
if (!AddFileToZip(zip, entry.path().string(), entryName + "/" + relativePath)) {
return false;
}
}
}
return true;
}
bool MockFile::CompressFiles(const std::vector<std::string>& files, const std::string& zipFilename)
{
zipFile zip = zipOpen(zipFilename.c_str(), APPEND_STATUS_CREATE);
if (!zip) {
std::cerr << "Could not create zip file " << zipFilename << std::endl;
return false;
}
for (const auto& file : files) {
if (fs::is_directory(file)) {
if (!AddFolderToZip(zip, file, fs::path(file).filename())) {
zipClose(zip, NULL);
return false;
}
} else {
if (!AddFileToZip(zip, file, fs::path(file).filename())) {
zipClose(zip, NULL);
return false;
}
}
}
if (zipClose(zip, NULL) != ZIP_OK) {
std::cerr << "Failed to close zip file " << zipFilename << std::endl;
return false;
}
return true;
}
namespace {
void WriteToFile(const std::string& filePath, const std::string& content)
{
std::ofstream file(filePath);
if (!file) {
std::cerr << "Error creating file: " << filePath << std::endl;
return;
}
file << content;
file.close();
}
void CreateFiles(const std::string hspAbcContent)
{
std::filesystem::path dir("ets");
if (std::filesystem::exists(dir)) {
std::cout << "Folder already exists." << std::endl;
} else {
std::filesystem::create_directory(dir);
std::cout << "Folder created successfully." << std::endl;
}
WriteToFile("ets/modules.abc", hspAbcContent);
WriteToFile("module.json", hspAbcContent);
}
}
std::string MockFile::CreateHspFile(const std::string hspFileName, const std::string hspAbcContent)
{
CreateFiles(hspAbcContent);
std::vector<std::string> filesToCompress = { "ets", "module.json" };
std::string zipFilename = hspFileName + ".zip";
std::string newFileName = hspFileName + ".hsp";
if (CompressFiles(filesToCompress, zipFilename)) {
std::cout << "Compression successful. File created: " << zipFilename << std::endl;
if (std::rename(zipFilename.c_str(), newFileName.c_str()) != 0) {
std::cout << newFileName << " 创建hsp文件失败" << std::endl;
return "";
}
} else {
std::cerr << "Compression failed." << std::endl;
return "";
}
return newFileName;
}