diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 97cbc5d2fde65bdce1a3bcc9231e2695f0d0c701..0d00b5f2f486d052cc655c2e9be81308ca53469c 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -716,6 +716,7 @@ ohos_shared_library("ani_file_fs") { "src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp", "src/mod_fs/class_watcher/fs_file_watcher.cpp", "src/mod_fs/class_watcher/fs_watcher.cpp", + "src/mod_fs/class_watcher/watcher_data_cache.cpp", "src/mod_fs/fs_utils.cpp", "src/mod_fs/properties/access_core.cpp", "src/mod_fs/properties/ani/access_ani.cpp", diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp index 24e09e958d69f8ec7383e2a6ffe350e53a79b5d0..9f77d49df39c7e271a3d9ca53d0e9a9b9418a648 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp @@ -28,12 +28,6 @@ namespace OHOS::FileManagement::ModuleFileIO { using namespace std; -mutex FsFileWatcher::watchMutex_; - -FsFileWatcher::FsFileWatcher() {} - -FsFileWatcher::~FsFileWatcher() {} - int32_t FsFileWatcher::GetNotifyId() { return notifyFd_; @@ -54,51 +48,43 @@ bool FsFileWatcher::InitNotify() return true; } -tuple FsFileWatcher::CheckEventWatched(const string &fileName, const uint32_t &event) +int32_t FsFileWatcher::StartNotify(shared_ptr info) { - int32_t wd = -1; - auto iter = wdFileNameMap_.find(fileName); - if (iter == wdFileNameMap_.end()) { - return { false, wd }; + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; } - wd = iter->second.first; - if ((iter->second.second & event) == event) { - return { true, wd }; - } - return { false, wd }; -} -int32_t FsFileWatcher::StartNotify(shared_ptr info) -{ - lock_guard lock(watchMutex_); if (notifyFd_ < 0) { HILOGE("Failed to start notify notifyFd_:%{public}d", notifyFd_); return EIO; } - auto [isWatched, wd] = CheckEventWatched(info->fileName, info->events); + auto [isWatched, wd] = dataCache_.FindWatchedWd(info->fileName, info->events); if (isWatched && wd > 0) { info->wd = wd; return ERRNO_NOERR; } + uint32_t watchEvents = 0; if (wd != -1) { - watchEvents = wdFileNameMap_[info->fileName].second | info->events; + watchEvents = dataCache_.GetFileEvents(info->fileName) | info->events; } else { watchEvents = info->events; } + int32_t newWd = inotify_add_watch(notifyFd_, info->fileName.c_str(), watchEvents); if (newWd < 0) { HILOGE("Failed to start notify errCode:%{public}d", errno); return errno; } + info->wd = newWd; - wdFileNameMap_[info->fileName].first = newWd; - wdFileNameMap_[info->fileName].second = watchEvents; + dataCache_.UpdateWatchedEvents(info->fileName, newWd, watchEvents); return ERRNO_NOERR; } -int32_t FsFileWatcher::NotifyToWatchNewEvents(const string &fileName, const int32_t &wd, const uint32_t &watchEvents) +int32_t FsFileWatcher::NotifyToWatchNewEvents(const string &fileName, int32_t wd, uint32_t watchEvents) { int32_t newWd = inotify_add_watch(notifyFd_, fileName.c_str(), watchEvents); if (newWd < 0) { @@ -110,7 +96,8 @@ int32_t FsFileWatcher::NotifyToWatchNewEvents(const string &fileName, const int3 HILOGE("New notify wd is error"); return EIO; } - wdFileNameMap_[fileName].second = watchEvents; + + dataCache_.UpdateWatchedEvents(fileName, wd, watchEvents); return ERRNO_NOERR; } @@ -118,13 +105,14 @@ int32_t FsFileWatcher::CloseNotifyFd() { int32_t closeRet = ERRNO_NOERR; - if (watcherInfoSet_.size() == 0) { + if (!dataCache_.HasWatcherInfo()) { run_ = false; closeRet = close(notifyFd_); if (closeRet != 0) { HILOGE("Failed to stop notify close fd errCode:%{public}d", errno); } notifyFd_ = -1; + closeRet = close(eventFd_); if (closeRet != 0) { HILOGE("Failed to close eventfd errCode:%{public}d", errno); @@ -137,7 +125,7 @@ int32_t FsFileWatcher::CloseNotifyFd() return closeRet; } -int FsFileWatcher::CloseNotifyFdLocked() +int32_t FsFileWatcher::CloseNotifyFdLocked() { { lock_guard lock(readMutex_); @@ -152,20 +140,28 @@ int FsFileWatcher::CloseNotifyFdLocked() int32_t FsFileWatcher::StopNotify(shared_ptr info) { - unique_lock lock(watchMutex_); + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; + } + if (notifyFd_ < 0) { HILOGE("Failed to stop notify notifyFd_:%{public}d", notifyFd_); return EIO; } - uint32_t newEvents = RemoveWatcherInfo(info); - if (newEvents > 0) { + + uint32_t remainingEvents = RemoveWatcherInfo(info); + if (remainingEvents > 0) { + // There are still events remaining to be listened for. if (access(info->fileName.c_str(), F_OK) == 0) { - return NotifyToWatchNewEvents(info->fileName, info->wd, newEvents); + return NotifyToWatchNewEvents(info->fileName, info->wd, remainingEvents); } HILOGE("The Watched file does not exist, and the remaining monitored events will be invalid."); return ERRNO_NOERR; } - int oldWd = -1; + + // No events remain to be listened for, and proceed to the file watch removal process. + int32_t oldWd = -1; { lock_guard lock(readMutex_); if (!(closed_ && reading_)) { @@ -174,16 +170,18 @@ int32_t FsFileWatcher::StopNotify(shared_ptr info) HILOGE("rm watch fail"); } } + if (oldWd == -1) { - int rmErr = errno; + int32_t rmErr = errno; if (access(info->fileName.c_str(), F_OK) == 0) { HILOGE("Failed to stop notify errCode:%{public}d", rmErr); - wdFileNameMap_.erase(info->fileName); + dataCache_.RemoveFileWatcher(info->fileName); CloseNotifyFdLocked(); return rmErr; } } - wdFileNameMap_.erase(info->fileName); + + dataCache_.RemoveFileWatcher(info->fileName); return CloseNotifyFdLocked(); } @@ -193,6 +191,7 @@ void FsFileWatcher::ReadNotifyEvent() int32_t index = 0; char buf[BUF_SIZE] = { 0 }; struct inotify_event *event = nullptr; + do { len = read(notifyFd_, &buf, sizeof(buf)); if (len < 0 && errno != EINTR) { @@ -200,6 +199,7 @@ void FsFileWatcher::ReadNotifyEvent() break; } } while (len < 0); + while (index < len) { event = reinterpret_cast(buf + index); NotifyEvent(event); @@ -217,7 +217,9 @@ void FsFileWatcher::ReadNotifyEventLocked() } reading_ = true; } + ReadNotifyEvent(); + { lock_guard lock(readMutex_); reading_ = false; @@ -243,95 +245,78 @@ void FsFileWatcher::GetNotifyEvent() if (run_) { return; } + run_ = true; nfds_t nfds = 2; - struct pollfd fds[2]; + struct pollfd fds[2] = { { -1 } }; fds[0].fd = eventFd_; - fds[0].events = 0; + fds[0].events = POLLIN; fds[1].fd = notifyFd_; fds[1].events = POLLIN; int32_t ret = 0; + while (run_) { - ret = poll(fds, nfds, -1); + ret = poll(fds, nfds, pollTimeoutMs); if (ret > 0) { if (static_cast(fds[0].revents) & POLLNVAL) { run_ = false; - return; + break; + } + if (static_cast(fds[0].revents) & POLLIN) { + run_ = false; + break; } if (static_cast(fds[1].revents) & POLLIN) { ReadNotifyEventLocked(); } - } else if (ret < 0 && errno == EINTR) { - continue; - } else { + } else if (ret < 0 && errno != EINTR) { HILOGE("Failed to poll NotifyFd, errno=%{public}d", errno); - return; + break; } + // Ignore cases where poll returns 0 (timeout) or EINTR (interrupted system call) } } -bool FsFileWatcher::AddWatcherInfo(const string &fileName, shared_ptr info) +bool FsFileWatcher::AddWatcherInfo(shared_ptr info) { - for (auto &iter : watcherInfoSet_) { - if (iter->fileName == info->fileName && iter->events == info->events) { - bool isSame = iter->callback->IsStrictEquals(info->callback); - if (isSame) { - HILOGE("Faile to add watcher, fileName:%{public}s the callback is same", fileName.c_str()); - return false; - } - } + if (!info) { + HILOGE("Invalid param: info"); + return false; } - watcherInfoSet_.insert(info); - return true; + return dataCache_.AddWatcherInfo(info); } uint32_t FsFileWatcher::RemoveWatcherInfo(shared_ptr info) { - watcherInfoSet_.erase(info); - uint32_t otherEvents = 0; - for (const auto &iter : watcherInfoSet_) { - if (iter->fileName == info->fileName && iter->wd > 0) { - otherEvents |= iter->events; - } + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; } - return otherEvents; + return dataCache_.RemoveWatcherInfo(info); } -static bool CheckIncludeEvent(const uint32_t &mask, const uint32_t &event) +void FsFileWatcher::NotifyEvent(const struct inotify_event *event) { - if ((mask & event) > 0) { - return true; + if (!event) { + HILOGE("Invalid inotify event"); + return; } - return false; -} -void FsFileWatcher::NotifyEvent(const struct inotify_event *event) -{ - lock_guard lock(watchMutex_); - string tempFileName; - auto found = find_if(wdFileNameMap_.begin(), wdFileNameMap_.end(), - [event](const pair> &iter) { return iter.second.first == event->wd; }); - if (found != wdFileNameMap_.end()) { - tempFileName = found->first; + auto [matched, fileName, watcherInfos] = dataCache_.FindWatcherInfos(event->wd, event->mask); + if (!matched) { + HILOGE("Cannot find matched watcherInfos"); + return; } - for (const auto &iter : watcherInfoSet_) { - string fileName = tempFileName; - uint32_t watchEvent = 0; - if ((iter->fileName == fileName) && (iter->wd > 0)) { - watchEvent = iter->events; - } - if (!CheckIncludeEvent(event->mask, watchEvent)) { - continue; - } + for (const auto &info : watcherInfos) { if (event->len > 0) { fileName += "/" + string(event->name); } - iter->TriggerCallback(fileName, event->mask & IN_ALL_EVENTS, event->cookie); + info->TriggerCallback(fileName, event->mask & IN_ALL_EVENTS, event->cookie); } } -bool FsFileWatcher::CheckEventValid(const uint32_t &event) +bool FsFileWatcher::CheckEventValid(uint32_t event) { if ((event & IN_ALL_EVENTS) == event) { return true; @@ -344,12 +329,20 @@ bool FsFileWatcher::CheckEventValid(const uint32_t &event) void FsFileWatcher::DestroyTaskThead() { if (taskThead_.joinable()) { - taskThead_.join(); + if (taskThead_.get_id() != std::this_thread::get_id()) { + taskThead_.join(); + } else { + taskThead_.detach(); + } } - lock_guard lock(taskMutex_); - if (taskRunning_) { - taskRunning_ = false; + { + lock_guard lock(taskMutex_); + if (taskRunning_) { + taskRunning_ = false; + run_ = false; + } } + dataCache_.ClearCache(); } } // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h index 17be3a40a699c0077df52cc16e08aa927bb44145..57b83d3319f938baffee83d9834144eb3024719f 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h @@ -18,46 +18,48 @@ #include #include #include -#include -#include #include #include "filemgmt_libfs.h" #include "fs_watch_entity.h" #include "singleton.h" +#include "watcher_data_cache.h" namespace OHOS::FileManagement::ModuleFileIO { using namespace std; -constexpr int BUF_SIZE = 1024; +constexpr int32_t BUF_SIZE = 1024; class FsFileWatcher : public Singleton { public: - FsFileWatcher(); - ~FsFileWatcher(); int32_t GetNotifyId(); bool InitNotify(); - int StartNotify(shared_ptr info); - int StopNotify(shared_ptr info); + int32_t StartNotify(shared_ptr info); + int32_t StopNotify(shared_ptr info); void GetNotifyEvent(); void AsyncGetNotifyEvent(); - bool AddWatcherInfo(const string &fileName, shared_ptr info); - bool CheckEventValid(const uint32_t &event); + bool AddWatcherInfo(shared_ptr info); + bool CheckEventValid(uint32_t event); + +public: + FsFileWatcher() = default; + ~FsFileWatcher() = default; + FsFileWatcher(const FsFileWatcher &) = delete; + FsFileWatcher &operator=(const FsFileWatcher &) = delete; private: uint32_t RemoveWatcherInfo(shared_ptr info); - tuple CheckEventWatched(const string &fileName, const uint32_t &event); void NotifyEvent(const struct inotify_event *event); - int CloseNotifyFd(); - int CloseNotifyFdLocked(); - int NotifyToWatchNewEvents(const string &fileName, const int &wd, const uint32_t &watchEvents); + int32_t CloseNotifyFd(); + int32_t CloseNotifyFdLocked(); + int32_t NotifyToWatchNewEvents(const string &fileName, int32_t wd, uint32_t watchEvents); void ReadNotifyEvent(); void ReadNotifyEventLocked(); void DestroyTaskThead(); private: - static mutex watchMutex_; + static constexpr int32_t pollTimeoutMs = 500; mutex taskMutex_; mutex readMutex_; @@ -70,11 +72,7 @@ private: bool closed_ = false; int32_t notifyFd_ = -1; int32_t eventFd_ = -1; - unordered_set> watcherInfoSet_; - unordered_map> wdFileNameMap_; - - FsFileWatcher(const FsFileWatcher &) = delete; - FsFileWatcher &operator=(const FsFileWatcher &) = delete; + WatcherDataCache dataCache_; }; } // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83b5e2a51d734de7f54b020ef54e0bbffa608ae0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp @@ -0,0 +1,162 @@ +/* + * 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 "watcher_data_cache.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +bool WatcherDataCache::AddWatcherInfo(std::shared_ptr info) +{ + std::lock_guard lock(cacheMutex_); + for (auto &iter : watcherInfoCache_) { + if (iter->fileName == info->fileName && iter->events == info->events) { + bool isSame = iter->callback->IsStrictEquals(info->callback); + if (isSame) { + HILOGE("Failed to add watcher, fileName:%{private}s the callback is same", info->fileName.c_str()); + return false; + } + } + } + watcherInfoCache_.push_back(info); + wdFileNameCache_[info->fileName] = std::make_pair(info->wd, info->events); + return true; +} + +uint32_t WatcherDataCache::RemoveWatcherInfo(std::shared_ptr info) +{ + std::lock_guard lock(cacheMutex_); + auto it = std::find(watcherInfoCache_.begin(), watcherInfoCache_.end(), info); + if (it != watcherInfoCache_.end()) { + watcherInfoCache_.erase(it); + } + + uint32_t remainingEvents = 0; + for (const auto &iter : watcherInfoCache_) { + if (iter->fileName == info->fileName && iter->wd > 0) { + remainingEvents |= iter->events; + } + } + + return remainingEvents; +} + +bool WatcherDataCache::RemoveFileWatcher(const std::string &fileName) +{ + std::lock_guard lock(cacheMutex_); + + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return false; + } + wdFileNameCache_.erase(iter); + + watcherInfoCache_.erase(std::remove_if(watcherInfoCache_.begin(), watcherInfoCache_.end(), + [&fileName](const std::shared_ptr &info) { + return info->fileName == fileName; + }), watcherInfoCache_.end()); + + return true; +} + +std::tuple WatcherDataCache::FindWatchedWd(const std::string &fileName, uint32_t event) +{ + std::lock_guard lock(cacheMutex_); + + int32_t wd = -1; + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return { false, wd }; + } + + wd = iter->second.first; + if ((iter->second.second & event) == event) { + return { true, wd }; + } + + return { false, wd }; +} + +bool WatcherDataCache::UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events) +{ + std::lock_guard lock(cacheMutex_); + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return false; + } + + iter->second = std::make_pair(wd, events); + return true; +} + +static bool CheckIncludeEvent(uint32_t mask, uint32_t event) +{ + return (mask & event) > 0; +} + +std::tuple>> WatcherDataCache::FindWatcherInfos( + int32_t wd, uint32_t eventMask) +{ + std::lock_guard lock(cacheMutex_); + std::string fileName; + bool found = false; + for (const auto &[key, val] : wdFileNameCache_) { + if (val.first == wd) { + fileName = key; + found = true; + break; + } + } + + if (!found) { + return { false, "", {} }; + } + + std::vector> matchedInfos; + for (const auto &info : watcherInfoCache_) { + uint32_t watchEvent = 0; + if ((info->fileName == fileName) && (info->wd > 0)) { + watchEvent = info->events; + } + if (CheckIncludeEvent(eventMask, watchEvent)) { + matchedInfos.push_back(info); + } + } + return { !matchedInfos.empty(), fileName, matchedInfos }; +} + +uint32_t WatcherDataCache::GetFileEvents(const std::string &fileName) +{ + std::lock_guard lock(cacheMutex_); + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return 0; + } + return iter->second.second; +} + +bool WatcherDataCache::HasWatcherInfo() const +{ + std::lock_guard lock(cacheMutex_); + return !watcherInfoCache_.empty(); +} + +void WatcherDataCache::ClearCache() +{ + std::lock_guard lock(cacheMutex_); + watcherInfoCache_.clear(); + wdFileNameCache_.clear(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..e18d584f1ce7dc0c7814157e638e240724599d81 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h @@ -0,0 +1,54 @@ +/* + * 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_CLASS_WATCHER_WATCHER_DATA_CACHE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_WATCHER_DATA_CACHE_H + +#include +#include +#include +#include +#include + +#include "fs_watch_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +class WatcherDataCache { +public: + bool AddWatcherInfo(std::shared_ptr info); + uint32_t RemoveWatcherInfo(std::shared_ptr info); + bool RemoveFileWatcher(const std::string &fileName); + std::tuple FindWatchedWd(const std::string &fileName, uint32_t event); + bool UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events); + std::tuple>> FindWatcherInfos( + int32_t wd, uint32_t eventMask); + uint32_t GetFileEvents(const std::string &fileName); + bool HasWatcherInfo() const; + void ClearCache(); + +public: + WatcherDataCache() = default; + ~WatcherDataCache() = default; + WatcherDataCache(const WatcherDataCache &) = delete; + WatcherDataCache &operator=(const WatcherDataCache &) = delete; + +private: + mutable std::mutex cacheMutex_; + std::vector> watcherInfoCache_; + std::unordered_map> wdFileNameCache_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_WATCHER_DATA_CACHE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp index 382f494ec67385ce04a25f7bd2d66e0be80403c8..1ea4a713a55989c1340331c6c47ef623c5a57711 100644 --- a/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp @@ -98,7 +98,7 @@ FsResult WatcherCore::DoCreateWatcher( watchEntity->data_ = info; - bool ret = FsFileWatcher::GetInstance().AddWatcherInfo(info->fileName, info); + bool ret = FsFileWatcher::GetInstance().AddWatcherInfo(info); if (!ret) { HILOGE("Failed to add watcher info."); return FsResult::Error(EINVAL); diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn index f3acdf930a13c888d0cf0697489a24bff570b8a7..71d82ce8fcd7c1b6a504de8d9dbc66c29e04e0c7 100644 --- a/interfaces/test/unittest/js/BUILD.gn +++ b/interfaces/test/unittest/js/BUILD.gn @@ -89,10 +89,10 @@ ohos_unittest("ani_file_fs_test") { "mod_fs/properties/dup_core_test.cpp", "mod_fs/properties/fdopen_stream_core_test.cpp", "mod_fs/properties/listfile_core_test.cpp", - "mod_fs/properties/read_core_test.cpp", - "mod_fs/properties/read_lines_core_test.cpp", "mod_fs/properties/lstat_core_test.cpp", "mod_fs/properties/open_core_test.cpp", + "mod_fs/properties/read_core_test.cpp", + "mod_fs/properties/read_lines_core_test.cpp", "mod_fs/properties/read_text_core_test.cpp", "mod_fs/properties/rmdir_core_test.cpp", "mod_fs/properties/truncate_core_test.cpp", @@ -102,12 +102,12 @@ ohos_unittest("ani_file_fs_test") { ] deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_fs", "${file_api_path}/interfaces/kits/native:remote_uri_native", "${file_api_path}/interfaces/kits/native:task_signal_native", "${file_api_path}/interfaces/kits/rust:rust_file", "${utils_path}/filemgmt_libfs:filemgmt_libfs", "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${file_api_path}/interfaces/kits/js:ani_file_fs", ] external_deps = [ @@ -120,9 +120,7 @@ ohos_unittest("ani_file_fs_test") { "libuv:uv", ] - defines = [ - "private=public", - ] + defines = [ "private=public" ] } ohos_unittest("ani_file_fs_mock_test") { @@ -138,8 +136,11 @@ ohos_unittest("ani_file_fs_mock_test") { "${file_api_path}/interfaces/kits/js/src/mod_fs/class_readeriterator", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", "${file_api_path}/interfaces/test/unittest/js/mod_fs/class_stream/mock", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/common", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/mock", "${file_api_path}/interfaces/test/unittest/js/mod_fs/properties/mock", ] @@ -149,30 +150,37 @@ ohos_unittest("ani_file_fs_mock_test") { "mod_fs/class_stat/fs_stat_mock_test.cpp", "mod_fs/class_stream/fs_stream_mock_test.cpp", "mod_fs/class_stream/mock/c_mock.cpp", + "mod_fs/class_watcher/fs_file_watcher_mock_test.cpp", + "mod_fs/class_watcher/fs_watcher_mock_test.cpp", + "mod_fs/mock/eventfd_mock.cpp", + "mod_fs/mock/inotify_mock.cpp", + "mod_fs/mock/poll_mock.cpp", + "mod_fs/mock/unistd_mock.cpp", "mod_fs/properties/access_core_mock_test.cpp", "mod_fs/properties/create_randomaccessfile_core_mock_test.cpp", "mod_fs/properties/dup_core_mock_test.cpp", "mod_fs/properties/fdatasync_core_mock_test.cpp", - "mod_fs/properties/read_core_mock_test.cpp", - "mod_fs/properties/read_lines_core_mock_test.cpp", - "mod_fs/properties/symlink_core_mock_test.cpp", - "mod_fs/properties/truncate_core_mock_test.cpp", - "mod_fs/properties/utimes_core_mock_test.cpp", "mod_fs/properties/lstat_core_mock_test.cpp", "mod_fs/properties/mock/system_mock.cpp", "mod_fs/properties/mock/uv_fs_mock.cpp", "mod_fs/properties/open_core_mock_test.cpp", + "mod_fs/properties/read_core_mock_test.cpp", + "mod_fs/properties/read_lines_core_mock_test.cpp", + "mod_fs/properties/symlink_core_mock_test.cpp", + "mod_fs/properties/truncate_core_mock_test.cpp", "mod_fs/properties/unlink_core_mock_test.cpp", + "mod_fs/properties/utimes_core_mock_test.cpp", + "mod_fs/properties/watcher_core_mock_test.cpp", "mod_fs/properties/xattr_core_mock_test.cpp", ] deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_fs", "${file_api_path}/interfaces/kits/native:remote_uri_native", "${file_api_path}/interfaces/kits/native:task_signal_native", "${file_api_path}/interfaces/kits/rust:rust_file", "${utils_path}/filemgmt_libfs:filemgmt_libfs", "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${file_api_path}/interfaces/kits/js:ani_file_fs", ] external_deps = [ @@ -186,9 +194,7 @@ ohos_unittest("ani_file_fs_mock_test") { "libuv:uv", ] - defines = [ - "private=public", - ] + defines = [ "private=public" ] } ohos_unittest("ani_file_hash_test") { @@ -196,9 +202,7 @@ ohos_unittest("ani_file_hash_test") { resource_config_file = "../resource/ohos_test.xml" - sources = [ - "mod_hash/hash_core_test.cpp", - ] + sources = [ "mod_hash/hash_core_test.cpp" ] include_dirs = [ "mock/libuv", @@ -206,17 +210,17 @@ ohos_unittest("ani_file_hash_test") { ] deps = [ - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${utils_path}/filemgmt_libfs:filemgmt_libfs", "${file_api_path}/interfaces/kits/js:ani_file_hash", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", ] external_deps = [ "c_utils:utils", - "hilog:libhilog", - "libuv:uv", "googletest:gmock_main", "googletest:gtest_main", + "hilog:libhilog", + "libuv:uv", ] } @@ -225,9 +229,7 @@ ohos_unittest("ani_file_securitylabel_test") { resource_config_file = "../resource/ohos_test.xml" - sources = [ - "mod_securitylabel/securitylabel_core_test.cpp", - ] + sources = [ "mod_securitylabel/securitylabel_core_test.cpp" ] include_dirs = [ "mock/libuv", @@ -236,16 +238,16 @@ ohos_unittest("ani_file_securitylabel_test") { deps = [ "${file_api_path}/interfaces/kits/js:ani_file_securitylabel", - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", ] external_deps = [ "c_utils:utils", - "hilog:libhilog", - "libuv:uv", "googletest:gmock_main", "googletest:gtest_main", + "hilog:libhilog", + "libuv:uv", ] } @@ -254,9 +256,7 @@ ohos_unittest("ani_file_statvfs_test") { resource_config_file = "../resource/ohos_test.xml" - sources = [ - "mod_statvfs/statvfs_core_test.cpp", - ] + sources = [ "mod_statvfs/statvfs_core_test.cpp" ] include_dirs = [ "mock/libuv", @@ -276,4 +276,4 @@ ohos_unittest("ani_file_statvfs_test") { "hilog:libhilog", "libuv:uv", ] -} \ No newline at end of file +} diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adf4db15e9e500584d345e1286c7da18dccede51 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp @@ -0,0 +1,1163 @@ +/* + * 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 "eventfd_mock.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" +#include "inotify_mock.h" +#include "mock_watcher_callback.h" +#include "poll_mock.h" +#include "securec.h" +#include "unistd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class FsFileWatcherMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsFileWatcherMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsFileWatcherMockTest::TearDownTestCase(void) +{ + EventfdMock::DestroyMock(); + InotifyMock::DestroyMock(); + PollMock::DestroyMock(); + UnistdMock::DestroyMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsFileWatcherMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void FsFileWatcherMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyId_001 + * @tc.desc: Test function of FsFileWatcher::GetNotifyId interface. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyId_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyId_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + int32_t expected = -1; + // Do testing + int32_t result = watcher.GetNotifyId(); + // Verify results + EXPECT_EQ(result, expected); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyId_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_001 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto eventfdMock = EventfdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::Return(2)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result); + EXPECT_EQ(watcher.notifyFd_, 1); + EXPECT_EQ(watcher.eventFd_, 2); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_002 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when inotify_init fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_003 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when eventfd fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto eventfdMock = EventfdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, 1); + EXPECT_EQ(watcher.eventFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_001 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS when path is not watched. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_001"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StartNotify_001"; + info->events = IN_CREATE | IN_DELETE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + // Set mock behaviors + int32_t expectedWd = 100; + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(expectedWd)); + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + EXPECT_EQ(info->wd, expectedWd); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_002 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS when path is already watched with same + * events. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_002"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StartNotify_002"; + info->events = IN_CREATE | IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).Times(0); + // Do testing + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + int32_t result = watcher.StartNotify(info); + // Verify results + EXPECT_EQ(result, ERRNO_NOERR); + EXPECT_EQ(info->wd, expectedWd); +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_003 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when info is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing with nullptr parameter + int32_t result = watcher.StartNotify(nullptr); + // Verify results + EXPECT_EQ(result, EINVAL); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_004 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when notifyFd_ is invalid. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_004"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Build test parameters + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StartNotify_004"; + info->events = IN_CREATE; + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_005 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when inotify_add_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_005"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + // Build test parameters + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StartNotify_005"; + info->events = IN_DELETE; + // Set mock behaviors for inotify_add_watch failure + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_001 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_001"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_001"; + info->events = IN_CREATE | IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_002 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when info is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + int32_t result = watcher.StopNotify(nullptr); + // Verify results + EXPECT_EQ(result, EINVAL); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_003 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when notifyFd_ is invalid. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_003"; + info->events = IN_CREATE; + info->wd = expectedWd; + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_004 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when inotify_rm_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_004"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_004"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_005 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when rm watch fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_005"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_005"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set rm watch fail condition + watcher.closed_ = true; + watcher.reading_ = true; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_006 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when having remainingEvents but access + * file failed. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_006"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_006"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "/test/FsFileWatcherMockTest_StopNotify_006"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = expectedWd; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_006"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_007 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when having remainingEvents and + * NotifyToWatchNewEvents success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_007"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_007"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "/test/FsFileWatcherMockTest_StopNotify_007"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = expectedWd; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(expectedWd)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_007"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_008 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when having remainingEvents but + * NotifyToWatchNewEvents fails for inotify_add_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_008"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_008"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "/test/FsFileWatcherMockTest_StopNotify_008"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = expectedWd; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_008"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_009 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when having remainingEvents but + * NotifyToWatchNewEvents fails for inotify_add_watch return another wd. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_009"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_009"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "/test/FsFileWatcherMockTest_StopNotify_009"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = expectedWd; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + int32_t unexpectedWd = 200; + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(unexpectedWd)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_009"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_010 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when CloseNotifyFd fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_010"; + // Prepare test parameters + int32_t expectedWd = 100; + auto info = std::make_shared(nullptr); + info->fileName = "/test/FsFileWatcherMockTest_StopNotify_010"; + info->events = IN_DELETE; + info->wd = expectedWd; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.eventFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(EIO)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + EXPECT_EQ(watcher.notifyFd_, -1); + EXPECT_EQ(watcher.eventFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_010"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when run_ is true. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[0].revents has + * POLLNVAL. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([](struct pollfd *fds, nfds_t n, int timeout) { + fds[0].revents = POLLNVAL; + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[0].revents has + * POLLIN. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([](struct pollfd *fds, nfds_t n, int timeout) { + fds[0].revents = POLLIN; + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_004 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[1].revents has + * POLLIN. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_004"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + watcher.closed_ = true; // Avoid calling ReadNotifyEvent + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + fds[1].revents = POLLIN; + watcher.run_ = false; // Ensure the loop will exit + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_005 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret == 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_005"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + watcher.run_ = false; // Ensure the loop will exit + return 0; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_006 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret < 0 and errno == EINTR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_006"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + errno = EINTR; + watcher.run_ = false; // Ensure the loop will exit + return -1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_006"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_007 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret < 0 and errno != EINTR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_007"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + errno = EIO; + watcher.run_ = false; // Ensure the loop will exit + return -1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_007"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEventLocked_001 + * @tc.desc: Test ReadNotifyEventLocked when closed_ is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEventLocked_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEventLocked_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.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 + watcher.ReadNotifyEventLocked(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.reading_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEventLocked_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEventLocked_002 + * @tc.desc: Test ReadNotifyEventLocked when close after read. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEventLocked_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEventLocked_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.closed_ = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](int fd, void *buf, size_t count) { + errno = EIO; + watcher.closed_ = true; // Set close after read condition + return 0; + }); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + watcher.ReadNotifyEventLocked(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.closed_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEventLocked_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for SUCCESS when read valid event data. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + 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 + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for FAILURE when read returns -1. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for SUCCESS when read returns 0 (EOF). + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, 0); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for SUCCESS when valid event without filename. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_001"; + // Prepare test parameters + int32_t expectedWd = 100; + uint32_t mask = IN_CREATE; + struct inotify_event event = { .wd = expectedWd, .mask = mask, .cookie = 0, .len = 0 }; + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "/test/FsFileWatcherMockTest_NotifyEvent_001"; + info->events = mask; + info->wd = expectedWd; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); + // Do testing + watcher.NotifyEvent(&event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for SUCCESS when valid event with filename. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_002"; + // Prepare test parameters + int32_t expectedWd = 100; + const char *name = "test.txt"; + size_t len = strlen(name); + uint32_t mask = IN_CREATE; + size_t totalSize = sizeof(struct inotify_event) + len + 1; + std::vector buffer(totalSize); + struct inotify_event *event = reinterpret_cast(buffer.data()); + event->wd = expectedWd; + event->mask = mask; + event->cookie = 0; + event->len = len + 1; + char *namePtr = reinterpret_cast(event + 1); + int ret = memcpy_s(namePtr, len + 1, name, len + 1); + if (ret != 0) { + EXPECT_EQ(ret, 0); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_002"; + return; + } + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "/test/FsFileWatcherMockTest_NotifyEvent_002"; + info->events = mask; + info->wd = expectedWd; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); + // Do testing + watcher.NotifyEvent(event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for FAILURE when event pointer is NULL. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + watcher.NotifyEvent(nullptr); + // Verify results + EXPECT_TRUE(watcher.dataCache_.wdFileNameCache_.empty()); + EXPECT_TRUE(watcher.dataCache_.watcherInfoCache_.empty()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_004 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for FAILURE when no matched watcher found. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_004"; + // Prepare test parameters + int32_t expectedWd = 100; + int32_t unexpectedWd = 200; + struct inotify_event event = { .wd = expectedWd, .mask = IN_CREATE, .cookie = 0, .len = 0 }; + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "/test/FsFileWatcherMockTest_NotifyEvent_004"; + info->events = IN_MODIFY; // Not matched mask + info->wd = unexpectedWd; // Not matched wd + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.NotifyEvent(&event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + EXPECT_FALSE(watcher.dataCache_.wdFileNameCache_.empty()); + EXPECT_FALSE(watcher.dataCache_.watcherInfoCache_.empty()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_004"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74a74b8091d2584bc5e6c3effd3b337a349110ff --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp @@ -0,0 +1,264 @@ +/* + * 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 "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_err_code.h" +#include "fs_file_watcher.h" +#include "fs_watcher.h" +#include "inotify_mock.h" +#include "unistd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class FsWatcherMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsWatcherMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsWatcherMockTest::TearDownTestCase(void) +{ + InotifyMock::DestroyMock(); + UnistdMock::DestroyMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsWatcherMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void FsWatcherMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsWatcherTest_Constructor_001 + * @tc.desc: Test function of FsWatcher::Constructor interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Constructor_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Constructor_001"; + // Do testing + auto result = FsWatcher::Constructor(); + // Verify results + EXPECT_TRUE(result.IsSuccess()); + auto *watcher = result.GetData().value(); + EXPECT_NE(watcher, nullptr); + if (watcher) { + auto *watcherEntity = watcher->GetWatchEntity(); + EXPECT_NE(watcherEntity, nullptr); + } + delete watcher; + watcher = nullptr; + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Constructor_001"; +} + +/** + * @tc.name: FsWatcherTest_Start_001 + * @tc.desc: Test function of FsWatcher::Start interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_001"; + // Prepare test condition + int32_t expectedWd = 100; + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.taskRunning_ = true; // Avoid starting thread + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(expectedWd)); + // Do testing + auto result = fsWatcher.Start(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_001"; +} + +/** + * @tc.name: FsWatcherTest_Start_002 + * @tc.desc: Test function of FsWatcher::Start interface for FAILURE when watchEntity is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_002"; + // Prepare test condition + FsWatcher fsWatcher(nullptr); + // Do testing + auto result = fsWatcher.Start(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_INVAL_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_002"; +} + +/** + * @tc.name: FsWatcherTest_Start_003 + * @tc.desc: Test function of FsWatcher::Start interface for FAILURE when StartNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_003"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Do testing + auto result = fsWatcher.Start(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_IO_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_003"; +} + +/** + * @tc.name: FsWatcherTest_Stop_001 + * @tc.desc: Test function of FsWatcher::Stop interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_001"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_001"; +} + +/** + * @tc.name: FsWatcherTest_Stop_002 + * @tc.desc: Test function of FsWatcher::Stop interface for FAILURE when watchEntity is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_002"; + // Prepare test condition + FsWatcher fsWatcher(nullptr); + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_INVAL_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_002"; +} + +/** + * @tc.name: FsWatcherTest_Stop_003 + * @tc.desc: Test function of FsWatcher::Stop interface for FAILURE when StopNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_003"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_IO_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_003"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h b/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h new file mode 100644 index 0000000000000000000000000000000000000000..7e8a4cbbdc2423d73cdad3d0b6a8d0063fb7c6c9 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h @@ -0,0 +1,34 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +enum FsErrCode { + E_IO_CODE = 13900005, + E_INVAL_CODE = 13900020, +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3406f521c830900569ad672564322e394bf0fc3d --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp @@ -0,0 +1,51 @@ +/* + * 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 "eventfd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr EventfdMock::eventfdMock = nullptr; + +std::shared_ptr EventfdMock::GetMock() +{ + if (eventfdMock == nullptr) { + eventfdMock = std::make_shared(); + } + return eventfdMock; +} + +void EventfdMock::DestroyMock() +{ + eventfdMock = nullptr; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int eventfd(unsigned int count, int flags) +{ + return EventfdMock::GetMock()->eventfd(count, flags); +} + +} // extern "C" \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..e1bbd820deb46fe8f901c478dc067f79e293db4b --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h @@ -0,0 +1,50 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IEventfdMock { +public: + virtual ~IEventfdMock() = default; + virtual int eventfd(unsigned int, int) = 0; +}; + +class EventfdMock : public IEventfdMock { +public: + MOCK_METHOD(int, eventfd, (unsigned int, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void DestroyMock(); + +private: + static thread_local std::shared_ptr eventfdMock; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c4deb01a2667e8526e092274e1b6c86cbb2ed81 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp @@ -0,0 +1,61 @@ +/* + * 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 "inotify_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr InotifyMock::inotifyMock = nullptr; + +std::shared_ptr InotifyMock::GetMock() +{ + if (inotifyMock == nullptr) { + inotifyMock = std::make_shared(); + } + return inotifyMock; +} + +void InotifyMock::DestroyMock() +{ + inotifyMock = nullptr; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int inotify_init() +{ + return InotifyMock::GetMock()->inotify_init(); +} + +int inotify_add_watch(int fd, const char *pathname, uint32_t mask) +{ + return InotifyMock::GetMock()->inotify_add_watch(fd, pathname, mask); +} + +int inotify_rm_watch(int fd, int wd) +{ + return InotifyMock::GetMock()->inotify_rm_watch(fd, wd); +} + +} // extern "C" \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..188f63a2814a5c46211d874fe86dc0c4135a72ec --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h @@ -0,0 +1,54 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IInotifyMock { +public: + virtual ~IInotifyMock() = default; + virtual int inotify_init() = 0; + virtual int inotify_add_watch(int, const char *, uint32_t) = 0; + virtual int inotify_rm_watch(int, int) = 0; +}; + +class InotifyMock : public IInotifyMock { +public: + MOCK_METHOD(int, inotify_init, (), (override)); + MOCK_METHOD(int, inotify_add_watch, (int, const char *, uint32_t), (override)); + MOCK_METHOD(int, inotify_rm_watch, (int, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void DestroyMock(); + +private: + static thread_local std::shared_ptr inotifyMock; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h b/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h new file mode 100644 index 0000000000000000000000000000000000000000..c1004d84f5ee144130ba40352c7c7a4d4e747ede --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h @@ -0,0 +1,41 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H + +#include +#include +#include "i_watcher_callback.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace OHOS::FileManagement::ModuleFileIO; + +class MockWatcherCallback : public IWatcherCallback { +public: + MOCK_METHOD(bool, IsStrictEquals, (const std::shared_ptr &other), (const, override)); + MOCK_METHOD( + void, InvokeCallback, (const std::string &fileName, uint32_t event, uint32_t cookie), (const, override)); + MOCK_METHOD(std::string, GetClassName, (), (const, override)); +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa66cf0552223b4e80436e1e83c790c722724530 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp @@ -0,0 +1,51 @@ +/* + * 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 "poll_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr PollMock::pollMock = nullptr; + +std::shared_ptr PollMock::GetMock() +{ + if (pollMock == nullptr) { + pollMock = std::make_shared(); + } + return pollMock; +} + +void PollMock::DestroyMock() +{ + pollMock = nullptr; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int poll(struct pollfd *fds, nfds_t n, int timeout) +{ + return PollMock::GetMock()->poll(fds, n, timeout); +} + +} // extern "C" \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..0dd0057108e19365d0a1026d182c1871f420aee3 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h @@ -0,0 +1,50 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IPollMock { +public: + virtual ~IPollMock() = default; + virtual int poll(struct pollfd *, nfds_t, int) = 0; +}; + +class PollMock : public IPollMock { +public: + MOCK_METHOD(int, poll, (struct pollfd *, nfds_t, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void DestroyMock(); + +private: + static thread_local std::shared_ptr pollMock; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb646967bb0b488f17ad9dff5a09ea3f82b8d9da --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp @@ -0,0 +1,61 @@ +/* + * 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 "unistd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr UnistdMock::unistdMock = nullptr; + +std::shared_ptr UnistdMock::GetMock() +{ + if (unistdMock == nullptr) { + unistdMock = std::make_shared(); + } + return unistdMock; +} + +void UnistdMock::DestroyMock() +{ + unistdMock = nullptr; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int access(const char *filename, int amode) +{ + return UnistdMock::GetMock()->access(filename, amode); +} + +int close(int fd) +{ + return UnistdMock::GetMock()->close(fd); +} + +ssize_t read(int fd, void *buf, size_t count) +{ + return UnistdMock::GetMock()->read(fd, buf, count); +} + +} // extern "C" \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..37dc6d5cf2d017c0b268a5787d2264d1e760cb72 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h @@ -0,0 +1,54 @@ +/* + * 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_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IUnistdMock { +public: + virtual ~IUnistdMock() = default; + virtual int access(const char *, int) = 0; + virtual int close(int) = 0; + virtual ssize_t read(int, void *, size_t) = 0; +}; + +class UnistdMock : public IUnistdMock { +public: + MOCK_METHOD(int, access, (const char *, int), (override)); + MOCK_METHOD(int, close, (int), (override)); + MOCK_METHOD(ssize_t, read, (int, void *, size_t), (override)); + +public: + static std::shared_ptr GetMock(); + static void DestroyMock(); + +private: + static thread_local std::shared_ptr unistdMock; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H diff --git a/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp index 33f25f3cdd2782d35a5bd416a935aa96cc11aea2..9463f6399e76ab13b56e84993fc9ec599abf39e6 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp @@ -13,14 +13,15 @@ * limitations under the License. */ -#include "mock/uv_fs_mock.h" -#include "open_core.h" - #include #include #include #include +#include "mock/uv_fs_mock.h" +#include "open_core.h" +#include "unistd_mock.h" + namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; using namespace testing::ext; @@ -32,6 +33,8 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + +private: static inline shared_ptr uvMock = nullptr; }; @@ -47,6 +50,7 @@ void OpenCoreMockTest::TearDownTestCase(void) GTEST_LOG_(INFO) << "TearDownTestCase"; Uvfs::ins = nullptr; uvMock = nullptr; + UnistdMock::DestroyMock(); } void OpenCoreMockTest::SetUp(void) @@ -70,9 +74,9 @@ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_001, testing::ext::TestSize.L { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_001"; - string path = "/test/open_test.txt"; + string path = "/test/OpenCoreMockTest_DoOpen_001"; int32_t mode = 0; - + EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(0)); auto res = OpenCore::DoOpen(path, mode); EXPECT_EQ(res.IsSuccess(), true); @@ -91,11 +95,15 @@ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_002, testing::ext::TestSize.L { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_002"; - string path = "file://test/open_test.txt"; + string path = "file://test/OpenCoreMockTest_DoOpen_002"; int32_t mode = 0; + auto unistdMock = UnistdMock::GetMock(); EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).WillRepeatedly(testing::Return(0)); auto res = OpenCore::DoOpen(path, mode); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); EXPECT_EQ(res.IsSuccess(), true); GTEST_LOG_(INFO) << "OpenCoreMockTest-end OpenCoreMockTest_DoOpen_002"; @@ -112,11 +120,15 @@ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_003, testing::ext::TestSize.L { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_003"; - string path = "file://test/open_test.txt"; + string path = "file://test/OpenCoreMockTest_DoOpen_003"; int32_t mode = 0; + auto unistdMock = UnistdMock::GetMock(); EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(-1)); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).WillRepeatedly(testing::Return(0)); auto res = OpenCore::DoOpen(path, mode); + testing::Mock::VerifyAndClearExpectations(&unistdMock); EXPECT_EQ(res.IsSuccess(), false); GTEST_LOG_(INFO) << "OpenCoreMockTest-end OpenCoreMockTest_DoOpen_003"; @@ -133,7 +145,7 @@ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_004, testing::ext::TestSize.L { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_004"; - string path = "/test/open_test.txt"; + string path = "/test/OpenCoreMockTest_DoOpen_004"; int32_t mode = 0; EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(-1)); diff --git a/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..322bca06b91b4d9cdeae3732d7717786e7eea669 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp @@ -0,0 +1,225 @@ +/* + * 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 "eventfd_mock.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" +#include "inotify_mock.h" +#include "mock_watcher_callback.h" +#include "watcher_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class WatcherCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void WatcherCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void WatcherCoreMockTest::TearDownTestCase(void) +{ + EventfdMock::DestroyMock(); + InotifyMock::DestroyMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void WatcherCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void WatcherCoreMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_001 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_001"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_001"; + int32_t events = IN_CREATE; + std::shared_ptr callback = std::make_shared(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto eventfdMock = EventfdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::Return(2)); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_001"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_002 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when InitNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_002"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_002"; + int32_t events = IN_CREATE; + std::shared_ptr callback = std::make_shared(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_002"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_003 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when events are invalid. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_003"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_003"; + int32_t events = -1; + std::shared_ptr callback = std::make_shared(); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_003"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_004 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when CheckEventValid false. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_004"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_004"; + int32_t invalidEvents = ~IN_ALL_EVENTS; + std::shared_ptr callback = std::make_shared(); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, invalidEvents, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_004"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_005 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when callback is null. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_005"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_005"; + int32_t events = IN_CREATE; + std::shared_ptr callback = nullptr; + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_005"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_006 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when AddWatcherInfo fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_006"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_006"; + int32_t events = IN_CREATE; + std::shared_ptr callback = std::make_shared(); + // Prepare test condition + int32_t expectedWd = 100; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + auto info = std::make_shared(callback); + info->fileName = "/test/WatcherCoreMockTest_DoCreateWatcher_006"; + info->events = IN_CREATE; + info->wd = expectedWd; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto cbMock = std::dynamic_pointer_cast(callback); + EXPECT_CALL(*cbMock, IsStrictEquals(testing::_)).Times(1).WillOnce(testing::Return(true)); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(cbMock.get()); + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_006"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp index 5ff953b3e11346578fd5129a6cccd5307fabc88e..ed8996f460bcfd01a6c92010f5884902ff1bddb6 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp @@ -84,7 +84,7 @@ HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoSetXattr_001, testing::ext::Test string key = "test_key"; string value = "test_value"; - EXPECT_CALL(*sys, setxattr(_, _, _, _, _)).WillOnce(Return(-1)); + EXPECT_CALL(*sys, setxattr(_, _, _, _, _)).WillOnce(SetErrnoAndReturn(EIO, -1)); auto ret = XattrCore::DoSetXattr(path, key, value); EXPECT_FALSE(ret.IsSuccess()); @@ -127,7 +127,7 @@ HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoGetXattr_001, testing::ext::Test string path = tempFilePath.string(); string key = "test_key"; - EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillRepeatedly(Return(-1)); + EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillRepeatedly(SetErrnoAndReturn(EIO, -1)); auto ret = XattrCore::DoGetXattr(path, key); EXPECT_TRUE(ret.IsSuccess());