diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..612326ba422231742ae7c0250120114c9c30cd58 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp @@ -0,0 +1,891 @@ +/* + * Copyright (c) 2025 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 "copy_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "datashare_helper.h" +#include "file_uri.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" +#include "if_system_ability_manager.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "trans_listener_core.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace AppFileService::ModuleFileUri; +namespace fs = std::filesystem; +const std::string FILE_PREFIX_NAME = "file://"; +const std::string NETWORK_PARA = "?networkid="; +const string PROCEDURE_COPY_NAME = "FileFSCopy"; +const std::string MEDIALIBRARY_DATA_URI = "datashare:///media"; +const std::string MEDIA = "media"; +const int SLEEP_TIME = 100000; +constexpr int DISMATCH = 0; +constexpr int MATCH = 1; +constexpr int BUF_SIZE = 1024; +constexpr size_t MAX_SIZE = 1024 * 1024 * 4; +constexpr std::chrono::milliseconds NOTIFY_PROGRESS_DELAY(300); +std::recursive_mutex CopyCore::mutex_; +std::map> CopyCore::callbackMap_; + +static int OpenSrcFile(const string &srcPth, std::shared_ptr infos, int32_t &srcFd) +{ + Uri uri(infos->srcUri); + if (uri.GetAuthority() == MEDIA) { + std::shared_ptr dataShareHelper = nullptr; + sptr remote = new (std::nothrow) IRemoteStub(); + if (!remote) { + HILOGE("Failed to get remote object"); + return ENOMEM; + } + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); + if (!dataShareHelper) { + HILOGE("Failed to connect to datashare"); + return E_PERMISSION; + } + srcFd = dataShareHelper->OpenFile(uri, FsUtils::GetModeFromFlags(O_RDONLY)); + if (srcFd < 0) { + HILOGE("Open media uri by data share fail. ret = %{public}d", srcFd); + return EPERM; + } + } else { + srcFd = open(srcPth.c_str(), O_RDONLY); + if (srcFd < 0) { + HILOGE("Error opening src file descriptor. errno = %{public}d", errno); + return errno; + } + } + return ERRNO_NOERR; +} + +static int SendFileCore(std::unique_ptr srcFdg, std::unique_ptr destFdg, + std::shared_ptr infos) +{ + std::unique_ptr sendFileReq = { new (nothrow) uv_fs_t, + FsUtils::FsReqCleanup }; + if (sendFileReq == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int64_t offset = 0; + struct stat srcStat {}; + if (fstat(srcFdg->GetFD(), &srcStat) < 0) { + HILOGE("Failed to get stat of file by fd: %{public}d ,errno = %{public}d", srcFdg->GetFD(), errno); + return errno; + } + int32_t ret = 0; + int64_t size = static_cast(srcStat.st_size); + while (size >= 0) { + ret = uv_fs_sendfile(nullptr, sendFileReq.get(), destFdg->GetFD(), srcFdg->GetFD(), offset, MAX_SIZE, nullptr); + if (ret < 0) { + HILOGE("Failed to sendfile by errno : %{public}d", errno); + return errno; + } + if (infos != nullptr && infos->taskSignal != nullptr) { + if (infos->taskSignal->CheckCancelIfNeed(infos->srcPath)) { + return ECANCELED; + } + } + offset += static_cast(ret); + size -= static_cast(ret); + if (ret == 0) { + break; + } + } + if (size != 0) { + HILOGE("The execution of the sendfile task was terminated, remaining file size %{public}" PRIu64, size); + return EIO; + } + return ERRNO_NOERR; +} + +bool CopyCore::IsValidUri(const std::string &uri) +{ + return uri.find(FILE_PREFIX_NAME) == 0; +} + +bool CopyCore::ValidOperand(std::string uriStr) +{ + return IsValidUri(uriStr); +} + +bool CopyCore::IsRemoteUri(const std::string &uri) +{ + // NETWORK_PARA + return uri.find(NETWORK_PARA) != uri.npos; +} + +bool CopyCore::IsDirectory(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGE("Stat failed, errno is %{public}d", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFDIR; +} + +bool CopyCore::IsFile(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGI("Stat failed, errno is %{public}d, ", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFREG; +} + +bool CopyCore::IsMediaUri(const std::string &uriPath) +{ + Uri uri(uriPath); + string bundleName = uri.GetAuthority(); + return bundleName == MEDIA; +} + +tuple CopyCore::GetFileSize(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGI("Stat failed."); + return { errno, 0 }; + } + return { ERRNO_NOERR, buf.st_size }; +} + +int CopyCore::CheckOrCreatePath(const std::string &destPath) +{ + std::error_code errCode; + if (!filesystem::exists(destPath, errCode) && errCode.value() == ERRNO_NOERR) { + HILOGI("DestPath not exist"); + auto file = open(destPath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (file < 0) { + HILOGE("Error opening file descriptor. errno = %{public}d", errno); + return errno; + } + close(file); + } else if (errCode.value() != 0) { + return errCode.value(); + } + return ERRNO_NOERR; +} + +int CopyCore::CopyFile(const string &src, const string &dest, std::shared_ptr infos) +{ + HILOGD("src = %{public}s, dest = %{public}s", GetAnonyString(src).c_str(), GetAnonyString(dest).c_str()); + + int32_t srcFd = -1; + int32_t ret = OpenSrcFile(src, infos, srcFd); + if (srcFd < 0) { + return ret; + } + + auto destFd = open(dest.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (destFd < 0) { + HILOGE("Error opening dest file descriptor. errno = %{public}d", errno); + close(srcFd); + return errno; + } + + auto srcFdg = CreateUniquePtr(srcFd, true); + auto destFdg = CreateUniquePtr(destFd, true); + if (srcFdg == nullptr || destFdg == nullptr) { + HILOGE("Failed to request heap memory."); + close(srcFd); + close(destFd); + return ENOMEM; + } + return SendFileCore(move(srcFdg), move(destFdg), infos); +} + +int CopyCore::MakeDir(const string &path) +{ + filesystem::path destDir(path); + std::error_code errCode; + if (!filesystem::create_directory(destDir, errCode)) { + HILOGE("Failed to create directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +int CopyCore::CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos) +{ + std::error_code errCode; + if (!filesystem::exists(destPath, errCode) && errCode.value() == ERRNO_NOERR) { + int res = MakeDir(destPath); + if (res != ERRNO_NOERR) { + HILOGE("Failed to mkdir"); + return res; + } + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + uint32_t watchEvents = IN_MODIFY; + if (infos->notifyFd >= 0) { + int newWd = inotify_add_watch(infos->notifyFd, destPath.c_str(), watchEvents); + if (newWd < 0) { + HILOGE("inotify_add_watch, newWd is unvaild, newWd = %{public}d", newWd); + return errno; + } + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + auto receiveInfo = CreateSharedPtr(); + if (receiveInfo == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + receiveInfo->path = destPath; + if (iter == CopyCore::callbackMap_.end() || iter->second == nullptr) { + HILOGE("Failed to find infos, srcPath = %{public}s, destPath = %{public}s", + GetAnonyString(infos->srcPath).c_str(), GetAnonyString(infos->destPath).c_str()); + return UNKNOWN_ERR; + } + iter->second->wds.push_back({ newWd, receiveInfo }); + } + } + return RecurCopyDir(srcPath, destPath, infos); +} + +static int FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return DISMATCH; + } + return MATCH; +} + +struct NameList { + struct dirent **namelist = { nullptr }; + int direntNum = 0; +}; + +static void Deleter(struct NameList *arg) +{ + for (int i = 0; i < arg->direntNum; i++) { + free((arg->namelist)[i]); + (arg->namelist)[i] = nullptr; + } + free(arg->namelist); + arg->namelist = nullptr; + delete arg; + arg = nullptr; +} + +std::string CopyCore::GetRealPath(const std::string &path) +{ + fs::path tempPath(path); + fs::path realPath {}; + for (const auto &component : tempPath) { + if (component == ".") { + continue; + } else if (component == "..") { + realPath = realPath.parent_path(); + } else { + realPath /= component; + } + } + return realPath.string(); +} + +uint64_t CopyCore::GetDirSize(std::shared_ptr infos, std::string path) +{ + unique_ptr pNameList = { new (nothrow) struct NameList, Deleter }; + if (pNameList == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, alphasort); + pNameList->direntNum = num; + + long int size = 0; + for (int i = 0; i < num; i++) { + string dest = path + '/' + string((pNameList->namelist[i])->d_name); + if ((pNameList->namelist[i])->d_type == DT_LNK) { + continue; + } + if ((pNameList->namelist[i])->d_type == DT_DIR) { + size += static_cast(GetDirSize(infos, dest)); + } else { + struct stat st {}; + if (stat(dest.c_str(), &st) == -1) { + return size; + } + size += st.st_size; + } + } + return size; +} + +int CopyCore::RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos) +{ + unique_ptr pNameList = { new (nothrow) struct NameList, Deleter }; + if (pNameList == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(srcPath.c_str(), &(pNameList->namelist), FilterFunc, alphasort); + pNameList->direntNum = num; + + for (int i = 0; i < num; i++) { + string src = srcPath + '/' + string((pNameList->namelist[i])->d_name); + string dest = destPath + '/' + string((pNameList->namelist[i])->d_name); + if ((pNameList->namelist[i])->d_type == DT_LNK) { + continue; + } + int ret = ERRNO_NOERR; + if ((pNameList->namelist[i])->d_type == DT_DIR) { + ret = CopySubDir(src, dest, infos); + } else { + infos->filePaths.insert(dest); + ret = CopyFile(src, dest, infos); + } + if (ret != ERRNO_NOERR) { + return ret; + } + } + return ERRNO_NOERR; +} + +int CopyCore::CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos) +{ + HILOGD("CopyDirFunc in, src = %{public}s, dest = %{public}s", GetAnonyString(src).c_str(), + GetAnonyString(dest).c_str()); + size_t found = dest.find(src); + if (found != std::string::npos && found == 0) { + return EINVAL; + } + fs::path srcPath = fs::u8path(src); + std::string dirName; + if (srcPath.has_parent_path()) { + dirName = srcPath.parent_path().filename(); + } + string destStr = dest + "/" + dirName; + return CopySubDir(src, destStr, infos); +} + +int CopyCore::ExecLocal(std::shared_ptr infos, std::shared_ptr callback) +{ + if (infos->isFile) { + if (infos->srcPath == infos->destPath) { + HILOGE("The src and dest is same"); + return EINVAL; + } + int ret = CheckOrCreatePath(infos->destPath); + if (ret != ERRNO_NOERR) { + HILOGE("Check or create fail, error code is %{public}d", ret); + return ret; + } + } + if (!infos->hasListener) { + return ExecCopy(infos); + } + auto ret = SubscribeLocalListener(infos, callback); + if (ret != ERRNO_NOERR) { + HILOGE("Failed to subscribe local listener, errno = %{public}d", ret); + return ret; + } + StartNotify(infos, callback); + return ExecCopy(infos); +} + +int CopyCore::SubscribeLocalListener(std::shared_ptr infos, std::shared_ptr callback) +{ + infos->notifyFd = inotify_init(); + if (infos->notifyFd < 0) { + HILOGE("Failed to init inotify, errno:%{public}d", errno); + return errno; + } + infos->eventFd = eventfd(0, EFD_CLOEXEC); + if (infos->eventFd < 0) { + HILOGE("Failed to init eventFd, errno:%{public}d", errno); + return errno; + } + callback->notifyFd = infos->notifyFd; + callback->eventFd = infos->eventFd; + int newWd = inotify_add_watch(infos->notifyFd, infos->destPath.c_str(), IN_MODIFY); + if (newWd < 0) { + auto errCode = errno; + HILOGE("Failed to add watch, errno = %{public}d, notifyFd: %{public}d, destPath: %{public}s", errno, + infos->notifyFd, infos->destPath.c_str()); + CloseNotifyFdLocked(infos, callback); + return errCode; + } + auto receiveInfo = CreateSharedPtr(); + if (receiveInfo == nullptr) { + HILOGE("Failed to request heap memory."); + inotify_rm_watch(infos->notifyFd, newWd); + CloseNotifyFdLocked(infos, callback); + return ENOMEM; + } + receiveInfo->path = infos->destPath; + callback->wds.push_back({ newWd, receiveInfo }); + if (!infos->isFile) { + callback->totalSize = GetDirSize(infos, infos->srcPath); + return ERRNO_NOERR; + } + auto [err, fileSize] = GetFileSize(infos->srcPath); + if (err == ERRNO_NOERR) { + callback->totalSize = fileSize; + } + return err; +} + +std::shared_ptr CopyCore::RegisterListener(const std::shared_ptr &infos) +{ + auto callback = CreateSharedPtr(infos->listener); + if (callback == nullptr) { + HILOGE("Failed to request heap memory."); + return nullptr; + } + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter != callbackMap_.end()) { + HILOGE("CopyCore::RegisterListener, already registered."); + return nullptr; + } + callbackMap_.insert({ *infos, callback }); + return callback; +} + +void CopyCore::UnregisterListener(std::shared_ptr fileInfos) +{ + if (fileInfos == nullptr) { + HILOGE("fileInfos is nullptr"); + return; + } + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*fileInfos); + if (iter == callbackMap_.end()) { + HILOGI("It is not be registered."); + return; + } + callbackMap_.erase(*fileInfos); +} + +void CopyCore::ReceiveComplete(std::shared_ptr entry) +{ + if (entry == nullptr) { + HILOGE("entry pointer is nullptr."); + return; + } + if (entry->callback == nullptr) { + HILOGE("entry callback pointer is nullptr."); + return; + } + auto processedSize = entry->progressSize; + if (processedSize < entry->callback->maxProgressSize) { + return; + } + entry->callback->maxProgressSize = processedSize; + auto listener = entry->callback->listener; + if (listener == nullptr) { + HILOGE("listener pointer is nullptr."); + return; + } + listener->InvokeListener(processedSize, entry->totalSize); +} + +FsUvEntry *CopyCore::GetUVEntry(std::shared_ptr infos) +{ + FsUvEntry *entry = nullptr; + { + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter == callbackMap_.end()) { + HILOGE("Failed to find callback"); + return nullptr; + } + auto callback = iter->second; + entry = new (std::nothrow) FsUvEntry(iter->second, infos); + if (entry == nullptr) { + HILOGE("entry ptr is nullptr."); + return nullptr; + } + entry->progressSize = callback->progressSize; + entry->totalSize = callback->totalSize; + } + return entry; +} + +void CopyCore::OnFileReceive(std::shared_ptr infos) +{ + std::shared_ptr entry(GetUVEntry(infos)); + if (entry == nullptr) { + HILOGE("failed to get uv entry"); + return; + } + ReceiveComplete(entry); +} + +std::shared_ptr CopyCore::GetReceivedInfo(int wd, std::shared_ptr callback) +{ + auto it = find_if(callback->wds.begin(), callback->wds.end(), [wd](const auto &item) { return item.first == wd; }); + if (it != callback->wds.end()) { + return it->second; + } + return nullptr; +} + +bool CopyCore::CheckFileValid(const std::string &filePath, std::shared_ptr infos) +{ + return infos->filePaths.count(filePath) != 0; +} + +int CopyCore::UpdateProgressSize( + const std::string &filePath, std::shared_ptr receivedInfo, std::shared_ptr callback) +{ + auto [err, fileSize] = GetFileSize(filePath); + if (err != ERRNO_NOERR) { + HILOGE("GetFileSize failed, err: %{public}d.", err); + return err; + } + + auto size = fileSize; + auto iter = receivedInfo->fileList.find(filePath); + if (iter == receivedInfo->fileList.end()) { + receivedInfo->fileList.insert({ filePath, size }); + callback->progressSize += size; + } else { // file + if (size > iter->second) { + callback->progressSize += (size - iter->second); + iter->second = size; + } + } + return ERRNO_NOERR; +} + +std::shared_ptr CopyCore::GetRegisteredListener(std::shared_ptr infos) +{ + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter == callbackMap_.end()) { + HILOGE("It is not registered."); + return nullptr; + } + return iter->second; +} + +void CopyCore::CloseNotifyFd(std::shared_ptr infos, std::shared_ptr callback) +{ + callback->closed = false; + infos->eventFd = -1; + infos->notifyFd = -1; + { + std::unique_lock lock(callback->cvLock); + callback->CloseFd(); + callback->cv.notify_one(); + } +} + +void CopyCore::CloseNotifyFdLocked(std::shared_ptr infos, std::shared_ptr callback) +{ + { + lock_guard lock(callback->readMutex); + callback->closed = true; + if (callback->reading) { + HILOGE("close while reading"); + return; + } + } + CloseNotifyFd(infos, callback); +} + +tuple CopyCore::HandleProgress( + inotify_event *event, std::shared_ptr infos, std::shared_ptr callback) +{ + if (callback == nullptr) { + return { true, EINVAL, false }; + } + auto receivedInfo = GetReceivedInfo(event->wd, callback); + if (receivedInfo == nullptr) { + return { true, EINVAL, false }; + } + std::string fileName = receivedInfo->path; + if (!infos->isFile) { // files under subdir + fileName += "/" + string(event->name); + if (!CheckFileValid(fileName, infos)) { + return { true, EINVAL, false }; + } + auto err = UpdateProgressSize(fileName, receivedInfo, callback); + if (err != ERRNO_NOERR) { + return { false, err, false }; + } + } else { + auto [err, fileSize] = GetFileSize(fileName); + if (err != ERRNO_NOERR) { + return { false, err, false }; + } + callback->progressSize = fileSize; + } + return { true, callback->errorCode, true }; +} + +void CopyCore::ReadNotifyEvent(std::shared_ptr infos) +{ + char buf[BUF_SIZE] = { 0 }; + struct inotify_event *event = nullptr; + int len = 0; + int64_t index = 0; + auto callback = GetRegisteredListener(infos); + while (infos->run && ((len = read(infos->notifyFd, &buf, sizeof(buf))) < 0) && (errno == EINTR)) { + } + while (infos->run && index < len) { + event = reinterpret_cast(buf + index); + auto [needContinue, errCode, needSend] = HandleProgress(event, infos, callback); + if (!needContinue) { + infos->exceptionCode = errCode; + return; + } + if (needContinue && !needSend) { + index += static_cast(sizeof(struct inotify_event) + event->len); + continue; + } + if (!callback || (callback->progressSize == callback->totalSize)) { + infos->run = false; + return; + } + auto currentTime = std::chrono::steady_clock::now(); + if (currentTime >= infos->notifyTime) { + OnFileReceive(infos); + infos->notifyTime = currentTime + NOTIFY_PROGRESS_DELAY; + } + index += static_cast(sizeof(struct inotify_event) + event->len); + } +} + +void CopyCore::ReadNotifyEventLocked(std::shared_ptr infos, std::shared_ptr callback) +{ + { + std::lock_guard lock(callback->readMutex); + if (callback->closed) { + HILOGE("read after close"); + return; + } + callback->reading = true; + } + ReadNotifyEvent(infos); + { + std::lock_guard lock(callback->readMutex); + callback->reading = false; + if (callback->closed) { + HILOGE("close after read"); + CloseNotifyFd(infos, callback); + return; + } + } +} + +void CopyCore::GetNotifyEvent(std::shared_ptr infos) +{ + auto callback = GetRegisteredListener(infos); + if (callback == nullptr) { + infos->exceptionCode = EINVAL; + return; + } + prctl(PR_SET_NAME, "NotifyThread"); + nfds_t nfds = 2; + struct pollfd fds[2]; + fds[0].events = 0; + fds[1].events = POLLIN; + fds[0].fd = infos->eventFd; + fds[1].fd = infos->notifyFd; + while (infos->run && infos->exceptionCode == ERRNO_NOERR && infos->eventFd != -1 && infos->notifyFd != -1) { + auto ret = poll(fds, nfds, -1); + if (ret > 0) { + if (static_cast(fds[0].revents) & POLLNVAL) { + infos->run = false; + return; + } + if (static_cast(fds[1].revents) & POLLIN) { + ReadNotifyEventLocked(infos, callback); + } + } else if (ret < 0 && errno == EINTR) { + continue; + } else { + infos->exceptionCode = errno; + return; + } + { + std::unique_lock lock(callback->cvLock); + callback->cv.wait_for( + lock, std::chrono::microseconds(SLEEP_TIME), [callback]() -> bool { return callback->notifyFd == -1; }); + } + } +} + +tuple> CopyCore::CreateFileInfos( + const std::string &srcUri, const std::string &destUri, const std::optional &options) +{ + auto infos = CreateSharedPtr(); + if (infos == nullptr) { + HILOGE("Failed to request heap memory."); + return { ENOMEM, nullptr }; + } + infos->srcUri = srcUri; + infos->destUri = destUri; + FileUri srcFileUri(infos->srcUri); + infos->srcPath = srcFileUri.GetRealPath(); + FileUri dstFileUri(infos->destUri); + infos->destPath = dstFileUri.GetPath(); + infos->srcPath = GetRealPath(infos->srcPath); + infos->destPath = GetRealPath(infos->destPath); + infos->isFile = IsMediaUri(infos->srcUri) || IsFile(infos->srcPath); + infos->notifyTime = std::chrono::steady_clock::now() + NOTIFY_PROGRESS_DELAY; + if (options.has_value()) { + auto listener = options.value().progressListener; + if (listener) { + infos->hasListener = true; + infos->listener = listener; + } + auto copySignal = options.value().copySignal; + if (copySignal) { + infos->taskSignal = copySignal->GetTaskSignal(); + } + } + + return { ERRNO_NOERR, infos }; +} + +void CopyCore::StartNotify(std::shared_ptr infos, std::shared_ptr callback) +{ + if (infos->hasListener && callback != nullptr) { + callback->notifyHandler = std::thread([infos] { GetNotifyEvent(infos); }); + } +} + +int CopyCore::ExecCopy(std::shared_ptr infos) +{ + if (infos->isFile && IsFile(infos->destPath)) { + // copyFile + return CopyFile(infos->srcPath.c_str(), infos->destPath.c_str(), infos); + } + if (!infos->isFile && IsDirectory(infos->destPath)) { + if (infos->srcPath.back() != '/') { + infos->srcPath += '/'; + } + if (infos->destPath.back() != '/') { + infos->destPath += '/'; + } + // copyDir + return CopyDirFunc(infos->srcPath.c_str(), infos->destPath.c_str(), infos); + } + return EINVAL; +} + +bool CopyCore::ValidParams(const string &src, const string &dest) +{ + auto succSrc = ValidOperand(src); + auto succDest = ValidOperand(dest); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires uri/uri"); + return false; + } + return true; +} + +void CopyCore::WaitNotifyFinished(std::shared_ptr callback) +{ + if (callback != nullptr) { + if (callback->notifyHandler.joinable()) { + callback->notifyHandler.join(); + } + } +} + +void CopyCore::CopyComplete(std::shared_ptr infos, std::shared_ptr callback) +{ + if (callback != nullptr && infos->hasListener) { + callback->progressSize = callback->totalSize; + OnFileReceive(infos); + } +} + +FsResult CopyCore::DoCopy(const string &src, const string &dest, std::optional &options) +{ + auto isValid = ValidParams(src, dest); + if (!isValid) { + return FsResult::Error(E_PARAMS); + } + + auto [errCode, infos] = CreateFileInfos(src, dest, options); + if (errCode != ERRNO_NOERR) { + return FsResult::Error(errCode); + } + + auto callback = RegisterListener(infos); + if (callback == nullptr) { + return FsResult::Error(EINVAL); + } + + if (IsRemoteUri(infos->srcUri)) { + if (infos->taskSignal != nullptr) { + infos->taskSignal->MarkRemoteTask(); + } + auto ret = TransListenerCore::CopyFileFromSoftBus(infos->srcUri, infos->destUri, infos, std::move(callback)); + UnregisterListener(infos); + if (ret != ERRNO_NOERR) { + return FsResult::Error(ret); + } else { + return FsResult::Success(); + } + } + auto result = CopyCore::ExecLocal(infos, callback); + CloseNotifyFdLocked(infos, callback); + infos->run = false; + WaitNotifyFinished(callback); + if (result != ERRNO_NOERR) { + infos->exceptionCode = result; + UnregisterListener(infos); + return FsResult::Error(infos->exceptionCode); + } + CopyComplete(infos, callback); + UnregisterListener(infos); + if (infos->exceptionCode != ERRNO_NOERR) { + return FsResult::Error(infos->exceptionCode); + } else { + return FsResult::Success(); + } +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_core.h b/interfaces/kits/js/src/mod_fs/properties/copy_core.h new file mode 100644 index 0000000000000000000000000000000000000000..245dff3f07feb92e9c12625585b89a3ca82f29c9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_core.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H + +#include +#include +#include +#include +#include + +#include "bundle_mgr_client_impl.h" +#include "filemgmt_libfs.h" +#include "filemgmt_libhilog.h" +#include "fs_task_signal.h" +#include "i_progress_listener.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::AppExecFwk; +using namespace DistributedFS::ModuleTaskSignal; + +struct CopyOptions { + shared_ptr progressListener; + shared_ptr copySignal; +}; + +struct ReceiveInfo { + std::string path; // dir name + std::map fileList; // filename, proceededSize +}; + +struct FsCallbackObject { + std::shared_ptr listener = nullptr; + int32_t notifyFd = -1; + int32_t eventFd = -1; + std::vector>> wds; + uint64_t totalSize = 0; + uint64_t progressSize = 0; + uint64_t maxProgressSize = 0; + int32_t errorCode = 0; + std::thread notifyHandler; + std::mutex readMutex; + std::condition_variable cv; + std::mutex cvLock; + bool reading = false; + bool closed = false; + explicit FsCallbackObject(std::shared_ptr listener) : listener(listener) {} + + void CloseFd() + { + if (eventFd != -1) { + close(eventFd); + eventFd = -1; + } + if (notifyFd == -1) { + return; + } + for (auto item : wds) { + inotify_rm_watch(notifyFd, item.first); + } + close(notifyFd); + notifyFd = -1; + } + + ~FsCallbackObject() + { + CloseFd(); + } +}; + +struct FsFileInfos { + std::string srcUri; + std::string destUri; + std::string srcPath; + std::string destPath; + bool isFile = false; + std::chrono::steady_clock::time_point notifyTime; + int32_t notifyFd = -1; + int32_t eventFd = -1; + bool run = true; + bool hasListener = false; + std::shared_ptr listener = nullptr; + std::shared_ptr taskSignal = nullptr; + std::set filePaths; + int exceptionCode = ERRNO_NOERR; // notify copy thread or listener thread has exceptions. + bool operator==(const FsFileInfos &infos) const + { + return (srcUri == infos.srcUri && destUri == infos.destUri); + } + bool operator<(const FsFileInfos &infos) const + { + if (srcUri == infos.srcUri) { + return destUri < infos.destUri; + } + return srcUri < infos.srcUri; + } +}; + +struct FsUvEntry { + std::shared_ptr callback; + std::shared_ptr fileInfos; + uint64_t progressSize = 0; + uint64_t totalSize = 0; + FsUvEntry(const std::shared_ptr &cb, std::shared_ptr fileInfos) + : callback(cb), fileInfos(fileInfos) {} + + explicit FsUvEntry(const std::shared_ptr &cb) : callback(cb) {} +}; + +class CopyCore final { +public: + static FsResult DoCopy(const string &src, const string &dest, std::optional &options); + +private: + // operator of params + static bool ValidOperand(std::string uriStr); + static int CheckOrCreatePath(const std::string &destPath); + static bool ValidParams(const string &src, const string &dest); + + // operator of local listener + static std::shared_ptr RegisterListener(const std::shared_ptr &infos); + static std::shared_ptr GetRegisteredListener(std::shared_ptr infos); + static void UnregisterListener(std::shared_ptr fileInfos); + static int ExecLocal(std::shared_ptr infos, std::shared_ptr callback); + static void CopyComplete(std::shared_ptr infos, std::shared_ptr callback); + static void WaitNotifyFinished(std::shared_ptr callback); + static void ReadNotifyEvent(std::shared_ptr infos); + static void ReadNotifyEventLocked(std::shared_ptr infos, std::shared_ptr callback); + static int SubscribeLocalListener(std::shared_ptr infos, std::shared_ptr callback); + static void OnFileReceive(std::shared_ptr infos); + static void GetNotifyEvent(std::shared_ptr infos); + static void StartNotify(std::shared_ptr infos, std::shared_ptr callback); + static FsUvEntry *GetUVEntry(std::shared_ptr infos); + static void ReceiveComplete(std::shared_ptr entry); + static void CloseNotifyFd(std::shared_ptr infos, std::shared_ptr callback); + static void CloseNotifyFdLocked(std::shared_ptr infos, std::shared_ptr callback); + + // operator of file + static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos); + static tuple GetFileSize(const std::string &path); + static uint64_t GetDirSize(std::shared_ptr infos, std::string path); + static int CopyFile(const string &src, const string &dest, std::shared_ptr infos); + static int MakeDir(const string &path); + static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos); + static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos); + static tuple> CreateFileInfos( + const std::string &srcUri, const std::string &destUri, const std::optional &options); + static int ExecCopy(std::shared_ptr infos); + + // operator of file size + static int UpdateProgressSize(const std::string &filePath, std::shared_ptr receivedInfo, + std::shared_ptr callback); + static tuple HandleProgress( + inotify_event *event, std::shared_ptr infos, std::shared_ptr callback); + static std::shared_ptr GetReceivedInfo(int wd, std::shared_ptr callback); + static bool CheckFileValid(const std::string &filePath, std::shared_ptr infos); + + // operator of uri or path + static bool IsValidUri(const std::string &uri); + static bool IsRemoteUri(const std::string &uri); + static bool IsDirectory(const std::string &path); + static bool IsFile(const std::string &path); + static bool IsMediaUri(const std::string &uriPath); + static std::string ConvertUriToPath(const std::string &uri); + static std::string GetRealPath(const std::string &path); + + static std::recursive_mutex mutex_; + static std::map> callbackMap_; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b5266ae47a864b1b5a4bb848ee9ca59f53a577a --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2025 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 +#include +#include +#include + +#include "copy_core.h" +#include "inotify_mock.h" +#include "mock_progress_listener.h" +#include "poll_mock.h" +#include "unistd_mock.h" +#include "uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CopyCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; + + static const string testDir; + static const string srcDir; + static const string destDir; + static const string srcFile; + static const string destFile; + +private: + // rwxr-xr-x + static constexpr mode_t permission0755 = 0755; + // rw-r--r-- + static constexpr mode_t permission0644 = 0644; +}; + +const string CopyCoreMockTest::testDir = "/data/test/CopyCoreMockTest"; +const string CopyCoreMockTest::srcDir = testDir + "/src"; +const string CopyCoreMockTest::destDir = testDir + "/dest"; +const string CopyCoreMockTest::srcFile = srcDir + "/src.txt"; +const string CopyCoreMockTest::destFile = destDir + "/dest.txt"; + +void CopyCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + mkdir(testDir.c_str(), permission0755); + mkdir(srcDir.c_str(), permission0755); + mkdir(destDir.c_str(), permission0755); + int32_t fd = open(srcFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; + InotifyMock::EnableMock(); + PollMock::EnableMock(); + UnistdMock::EnableMock(); +} + +void CopyCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + int ret = remove(srcFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(srcDir.c_str()); + rmdir(destDir.c_str()); + rmdir(testDir.c_str()); + Uvfs::ins = nullptr; + uvMock = nullptr; + InotifyMock::DisableMock(); + PollMock::DisableMock(); + UnistdMock::DisableMock(); +} + +void CopyCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CopyCoreMockTest::TearDown(void) +{ + CopyCore::callbackMap_.clear(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: CopyCoreMockTest_CopyFile_001 + * @tc.desc: Test function of CopyCore::CopyFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopyFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopyFile_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = CopyCoreMockTest::srcFile; + infos->destPath = CopyCoreMockTest::destFile; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*uvMock, uv_fs_sendfile(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + + auto res = CopyCore::CopyFile(srcFile, destFile, infos); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopyFile_001"; +} + +/** + * @tc.name: CopyCoreMockTest_DoCopy_001 + * @tc.desc: Test function of CopyCore::DoCopy interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_DoCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_DoCopy_001"; + + string srcUri = "file://" + srcFile; + string destUri = "file://" + destFile; + optional options; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*uvMock, uv_fs_sendfile(_, _, _, _, _, _, _)).WillOnce(Return(0)); + + auto res = CopyCore::DoCopy(srcUri, destUri, options); + EXPECT_EQ(res.IsSuccess(), true); + EXPECT_TRUE(filesystem::exists(destFile)); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_DoCopy_001"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_001 + * @tc.desc: Test function of CopyCore::CopySubDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_001"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_002 + * @tc.desc: Test CopyCore::CopySubDir when iter == CopyCore::callbackMap_.end() + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_002"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + CopyCore::callbackMap_.clear(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_002"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_003 + * @tc.desc: Test CopyCore::CopySubDir when iter->second == nullptr + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_003"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + GTEST_LOG_(INFO) << "Open test file failed! ret: " << fd << ", errno: " << errno; + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + CopyCore::callbackMap_[*infos] = nullptr; + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + CopyCore::callbackMap_.clear(); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_003"; +} + +/** + * @tc.name: CopyCoreMockTest_ReceiveComplete_001 + * @tc.desc: Test CopyCore::ReceiveComplete in normal case + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReceiveComplete_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReceiveComplete_001"; + + auto mockListener = std::make_shared(); + auto callback = std::make_shared(mockListener); + callback->maxProgressSize = 50; + auto entry = std::make_shared(callback); + // 当前已经拷贝的字节数 + entry->progressSize = 100; + // 需要拷贝的字节数 + entry->totalSize = 200; + + EXPECT_CALL(*mockListener, InvokeListener(entry->progressSize, entry->totalSize)).Times(1); + CopyCore::ReceiveComplete(entry); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReceiveComplete_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReceiveComplete_002 + * @tc.desc: Test CopyCore::ReceiveComplete when processedSize < entry->callback->maxProgressSize + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReceiveComplete_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReceiveComplete_002"; + + auto mockListener = std::make_shared(); + auto callback = std::make_shared(mockListener); + callback->maxProgressSize = 100; + auto entry = std::make_shared(callback); + entry->progressSize = 50; // Mock valid progressSize + entry->totalSize = 200; // Mock valid totalSize, and progressSize < totalSize + + EXPECT_CALL(*mockListener, InvokeListener(testing::_, testing::_)).Times(0); + CopyCore::ReceiveComplete(entry); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReceiveComplete_002"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_001 + * @tc.desc: Test function of CopyCoreMockTest::ReadNotifyEvent interface for SUCCESS when read valid event data. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_001"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + int32_t len = static_cast(sizeof(struct inotify_event)); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(len)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_002 + * @tc.desc: Test function of CopyCore::ReadNotifyEvent interface for FAILURE when read returns -1. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_002"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, EIO); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_002"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_003 + * @tc.desc: Test function of CopyCore::ReadNotifyEvent interface for SUCCESS when read returns 0 (EOF). + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_003"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, 0); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_003"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEventLocked_001 + * @tc.desc: Test ReadNotifyEventLocked when closed is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEventLocked_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEventLocked_001"; + // Prepare test condition + auto infos = make_shared(); + auto callback = std::make_shared(nullptr); + callback->closed = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + // Do testing + CopyCore::ReadNotifyEventLocked(infos, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(callback->reading); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEventLocked_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEventLocked_002 + * @tc.desc: Test ReadNotifyEventLocked when close after read. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEventLocked_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEventLocked_002"; + // Prepare test condition + auto infos = make_shared(); + auto callback = std::make_shared(nullptr); + callback->closed = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([callback](int fd, void *buf, size_t count) { + errno = EIO; + callback->closed = true; + return 0; + }); + EXPECT_CALL(*unistdMock, close(testing::_)).WillRepeatedly(testing::Return(0)); + // Do testing + CopyCore::ReadNotifyEventLocked(infos, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(callback->closed); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEventLocked_002"; +} + +/** + * @tc.name: CopyCoreMockTest_GetNotifyId_001 + * @tc.desc: Test function of CopyCore::GetNotifyId interface for SUCCESS. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_GetNotifyId_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_GetNotifyId_001"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + infos->exceptionCode = ERRNO_NOERR; + infos->eventFd = 1; + infos->notifyFd = 1; + + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([infos](struct pollfd *fds, nfds_t n, int timeout) { + fds[1].revents = POLLIN; + // Ensure the loop will exit + infos->run = false; + return 1; + }); + // Do testing + CopyCore::GetNotifyEvent(infos); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_NE(callback, nullptr); + EXPECT_FALSE(infos->run); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_GetNotifyId_001"; +} + +/** + * @tc.name: CopyCoreMockTest_GetNotifyId_002 + * @tc.desc: Test function of CopyCore::GetNotifyId interface fails when callback is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_GetNotifyId_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_GetNotifyId_002"; + // Prepare test condition + auto infos = make_shared(); + // Do testing + CopyCore::GetNotifyEvent(infos); + // Verify results + EXPECT_EQ(infos->exceptionCode, EINVAL); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_GetNotifyId_002"; +} + +/** + * @tc.name: CopyCoreMockTest_CreateFileInfos_001 + * @tc.desc: Test function of CopyCore::CreateFileInfos interface with listener and copySignal. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CreateFileInfos_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CreateFileInfos_001"; + + auto copySignal = std::make_shared(); + copySignal->taskSignal_ = std::make_shared(); + auto options = std::make_optional(); + options->progressListener = std::make_shared(); + options->copySignal = std::move(copySignal); + + auto [errCode, infos] = CopyCore::CreateFileInfos(srcFile, destFile, options); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_NE(infos, nullptr); + if (infos) { + EXPECT_TRUE(infos->hasListener); + EXPECT_NE(infos->listener, nullptr); + EXPECT_NE(infos->taskSignal, nullptr); + } + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CreateFileInfos_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..febb6cf12c72123a1b048768464b2685d853e874 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp @@ -0,0 +1,1150 @@ +/* + * Copyright (C) 2025 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 "copy_core.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CopyCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const string testDir; + static const string copyCoreDir; + static const string srcDir; + static const string destDir; + static const string srcFile; + static const string destFile; + +private: + // rwxr-xr-x + static constexpr mode_t permission0755 = 0755; + // rw-r--r-- + static constexpr mode_t permission0644 = 0644; +}; + +const string CopyCoreTest::testDir = "/data/test"; +const string CopyCoreTest::copyCoreDir = testDir + "/CopyCoreTest"; +const string CopyCoreTest::srcDir = copyCoreDir + "/src"; +const string CopyCoreTest::destDir = copyCoreDir + "/dest"; +const string CopyCoreTest::srcFile = srcDir + "/src.txt"; +const string CopyCoreTest::destFile = destDir + "/dest.txt"; + +void CopyCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + mkdir(testDir.c_str(), permission0755); + mkdir(copyCoreDir.c_str(), permission0755); + mkdir(srcDir.c_str(), permission0755); + mkdir(destDir.c_str(), permission0755); + int32_t fd = open(srcFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); +} + +void CopyCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + int ret = remove(srcFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(srcDir.c_str()); + rmdir(destDir.c_str()); + rmdir(testDir.c_str()); +} + +void CopyCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CopyCoreTest::TearDown(void) +{ + CopyCore::callbackMap_.clear(); + GTEST_LOG_(INFO) << "TearDown"; +} + +inline const int32_t EXPECTED_WD = 100; +inline const int32_t UNEXPECTED_WD = 200; + +/** + * @tc.name: CopyCoreTest_IsValidUri_001 + * @tc.desc: Test function of CopyCore::IsValidUri interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsValidUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsValidUri_001"; + + string validUri = "file://data/test/file.txt"; + auto res = CopyCore::IsValidUri(validUri); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsValidUri_001"; +} + +/** + * @tc.name: CopyCoreTest_IsValidUri_002 + * @tc.desc: Test function of CopyCore::IsValidUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsValidUri_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsValidUri_002"; + + string invalidUri = "invalid://data/test/CopyCoreTest_IsValidUri_002/file.txt"; + auto res = CopyCore::IsValidUri(invalidUri); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsValidUri_002"; +} + +/** + * @tc.name: CopyCoreTest_IsRemoteUri_001 + * @tc.desc: Test function of CopyCore::IsRemoteUri interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsRemoteUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsRemoteUri_001"; + + string remoteUri = "file://data/test/file.txt?networkid=123"; + auto res = CopyCore::IsRemoteUri(remoteUri); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsRemoteUri_001"; +} + +/** + * @tc.name: CopyCoreTest_IsRemoteUri_002 + * @tc.desc: Test function of CopyCore::IsRemoteUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsRemoteUri_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsRemoteUri_002"; + + string localUri = "file://data/test/file.txt"; + auto res = CopyCore::IsRemoteUri(localUri); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsRemoteUri_002"; +} + +/** + * @tc.name: CopyCoreTest_IsDirectory_001 + * @tc.desc: Test function of CopyCore::IsDirectory interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsDirectory_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsDirectory_001"; + + auto res = CopyCore::IsDirectory(srcDir); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsDirectory_001"; +} + +/** + * @tc.name: CopyCoreTest_IsDirectory_002 + * @tc.desc: Test function of CopyCore::IsDirectory interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsDirectory_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsDirectory_002"; + + auto res = CopyCore::IsDirectory(srcFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsDirectory_002"; +} + +/** + * @tc.name: CopyCoreTest_IsFile_001 + * @tc.desc: Test function of CopyCore::IsFile interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsFile_001"; + + auto res = CopyCore::IsFile(srcFile); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsFile_001"; +} + +/** + * @tc.name: CopyCoreTest_IsFile_002 + * @tc.desc: Test function of CopyCore::IsFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsFile_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsFile_002"; + + auto res = CopyCore::IsFile(srcDir); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsFile_002"; +} + +/** + * @tc.name: CopyCoreTest_IsMediaUri_001 + * @tc.desc: Test function of CopyCore::IsMediaUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsMediaUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsMediaUri_001"; + + auto res = CopyCore::IsMediaUri(srcFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsMediaUri_001"; +} + +/** + * @tc.name: CopyCoreTest_GetFileSize_001 + * @tc.desc: Test function of CopyCore::GetFileSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetFileSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetFileSize_001"; + + auto [err, size] = CopyCore::GetFileSize(srcFile); + EXPECT_EQ(err, ERRNO_NOERR); + EXPECT_GE(size, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetFileSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetFileSize_002 + * @tc.desc: Test function of CopyCore::GetFileSize interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetFileSize_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetFileSize_002"; + + string nonExistentFile = "/data/test/non_existent.txt"; + auto [err, size] = CopyCore::GetFileSize(nonExistentFile); + EXPECT_NE(err, ERRNO_NOERR); + EXPECT_EQ(size, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetFileSize_002"; +} + +/** + * @tc.name: CopyCoreTest_CheckOrCreatePath_001 + * @tc.desc: Test function of CopyCore::CheckOrCreatePath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckOrCreatePath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckOrCreatePath_001"; + + auto res = CopyCore::CheckOrCreatePath(srcFile); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckOrCreatePath_001"; +} + +/** + * @tc.name: CopyCoreTest_CheckOrCreatePath_002 + * @tc.desc: Test function of CopyCore::CheckOrCreatePath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckOrCreatePath_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckOrCreatePath_002"; + + string newFile = destDir + "/new_file.txt"; + auto res = CopyCore::CheckOrCreatePath(newFile); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsFile(newFile)); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckOrCreatePath_002"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_001 + * @tc.desc: Test function of CopyCore::MakeDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_001"; + + string newDir = destDir + "/new_dir"; + auto res = CopyCore::MakeDir(newDir); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(newDir)); + + rmdir(newDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_001"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_002 + * @tc.desc: Test function of CopyCore::MakeDir interface for TRUE. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_002"; + + auto res = CopyCore::MakeDir(srcDir); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_002"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_003 + * @tc.desc: Test function of CopyCore::MakeDir interface for FALSE. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_003"; + + string invalidPath = "/invalid/path/dir"; + auto res = CopyCore::MakeDir(invalidPath); + EXPECT_NE(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_003"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_001 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_001"; + + string srcFile = "invalid://data/test/src.txt"; + + auto res = CopyCore::ValidParams(srcFile, destFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_001"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_002 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_002"; + + string destFile = "invalid://data/test/dest.txt"; + + auto res = CopyCore::ValidParams(srcFile, destFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_002"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_003 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_003"; + + string src = "file://data/test/src.txt"; + string dest = "file://data/test/dest.txt"; + + auto res = CopyCore::ValidParams(src, dest); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_003"; +} + +/** + * @tc.name: CopyCoreTest_CreateFileInfos_001 + * @tc.desc: Test function of CopyCore::CreateFileInfos interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CreateFileInfos_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CreateFileInfos_001"; + + optional options = std::make_optional(); + + auto [errCode, infos] = CopyCore::CreateFileInfos(srcFile, destFile, options); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_NE(infos, nullptr); + if (infos) { + EXPECT_FALSE(infos->hasListener); + EXPECT_EQ(infos->listener, nullptr); + EXPECT_EQ(infos->taskSignal, nullptr); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CreateFileInfos_001"; +} + +/** + * @tc.name: CopyCoreTest_CopySubDir_001 + * @tc.desc: Test function of CopyCore::CopySubDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopySubDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopySubDir_001"; + + string subDir = srcDir + "/CopyCoreTest_CopySubDir_001_sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + string destSubFile = destSubDir + "/sub_file.txt"; + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(destSubDir)); + EXPECT_TRUE(CopyCore::IsFile(destSubFile)); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopySubDir_001"; +} + +/** + * @tc.name: CopyCoreTest_CopySubDir_002 + * @tc.desc: Test function of CopyCore::CopySubDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopySubDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopySubDir_002"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, errno); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopySubDir_002"; +} + +/** + * @tc.name: CopyCoreTest_RecurCopyDir_001 + * @tc.desc: Test function of CopyCore::RecurCopyDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RecurCopyDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RecurCopyDir_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + auto res = CopyCore::RecurCopyDir(srcDir, destDir, infos); + string destSubFile = destSubDir + "/sub_file.txt"; + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(destSubDir)); + EXPECT_TRUE(CopyCore::IsFile(destSubDir + "/sub_file.txt")); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RecurCopyDir_001"; +} + +/** + * @tc.name: CopyCoreTest_CopyDirFunc_001 + * @tc.desc: Test function of CopyCore::CopyDirFunc interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopyDirFunc_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopyDirFunc_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/src/sub_dir"; + string destSubFile = destSubDir + "/sub_file.txt"; + string destSrcDir = destDir + "/src"; + auto infos = make_shared(); + auto res = CopyCore::CopyDirFunc(srcDir, destDir, infos); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_EQ(CopyCore::IsDirectory(destSubDir), false); + EXPECT_EQ(CopyCore::IsFile(destSubDir + "/sub_file.txt"), false); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + rmdir(destSrcDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopyDirFunc_001"; +} + +/** + * @tc.name: CopyCoreTest_ExecLocal_001 + * @tc.desc: Test function of CopyCore::ExecLocal interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecLocal_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecLocal_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::ExecLocal(infos, callback); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsFile(destFile)); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecLocal_001"; +} + +/** + * @tc.name: CopyCoreTest_ExecLocal_002 + * @tc.desc: Test function of CopyCore::ExecLocal interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecLocal_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecLocal_002"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = srcFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::ExecLocal(infos, callback); + EXPECT_EQ(res, EINVAL); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecLocal_002"; +} + +/** + * @tc.name: CopyCoreTest_RegisterListener_001 + * @tc.desc: Test function of CopyCore::RegisterListener interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RegisterListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RegisterListener_001"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + EXPECT_NE(callback, nullptr); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_NE(iter, CopyCore::callbackMap_.end()); + } + + CopyCore::UnregisterListener(infos); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RegisterListener_001"; +} + +/** + * @tc.name: CopyCoreTest_RegisterListener_002 + * @tc.desc: Test function of CopyCore::RegisterListener interface for the case when the info already exists in + * callbackMap_. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RegisterListener_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RegisterListener_002"; + + auto infos = make_shared(); + auto firstCallback = CopyCore::RegisterListener(infos); + EXPECT_NE(firstCallback, nullptr); + auto secondCallback = CopyCore::RegisterListener(infos); + EXPECT_EQ(secondCallback, nullptr); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_NE(iter, CopyCore::callbackMap_.end()); + } + + CopyCore::UnregisterListener(infos); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RegisterListener_002"; +} + +/** + * @tc.name: CopyCoreTest_UnregisterListener_001 + * @tc.desc: Test function of CopyCore::UnregisterListener interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UnregisterListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UnregisterListener_001"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + EXPECT_NE(callback, nullptr); + + CopyCore::UnregisterListener(infos); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_EQ(iter, CopyCore::callbackMap_.end()); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UnregisterListener_001"; +} + +/** + * @tc.name: CopyCoreTest_UnregisterListener_002 + * @tc.desc: Test function of CopyCore::UnregisterListener interface for the case when the info is not registered in + * callbackMap_. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UnregisterListener_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UnregisterListener_002"; + + auto infos = make_shared(); + + CopyCore::UnregisterListener(infos); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_EQ(iter, CopyCore::callbackMap_.end()); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UnregisterListener_002"; +} + +/** + * @tc.name: CopyCoreTest_DoCopy_001 + * @tc.desc: Test function of CopyCore::DoCopy interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_DoCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_DoCopy_001"; + + string src = "invalid:/" + srcFile; + string dest = "invalid:/" + destFile; + optional options; + + auto res = CopyCore::DoCopy(src, dest, options); + EXPECT_FALSE(res.IsSuccess()); + auto err = res.GetError(); + EXPECT_EQ(err.GetErrNo(), E_PARAMS); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_DoCopy_001"; +} + +/** + * @tc.name: CopyCoreTest_DoCopy_002 + * @tc.desc: Test function of CopyCore::DoCopy interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_DoCopy_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_DoCopy_002"; + + string src = "file:///data/test/src/src.txt"; + string dest = "file:///data/test/dest/dest.txt"; + optional options; + + auto res = CopyCore::DoCopy(src, dest, options); + EXPECT_TRUE(res.IsSuccess()); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_DoCopy_002"; +} + +/** + * @tc.name: CopyCoreTest_GetDirSize_001 + * @tc.desc: Test function of CopyCore::GetDirSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetDirSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetDirSize_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::GetDirSize(infos, srcDir); + EXPECT_EQ(res, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetDirSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetUVEntry_001 + * @tc.desc: Test function of CopyCore::GetUVEntry interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetUVEntry_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetUVEntry_001"; + + auto infos = make_shared(); + auto res = CopyCore::GetUVEntry(infos); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetUVEntry_001"; +} + +/** + * @tc.name: CopyCoreTest_CheckFileValid_001 + * @tc.desc: Test function of CopyCore::CheckFileValid interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckFileValid_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckFileValid_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::CheckFileValid(srcFile, infos); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckFileValid_001"; +} + +/** + * @tc.name: CopyCoreTest_UpdateProgressSize_001 + * @tc.desc: Test function of CopyCore::UpdateProgressSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UpdateProgressSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UpdateProgressSize_001"; + + auto receivedInfo = make_shared(); + auto callback = make_shared(nullptr); + + auto res = CopyCore::UpdateProgressSize(srcFile, receivedInfo, callback); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UpdateProgressSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRegisteredListener_001 + * @tc.desc: Test function of CopyCore::GetRegisteredListener interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRegisteredListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRegisteredListener_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::GetRegisteredListener(infos); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRegisteredListener_001"; +} + +/** + * @tc.name: CopyCoreTest_SubscribeLocalListener_001 + * @tc.desc: Test function of CopyCore::SubscribeLocalListener interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_SubscribeLocalListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_SubscribeLocalListener_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::SubscribeLocalListener(infos, callback); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_SubscribeLocalListener_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRealPath_001 + * @tc.desc: Test function of CopyCore::GetRealPath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRealPath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRealPath_001"; + + string path = "./data/test/src/src.txt"; + + auto res = CopyCore::GetRealPath(path); + EXPECT_EQ(res, "data/test/src/src.txt"); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRealPath_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRealPath_002 + * @tc.desc: Test function of CopyCore::GetRealPath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRealPath_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRealPath_002"; + + string path = "../data/test/src/src.txt"; + + auto res = CopyCore::GetRealPath(path); + EXPECT_EQ(res, "data/test/src/src.txt"); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRealPath_002"; +} + +/** + * @tc.name: CopyCoreTest_ExecCopy_001 + * @tc.desc: Test function of CopyCore::ExecCopy interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecCopy_001"; + + auto infos = make_shared(); + infos->isFile = false; + infos->srcPath = "/data/test/src"; + infos->destPath = "/data/test/dest"; + + auto res = CopyCore::ExecCopy(infos); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecCopy_001"; +} + +/** + * @tc.name: CopyCoreTest_CopyFile_001 + * @tc.desc: Test function of CopyCore::CopyFile interface for file copy FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopyFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopyFile_001"; + + string src = "datashare:///media/src_test.jpg"; + string dest = "datashare:///media/dest_test.jpg"; + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = src; + infos->destPath = dest; + + auto res = CopyCore::CopyFile(src, dest, infos); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopyFile_001"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_001 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_001"; + + auto infos = make_shared(); + infos->isFile = false; + infos->srcPath = "/data/test/src"; + infos->destPath = "/data/test/dest"; + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, nullptr); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, EINVAL); + EXPECT_FALSE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_001"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_002 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_002"; + + auto infos = make_shared(); + infos->srcPath = srcDir; + infos->destPath = destDir; + infos->isFile = true; + + auto callback = make_shared(nullptr); + + auto receiveInfo = make_shared(); + receiveInfo->path = testDir; + callback->wds.push_back({ UNEXPECTED_WD, receiveInfo }); + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, callback); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, EINVAL); + EXPECT_FALSE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_002"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_003 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_003"; + + auto infos = make_shared(); + infos->srcPath = srcDir; + infos->destPath = destDir; + infos->isFile = true; + + auto callback = make_shared(nullptr); + + auto receiveInfo = make_shared(); + receiveInfo->path = srcFile; + callback->wds.push_back({ EXPECTED_WD, receiveInfo }); + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, callback); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_TRUE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_003"; +} + +/** + * @tc.name: CopyCoreTest_OnFileReceive_001 + * @tc.desc: Test function of CopyCore::OnFileReceive interface fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_OnFileReceive_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_OnFileReceive_001"; + + auto infos = make_shared(); + CopyCore::OnFileReceive(infos); + EXPECT_TRUE(CopyCore::callbackMap_.empty()); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_OnFileReceive_001"; +} + +/** + * @tc.name: CopyCoreTest_OnFileReceive_002 + * @tc.desc: Test function of CopyCore::OnFileReceive interface when listener is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_OnFileReceive_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_OnFileReceive_002"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + CopyCore::OnFileReceive(infos); + EXPECT_NE(callback, nullptr); + if (callback) { + EXPECT_EQ(callback->listener, nullptr); + } + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_OnFileReceive_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mode_statvfs/statvfs_core_test.cpp b/interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp similarity index 100% rename from interfaces/test/unittest/js/mode_statvfs/statvfs_core_test.cpp rename to interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp diff --git a/interfaces/test/unittest/task_signal/BUILD.gn b/interfaces/test/unittest/task_signal/BUILD.gn index 2f9900498e80121911e65beaa44b750ca51d02d5..a475b0fffff7fd9a2a72d55eb29602816a2df010 100644 --- a/interfaces/test/unittest/task_signal/BUILD.gn +++ b/interfaces/test/unittest/task_signal/BUILD.gn @@ -35,5 +35,6 @@ ohos_unittest("task_signal_test") { "c_utils:utils", "googletest:gtest_main", "hilog:libhilog", + "ipc:ipc_napi", ] }