From 7794b796de104904cce9d7d85096f4688c081c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=9C=E5=B0=8F=E6=9E=97?= Date: Fri, 22 Aug 2025 10:33:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dwatcher=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=B7=B2=E7=9F=A5bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idf4a730352169da7a7f8f563c0c45b5208fa1ad1 Signed-off-by: 姜小林 --- .../mod_fs/class_watcher/fs_file_watcher.cpp | 88 ++- .../mod_fs/class_watcher/fs_file_watcher.h | 17 +- .../mod_fs/class_watcher/fs_watch_entity.h | 2 +- .../src/mod_fs/class_watcher/fs_watcher.cpp | 4 +- .../class_watcher/watcher_data_cache.cpp | 50 +- .../mod_fs/class_watcher/watcher_data_cache.h | 7 +- .../js/src/mod_fs/properties/watcher_core.cpp | 4 +- interfaces/test/unittest/js/BUILD.gn | 1 + .../fs_file_watcher_mock_test.cpp | 661 ++++++++++++++++-- .../class_watcher/fs_watcher_mock_test.cpp | 8 +- .../class_watcher/watcher_data_cache_test.cpp | 228 ++++++ .../unittest/js/mod_fs/mock/unistd_mock.cpp | 21 + .../unittest/js/mod_fs/mock/unistd_mock.h | 2 + .../properties/watcher_core_mock_test.cpp | 2 +- 14 files changed, 926 insertions(+), 169 deletions(-) create mode 100644 interfaces/test/unittest/js/mod_fs/class_watcher/watcher_data_cache_test.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 0f5af1e1e..079e6cfb0 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,9 +28,10 @@ namespace OHOS::FileManagement::ModuleFileIO { using namespace std; -int32_t FsFileWatcher::GetNotifyId() +bool FsFileWatcher::TryInitNotify() { - return notifyFd_; + lock_guard lock(notifyMutex_); + return notifyFd_ >= 0 || InitNotify(); } bool FsFileWatcher::InitNotify() @@ -60,7 +61,7 @@ int32_t FsFileWatcher::StartNotify(shared_ptr info) return EIO; } - auto [isWatched, wd] = dataCache_.FindWatchedWd(info->fileName, info->events); + auto [isWatched, wd, events] = dataCache_.FindWatchedEvents(info->fileName, info->events); if (isWatched && wd > 0) { info->wd = wd; return ERRNO_NOERR; @@ -68,7 +69,7 @@ int32_t FsFileWatcher::StartNotify(shared_ptr info) uint32_t watchEvents = 0; if (wd != -1) { - watchEvents = dataCache_.GetFileEvents(info->fileName) | info->events; + watchEvents = events | info->events; } else { watchEvents = info->events; } @@ -107,6 +108,7 @@ int32_t FsFileWatcher::CloseNotifyFd() if (!dataCache_.HasWatcherInfo()) { run_ = false; + WakeupThread(); closeRet = close(notifyFd_); if (closeRet != 0) { HILOGE("Failed to stop notify close fd errCode:%{public}d", errno); @@ -118,7 +120,6 @@ int32_t FsFileWatcher::CloseNotifyFd() HILOGE("Failed to close eventfd errCode:%{public}d", errno); } eventFd_ = -1; - DestroyTaskThead(); } closed_ = false; @@ -127,13 +128,12 @@ int32_t FsFileWatcher::CloseNotifyFd() int32_t FsFileWatcher::CloseNotifyFdLocked() { - { - lock_guard lock(readMutex_); - closed_ = true; - if (reading_) { - HILOGE("Close while reading"); - return ERRNO_NOERR; - } + scoped_lock lock(readMutex_, notifyMutex_); + closed_ = true; + if (reading_) { + HILOGE("Close while reading"); + closed_ = false; + return ERRNO_NOERR; } return CloseNotifyFd(); } @@ -152,6 +152,7 @@ int32_t FsFileWatcher::StopNotify(shared_ptr info) 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, remainingEvents); } @@ -159,6 +160,7 @@ int32_t FsFileWatcher::StopNotify(shared_ptr info) return ERRNO_NOERR; } + // No events remain to be listened for, and proceed to the file watch removal process. int32_t oldWd = -1; { lock_guard lock(readMutex_); @@ -173,13 +175,13 @@ int32_t FsFileWatcher::StopNotify(shared_ptr info) int32_t rmErr = errno; if (access(info->fileName.c_str(), F_OK) == 0) { HILOGE("Failed to stop notify errCode:%{public}d", rmErr); - dataCache_.RemoveFileWatcher(info->fileName); + dataCache_.RemoveWatchedEvents(info->fileName); CloseNotifyFdLocked(); return rmErr; } } - dataCache_.RemoveFileWatcher(info->fileName); + dataCache_.RemoveWatchedEvents(info->fileName); return CloseNotifyFdLocked(); } @@ -189,6 +191,7 @@ void FsFileWatcher::ReadNotifyEvent() int32_t index = 0; char buf[BUF_SIZE] = { 0 }; struct inotify_event *event = nullptr; + int32_t eventSize = static_cast(sizeof(struct inotify_event)); do { len = read(notifyFd_, &buf, sizeof(buf)); @@ -200,8 +203,19 @@ void FsFileWatcher::ReadNotifyEvent() while (index < len) { event = reinterpret_cast(buf + index); + if ((len - index) < eventSize) { + HILOGE( + "out of bounds access, len:%{public}d, index: %{public}d, inotify: %{public}d", len, index, eventSize); + break; + } + if (event->len > (static_cast(len - index - eventSize))) { + HILOGE("out of bounds access, index: %{public}d, inotify: %{public}d, " + "event :%{public}u, len: %{public}d", + index, eventSize, event->len, len); + break; + } NotifyEvent(event); - index += sizeof(struct inotify_event) + static_cast(event->len); + index += eventSize + static_cast(event->len); } } @@ -215,11 +229,9 @@ void FsFileWatcher::ReadNotifyEventLocked() } reading_ = true; } - ReadNotifyEvent(); - { - lock_guard lock(readMutex_); + scoped_lock lock(readMutex_, notifyMutex_); reading_ = false; if (closed_) { HILOGE("Close after read"); @@ -231,10 +243,9 @@ void FsFileWatcher::ReadNotifyEventLocked() void FsFileWatcher::AsyncGetNotifyEvent() { - lock_guard lock(taskMutex_); - if (!taskRunning_) { - taskRunning_ = true; - taskThead_ = thread(&FsFileWatcher::GetNotifyEvent, this); + bool expected = false; + if (taskRunning_.compare_exchange_strong(expected, true)) { + taskThread_ = thread(&FsFileWatcher::GetNotifyEvent, this); } } @@ -271,7 +282,10 @@ void FsFileWatcher::GetNotifyEvent() HILOGE("Failed to poll NotifyFd, errno=%{public}d", errno); break; } + // Ignore cases where poll returns 0 (timeout) or EINTR (interrupted system call) } + DestroyTaskThread(); + HILOGD("The task has been completed."); } bool FsFileWatcher::AddWatcherInfo(shared_ptr info) @@ -301,7 +315,7 @@ void FsFileWatcher::NotifyEvent(const struct inotify_event *event) auto [matched, fileName, watcherInfos] = dataCache_.FindWatcherInfos(event->wd, event->mask); if (!matched) { - HILOGE("Cannot find matched watcherInfos"); + // ignore unmatched event return; } @@ -323,23 +337,27 @@ bool FsFileWatcher::CheckEventValid(uint32_t event) } } -void FsFileWatcher::DestroyTaskThead() +void FsFileWatcher::DestroyTaskThread() { - if (taskThead_.joinable()) { - if (taskThead_.get_id() != std::this_thread::get_id()) { - taskThead_.join(); - } else { - taskThead_.detach(); + bool expected = true; + if (taskRunning_.compare_exchange_strong(expected, false)) { + run_ = false; + dataCache_.ClearCache(); + + if (taskThread_.joinable()) { + taskThread_.detach(); } } +} - { - lock_guard lock(taskMutex_); - if (taskRunning_) { - taskRunning_ = false; - run_ = false; +void FsFileWatcher::WakeupThread() +{ + if (taskRunning_ && eventFd_ >= 0 && taskThread_.joinable()) { + uint64_t val = 1; + auto ret = write(eventFd_, &val, sizeof(val)); + if (ret != sizeof(val)) { + HILOGE("WakeupThread failed! errno: %{public}d", errno); } } - 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 57b83d331..2a114cb13 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 @@ -33,11 +33,9 @@ constexpr int32_t BUF_SIZE = 1024; class FsFileWatcher : public Singleton { public: - int32_t GetNotifyId(); - bool InitNotify(); + bool TryInitNotify(); int32_t StartNotify(shared_ptr info); int32_t StopNotify(shared_ptr info); - void GetNotifyEvent(); void AsyncGetNotifyEvent(); bool AddWatcherInfo(shared_ptr info); bool CheckEventValid(uint32_t event); @@ -49,6 +47,8 @@ public: FsFileWatcher &operator=(const FsFileWatcher &) = delete; private: + bool InitNotify(); + void GetNotifyEvent(); uint32_t RemoveWatcherInfo(shared_ptr info); void NotifyEvent(const struct inotify_event *event); int32_t CloseNotifyFd(); @@ -56,18 +56,19 @@ private: int32_t NotifyToWatchNewEvents(const string &fileName, int32_t wd, uint32_t watchEvents); void ReadNotifyEvent(); void ReadNotifyEventLocked(); - void DestroyTaskThead(); + void DestroyTaskThread(); + void WakeupThread(); private: static constexpr int32_t pollTimeoutMs = 500; - mutex taskMutex_; mutex readMutex_; + mutex notifyMutex_; - atomic taskRunning_ = false; - thread taskThead_; + atomic taskRunning_ { false }; + thread taskThread_; - bool run_ = false; + atomic run_ { false }; bool reading_ = false; bool closed_ = false; int32_t notifyFd_ = -1; diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h index 83184bb48..534c0fae8 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h @@ -43,7 +43,7 @@ struct WatcherInfo { }; struct FsWatchEntity { - std::shared_ptr watherInfo; + std::shared_ptr watcherInfo; }; } // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp index 73dd1d830..c3be5dc1e 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp @@ -48,7 +48,7 @@ FsResult FsWatcher::Stop() HILOGE("Failed to get watchEntity when stop."); return FsResult::Error(EINVAL); } - int ret = FsFileWatcher::GetInstance().StopNotify(watchEntity->watherInfo); + int ret = FsFileWatcher::GetInstance().StopNotify(watchEntity->watcherInfo); if (ret != ERRNO_NOERR) { HILOGE("Failed to stopNotify errno:%{public}d", errno); return FsResult::Error(ret); @@ -63,7 +63,7 @@ FsResult FsWatcher::Start() return FsResult::Error(EINVAL); } - shared_ptr info = watchEntity->watherInfo; + shared_ptr info = watchEntity->watcherInfo; int ret = FsFileWatcher::GetInstance().StartNotify(info); if (ret != ERRNO_NOERR) { HILOGE("Failed to startNotify."); 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 index 83b5e2a51..03b63a1ae 100644 --- 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 @@ -30,7 +30,6 @@ bool WatcherDataCache::AddWatcherInfo(std::shared_ptr info) } } watcherInfoCache_.push_back(info); - wdFileNameCache_[info->fileName] = std::make_pair(info->wd, info->events); return true; } @@ -48,56 +47,39 @@ uint32_t WatcherDataCache::RemoveWatcherInfo(std::shared_ptr info) remainingEvents |= iter->events; } } - return remainingEvents; } -bool WatcherDataCache::RemoveFileWatcher(const std::string &fileName) +void WatcherDataCache::RemoveWatchedEvents(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; + wdFileNameCache_.erase(fileName); } -std::tuple WatcherDataCache::FindWatchedWd(const std::string &fileName, uint32_t event) +std::tuple WatcherDataCache::FindWatchedEvents(const std::string &fileName, uint32_t event) { std::lock_guard lock(cacheMutex_); int32_t wd = -1; + uint32_t events = 0; auto iter = wdFileNameCache_.find(fileName); if (iter == wdFileNameCache_.end()) { - return { false, wd }; + return { false, wd, events }; } wd = iter->second.first; - if ((iter->second.second & event) == event) { - return { true, wd }; + events = iter->second.second; + if ((iter->second.second & event) != event) { + return { false, wd, events }; } - return { false, wd }; + return { true, wd, events }; } -bool WatcherDataCache::UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events) +void 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; + wdFileNameCache_[fileName] = std::make_pair(wd, events); } static bool CheckIncludeEvent(uint32_t mask, uint32_t event) @@ -136,16 +118,6 @@ std::tuple>> Watcher 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_); 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 index e18d584f1..df6ac98a8 100644 --- 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 @@ -29,12 +29,11 @@ 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); + void RemoveWatchedEvents(const std::string &fileName); + std::tuple FindWatchedEvents(const std::string &fileName, uint32_t event); + void 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(); 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 2b78a7c91..d622ff9b8 100644 --- a/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp @@ -28,7 +28,7 @@ using namespace std; static FsResult InstantiateWatcher() { - if (FsFileWatcher::GetInstance().GetNotifyId() < 0 && !FsFileWatcher::GetInstance().InitNotify()) { + if (!FsFileWatcher::GetInstance().TryInitNotify()) { HILOGE("Failed to get notifyId or initnotify fail"); return FsResult::Error(errno); } @@ -96,7 +96,7 @@ FsResult WatcherCore::DoCreateWatcher( return FsResult::Error(EIO); } - watchEntity->watherInfo = info; + watchEntity->watcherInfo = info; bool ret = FsFileWatcher::GetInstance().AddWatcherInfo(info); if (!ret) { diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn index 069ac9f98..446afaf27 100644 --- a/interfaces/test/unittest/js/BUILD.gn +++ b/interfaces/test/unittest/js/BUILD.gn @@ -249,6 +249,7 @@ ohos_unittest("ani_file_fs_test") { "mod_fs/class_stat/fs_stat_test.cpp", "mod_fs/class_stream/fs_stream_test.cpp", "mod_fs/class_tasksignal/fs_task_signal_test.cpp", + "mod_fs/class_watcher/watcher_data_cache_test.cpp", "mod_fs/properties/access_core_test.cpp", "mod_fs/properties/close_core_test.cpp", "mod_fs/properties/copy_core_test.cpp", 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 index fe585ef71..446b5ac10 100644 --- 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 @@ -80,105 +80,120 @@ void FsFileWatcherMockTest::TearDown(void) inline const int32_t EXPECTED_WD = 100; inline const int32_t UNEXPECTED_WD = 200; +inline const int32_t INITIALIZED_NOTIFYFD = 1; +inline const int32_t UNINITIALIZED_NOTIFYFD = -1; +inline const int32_t INITIALIZED_EVENTFD = 1; +inline const int32_t UNINITIALIZED_EVENTFD = -1; /** - * @tc.name: FsFileWatcherMockTest_GetNotifyId_001 - * @tc.desc: Test function of FsFileWatcher::GetNotifyId interface. + * @tc.name: FsFileWatcherMockTest_TryInitNotify_001 + * @tc.desc: Test function of FsFileWatcher::TryInitNotify interface SUCCESS When notifyFd_ has initialed. * @tc.size: SMALL * @tc.type: FUNC * @tc.level Level 0 */ -HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyId_001, testing::ext::TestSize.Level0) +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_TryInitNotify_001, testing::ext::TestSize.Level0) { - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyId_001"; + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_TryInitNotify_001"; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - int32_t expected = -1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + // Set mock behaviors + auto eventfdMock = EventfdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(0); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(0); // Do testing - int32_t result = watcher.GetNotifyId(); + bool result = watcher.TryInitNotify(); // Verify results - EXPECT_EQ(result, expected); - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyId_001"; + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_TryInitNotify_001"; } /** - * @tc.name: FsFileWatcherMockTest_InitNotify_001 - * @tc.desc: Test function of FsFileWatcher::InitNotify interface for SUCCESS. + * @tc.name: FsFileWatcherMockTest_TryInitNotify_002 + * @tc.desc: Test function of FsFileWatcher::TryInitNotify interface for SUCCESS when InitNotify success. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 0 */ -HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_001, testing::ext::TestSize.Level0) +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_TryInitNotify_002, testing::ext::TestSize.Level0) { - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_001"; + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_TryInitNotify_002"; // 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)); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(INITIALIZED_NOTIFYFD)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::Return(INITIALIZED_EVENTFD)); // Do testing - bool result = watcher.InitNotify(); + bool result = watcher.TryInitNotify(); // 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"; + EXPECT_EQ(watcher.notifyFd_, INITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_TryInitNotify_002"; } /** - * @tc.name: FsFileWatcherMockTest_InitNotify_002 - * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when inotify_init fails. + * @tc.name: FsFileWatcherMockTest_TryInitNotify_003 + * @tc.desc: Test function of FsFileWatcher::TryInitNotify 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) +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_TryInitNotify_003, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_002"; + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_TryInitNotify_003"; // 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)); + EXPECT_CALL(*inotifyMock, inotify_init()) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, UNINITIALIZED_NOTIFYFD)); // Do testing - bool result = watcher.InitNotify(); + bool result = watcher.TryInitNotify(); // Verify results testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); EXPECT_FALSE(result); - EXPECT_EQ(watcher.notifyFd_, -1); - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_002"; + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_NOTIFYFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_TryInitNotify_003"; } /** - * @tc.name: FsFileWatcherMockTest_InitNotify_003 - * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when eventfd fails. + * @tc.name: FsFileWatcherMockTest_TryInitNotify_004 + * @tc.desc: Test function of FsFileWatcher::TryInitNotify 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) +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_TryInitNotify_004, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_003"; + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_TryInitNotify_004"; // 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)); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(INITIALIZED_NOTIFYFD)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, UNINITIALIZED_EVENTFD)); // Do testing - bool result = watcher.InitNotify(); + bool result = watcher.TryInitNotify(); // 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"; + EXPECT_EQ(watcher.notifyFd_, INITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_TryInitNotify_004"; } /** @@ -197,7 +212,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_001, testing:: info->events = IN_CREATE | IN_DELETE; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; // Set mock behaviors auto inotifyMock = InotifyMock::GetMock(); EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) @@ -230,8 +245,9 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_002, testing:: info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); + watcher.dataCache_.UpdateWatchedEvents(info->fileName, info->wd, info->events); // Set mock behaviors auto inotifyMock = InotifyMock::GetMock(); EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).Times(0); @@ -274,7 +290,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_004, testing:: GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_004"; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = -1; + watcher.notifyFd_ = UNINITIALIZED_NOTIFYFD; // Build test parameters auto info = std::make_shared(nullptr); info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_004"; @@ -298,7 +314,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_005, testing:: GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_005"; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; // Build test parameters auto info = std::make_shared(nullptr); info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_005"; @@ -332,7 +348,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_006, testing:: info->events = IN_CREATE; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; auto cachedInfo = std::make_shared(nullptr); cachedInfo->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_006"; cachedInfo->events = IN_DELETE; @@ -352,6 +368,39 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_006, testing:: GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_006"; } +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_007 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS fileName already watched but events + * unmatched. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_007, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_007"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_007"; + info->events = IN_CREATE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.dataCache_.UpdateWatchedEvents(info->fileName, EXPECTED_WD, IN_DELETE); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(EXPECTED_WD)); + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + EXPECT_EQ(info->wd, EXPECTED_WD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_007"; +} + /** * @tc.name: FsFileWatcherMockTest_StopNotify_001 * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS. @@ -369,7 +418,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_001, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set mock behaviors auto unistdMock = UnistdMock::GetMock(); @@ -417,7 +466,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_003, testing::e GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_003"; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = -1; + watcher.notifyFd_ = UNINITIALIZED_NOTIFYFD; // Prepare test parameters auto info = std::make_shared(nullptr); info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_003"; @@ -447,7 +496,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_004, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set mock behaviors auto unistdMock = UnistdMock::GetMock(); @@ -483,7 +532,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_005, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set rm watch fail condition watcher.closed_ = true; @@ -521,7 +570,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_006, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set having remainingEvents condition auto remainingInfo = std::make_shared(nullptr); @@ -562,7 +611,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_007, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set having remainingEvents condition auto remainingInfo = std::make_shared(nullptr); @@ -606,7 +655,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_008, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set having remainingEvents condition auto remainingInfo = std::make_shared(nullptr); @@ -650,7 +699,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_009, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; watcher.dataCache_.AddWatcherInfo(info); // Set having remainingEvents condition auto remainingInfo = std::make_shared(nullptr); @@ -693,23 +742,24 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_010, testing::e info->wd = EXPECTED_WD; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); - watcher.notifyFd_ = 1; - watcher.eventFd_ = 1; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; 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(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::SetErrnoAndReturn(EIO, -1)); 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); + EXPECT_EQ(result, -1); + EXPECT_EQ(errno, EIO); + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_010"; } @@ -750,8 +800,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_002, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; // Set mock behaviors auto pollMock = PollMock::GetMock(); EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) @@ -782,8 +832,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_003, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; // Set mock behaviors auto pollMock = PollMock::GetMock(); EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) @@ -814,8 +864,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_004, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; watcher.closed_ = true; // Avoid calling ReadNotifyEvent // Set mock behaviors auto pollMock = PollMock::GetMock(); @@ -847,8 +897,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_005, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; // Set mock behaviors auto pollMock = PollMock::GetMock(); EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) @@ -878,8 +928,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_006, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; // Set mock behaviors auto pollMock = PollMock::GetMock(); EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) @@ -910,8 +960,8 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_007, testin // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.run_ = false; - watcher.notifyFd_ = 1; - watcher.eventFd_ = 2; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; // Set mock behaviors auto pollMock = PollMock::GetMock(); EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) @@ -1058,6 +1108,60 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_003, testi GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_003"; } +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_004 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for FAILURE when read incomplete event struct. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_004, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_004"; + // 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 - 1)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_005 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for FAILURE when read incomplete event struct. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_005, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_005"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + int32_t len = static_cast(sizeof(struct inotify_event)); + auto data = "FsFileWatcherMockTest_ReadNotifyEvent_005"; + uint32_t dataLen = strlen(data); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::DoAll(testing::Invoke([dataLen](int, void *buf, size_t) { + auto *event = reinterpret_cast(buf); + event->len = dataLen; + }), + testing::Return(len + static_cast(dataLen) - 1))); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_005"; +} + /** * @tc.name: FsFileWatcherMockTest_NotifyEvent_001 * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for SUCCESS when valid event without filename. @@ -1079,6 +1183,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_001, testing:: info->wd = EXPECTED_WD; FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.dataCache_.AddWatcherInfo(info); + watcher.dataCache_.UpdateWatchedEvents(info->fileName, info->wd, info->events); // Set mock behaviors EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); // Do testing @@ -1124,6 +1229,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_002, testing:: info->wd = EXPECTED_WD; FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.dataCache_.AddWatcherInfo(info); + watcher.dataCache_.UpdateWatchedEvents(info->fileName, info->wd, info->events); // Set mock behaviors EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); // Do testing @@ -1173,6 +1279,7 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_004, testing:: info->wd = UNEXPECTED_WD; // Not matched wd FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.dataCache_.AddWatcherInfo(info); + watcher.dataCache_.UpdateWatchedEvents(info->fileName, info->wd, info->events); // Set mock behaviors EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(0); // Do testing @@ -1299,23 +1406,431 @@ HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_RemoveWatcherInfo_001, tes } /** - * @tc.name: FsFileWatcherMockTest_DestroyTaskThead_001 - * @tc.desc: Test function of FsFileWatcher::DestroyTaskThead interface when taskRunning is true. + * @tc.name: FsFileWatcherMockTest_DestroyTaskThread_001 + * @tc.desc: Test function of FsFileWatcher::DestroyTaskThread interface when taskRunning is true. * @tc.size: SMALL * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_DestroyTaskThead_001, testing::ext::TestSize.Level1) +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_DestroyTaskThread_001, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_DestroyTaskThead_001"; + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_DestroyTaskThread_001"; // Prepare test condition FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.taskRunning_ = true; + watcher.run_ = true; // Do testing - watcher.DestroyTaskThead(); + watcher.DestroyTaskThread(); // Verify results EXPECT_FALSE(watcher.taskRunning_); - GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_DestroyTaskThead_001"; + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_DestroyTaskThread_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_DestroyTaskThread_002 + * @tc.desc: Test function of FsFileWatcher::DestroyTaskThread interface when taskRunning is true and taskThread_ is + * joinable. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_DestroyTaskThread_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_DestroyTaskThread_002"; + // Prepare test condition + std::atomic keepAlive(false); + std::thread mockThread([&]() { + keepAlive = true; + while (keepAlive) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + }); + // Wait for mockThread to start (ensure keepAlive is set to true, prevent thread from exiting early) + while (!keepAlive) { + std::this_thread::yield(); + } + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskThread_ = std::move(mockThread); + watcher.taskRunning_ = true; + watcher.run_ = true; + // Do testing + watcher.DestroyTaskThread(); + // Verify results + EXPECT_FALSE(watcher.taskRunning_); + EXPECT_FALSE(watcher.run_); + // Cleanup resources + keepAlive = false; + if (watcher.taskThread_.joinable()) { + watcher.taskThread_.join(); + } + watcher.taskThread_ = std::thread(); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_DestroyTaskThread_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_DestroyTaskThread_003 + * @tc.desc: Test function of FsFileWatcher::DestroyTaskThread interface when taskRunning is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_DestroyTaskThread_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_DestroyTaskThread_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = true; + // Do testing + watcher.DestroyTaskThread(); + // Verify results + EXPECT_FALSE(watcher.taskRunning_); + EXPECT_TRUE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_DestroyTaskThread_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_WakeupThread_001 + * @tc.desc: Test function of FsFileWatcher::WakeupThread interface SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_WakeupThread_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_WakeupThread_001"; + // Prepare test condition + std::atomic keepAlive(false); + std::thread mockThread([&]() { + keepAlive = true; + while (keepAlive) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + }); + // Wait for mockThread to start (ensure keepAlive is set to true, prevent thread from exiting early) + while (!keepAlive) { + std::this_thread::yield(); + } + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskThread_ = std::move(mockThread); + watcher.taskRunning_ = true; + watcher.eventFd_ = INITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(sizeof(uint64_t))); + // Do testing + watcher.WakeupThread(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(watcher.taskRunning_); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + // Cleanup resources + keepAlive = false; + if (watcher.taskThread_.joinable()) { + watcher.taskThread_.join(); + } + watcher.taskThread_ = std::thread(); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_WakeupThread_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_WakeupThread_002 + * @tc.desc: Test function of FsFileWatcher::WakeupThread interface FAILURE when taskRunning_ is false. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_WakeupThread_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_WakeupThread_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.eventFd_ = INITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.WakeupThread(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.taskRunning_); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_WakeupThread_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_WakeupThread_003 + * @tc.desc: Test function of FsFileWatcher::WakeupThread interface FAILURE when eventFd_ < 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_WakeupThread_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_WakeupThread_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = true; + watcher.eventFd_ = UNINITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.WakeupThread(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(watcher.taskRunning_); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_WakeupThread_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_WakeupThread_004 + * @tc.desc: Test function of FsFileWatcher::WakeupThread interface FAILURE when eventFd_ < 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_WakeupThread_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_WakeupThread_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = true; + watcher.eventFd_ = INITIALIZED_EVENTFD; + watcher.taskThread_ = std::thread(); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.WakeupThread(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(watcher.taskRunning_); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_WakeupThread_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_WakeupThread_005 + * @tc.desc: Test function of FsFileWatcher::WakeupThread interface SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_WakeupThread_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_WakeupThread_001"; + // Prepare test condition + std::atomic keepAlive(false); + std::thread mockThread([&]() { + keepAlive = true; + while (keepAlive) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + }); + // Wait for mockThread to start (ensure keepAlive is set to true, prevent thread from exiting early) + while (!keepAlive) { + std::this_thread::yield(); + } + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskThread_ = std::move(mockThread); + watcher.taskRunning_ = true; + watcher.eventFd_ = INITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + watcher.WakeupThread(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(watcher.taskRunning_); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + EXPECT_EQ(errno, EIO); + // Cleanup resources + keepAlive = false; + if (watcher.taskThread_.joinable()) { + watcher.taskThread_.join(); + } + watcher.taskThread_ = std::thread(); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_WakeupThread_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_CloseNotifyFdLocked_001 + * @tc.desc: Test function of FsFileWatcher::CloseNotifyFdLocked interface when reading_ is true. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_CloseNotifyFdLocked_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_CloseNotifyFdLocked_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.reading_ = true; + // Do testing + auto ret = watcher.CloseNotifyFdLocked(); + // Verify results + EXPECT_FALSE(watcher.closed_); + EXPECT_EQ(ret, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_CloseNotifyFdLocked_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_CloseNotifyFdLocked_002 + * @tc.desc: Test function of FsFileWatcher::CloseNotifyFdLocked interface when CloseNotifyFd return ERRNO_NOERR. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_CloseNotifyFdLocked_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_CloseNotifyFdLocked_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.reading_ = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + auto ret = watcher.CloseNotifyFdLocked(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.closed_); + EXPECT_EQ(ret, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_CloseNotifyFdLocked_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_CloseNotifyFd_001 + * @tc.desc: Test function of FsFileWatcher::CloseNotifyFd interface SUCCESS when HasWatcherInfo is true. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_CloseNotifyFd_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_CloseNotifyFd_001"; + // Prepare test condition + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_CloseNotifyFd_001"; + info->events = IN_CREATE | IN_DELETE; + info->wd = EXPECTED_WD; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + watcher.closed_ = true; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + // Do testing + auto ret = watcher.CloseNotifyFd(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(watcher.run_); + EXPECT_FALSE(watcher.closed_); + EXPECT_EQ(watcher.notifyFd_, INITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + EXPECT_EQ(ret, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_CloseNotifyFd_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_CloseNotifyFd_002 + * @tc.desc: Test function of FsFileWatcher::CloseNotifyFd interface SUCCESS when HasWatcherInfo is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_CloseNotifyFd_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_CloseNotifyFd_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + watcher.closed_ = true; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + auto ret = watcher.CloseNotifyFd(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.run_); + EXPECT_FALSE(watcher.closed_); + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_NOTIFYFD); + EXPECT_EQ(ret, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_CloseNotifyFd_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_CloseNotifyFd_003 + * @tc.desc: Test function of FsFileWatcher::CloseNotifyFd interface FAILURE when close notifyFd_ and eventFd_ fails. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_CloseNotifyFd_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_CloseNotifyFd_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + watcher.closed_ = true; + watcher.notifyFd_ = INITIALIZED_NOTIFYFD; + watcher.eventFd_ = INITIALIZED_EVENTFD; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, write(testing::_, testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + auto ret = watcher.CloseNotifyFd(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.run_); + EXPECT_FALSE(watcher.closed_); + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); + EXPECT_EQ(ret, -1); + EXPECT_EQ(errno, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_CloseNotifyFd_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_AsyncGetNotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::AsyncGetNotifyEvent interface SUCCESS. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_AsyncGetNotifyEvent_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_AsyncGetNotifyEvent_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + watcher.taskRunning_ = false; + // Do testing + watcher.AsyncGetNotifyEvent(); + // Verify results + EXPECT_TRUE(watcher.run_); + EXPECT_TRUE(watcher.taskRunning_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_AsyncGetNotifyEvent_001"; } } // namespace Test 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 index 6894647ea..5be1fde4e 100644 --- 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 @@ -112,7 +112,7 @@ HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_001, testing::ext::TestSize.Leve auto watchEntity = CreateUniquePtr(); FsWatcher fsWatcher(std::move(watchEntity)); std::shared_ptr info = std::make_shared(nullptr); - fsWatcher.GetWatchEntity()->watherInfo = info; + fsWatcher.GetWatchEntity()->watcherInfo = info; // Prepare test condition for FsFileWatcher FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.notifyFd_ = 1; // Valid notifyFd @@ -165,7 +165,7 @@ HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_003, testing::ext::TestSize.Leve auto watchEntity = CreateUniquePtr(); FsWatcher fsWatcher(std::move(watchEntity)); std::shared_ptr info = std::make_shared(nullptr); - fsWatcher.GetWatchEntity()->watherInfo = info; + fsWatcher.GetWatchEntity()->watcherInfo = info; // Prepare test condition for FsFileWatcher FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.notifyFd_ = -1; // Invalid notifyFd @@ -192,7 +192,7 @@ HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_001, testing::ext::TestSize.Level auto watchEntity = CreateUniquePtr(); FsWatcher fsWatcher(std::move(watchEntity)); std::shared_ptr info = std::make_shared(nullptr); - fsWatcher.GetWatchEntity()->watherInfo = info; + fsWatcher.GetWatchEntity()->watcherInfo = info; // Prepare test condition for FsFileWatcher FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.notifyFd_ = 1; @@ -247,7 +247,7 @@ HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_003, testing::ext::TestSize.Level auto watchEntity = CreateUniquePtr(); FsWatcher fsWatcher(std::move(watchEntity)); std::shared_ptr info = std::make_shared(nullptr); - fsWatcher.GetWatchEntity()->watherInfo = info; + fsWatcher.GetWatchEntity()->watcherInfo = info; // Prepare test condition for FsFileWatcher FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.notifyFd_ = -1; // Invalid notifyFd diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_data_cache_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_data_cache_test.cpp new file mode 100644 index 000000000..0c4d2f200 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_data_cache_test.cpp @@ -0,0 +1,228 @@ +/* + * 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 "filemgmt_libhilog.h" +#include "watcher_data_cache.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class WatcherDataCacheTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void WatcherDataCacheTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void WatcherDataCacheTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void WatcherDataCacheTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void WatcherDataCacheTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +inline const int32_t EXPECTED_WD = 100; +inline const int32_t UNEXPECTED_WD = 200; +inline const uint32_t EXPECTED_EVENTS = IN_ACCESS | IN_CREATE; + +/** + * @tc.name: WatcherDataCacheTest_RemoveWatchedEvents_001 + * @tc.desc: Test function of WatcherDataCache::RemoveWatchedEvents SUCCESS. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_RemoveWatchedEvents_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_RemoveWatchedEvents_001"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_RemoveWatchedEvents_001"; + cache.wdFileNameCache_[fileName] = std::make_pair(EXPECTED_WD, IN_ACCESS); + // Do testing + cache.RemoveWatchedEvents(fileName); + // Verify results + EXPECT_TRUE(cache.wdFileNameCache_.empty()); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_RemoveWatchedEvents_001"; +} + +/** + * @tc.name: WatcherDataCacheTest_RemoveWatchedEvents_002 + * @tc.desc: Test function of WatcherDataCache::RemoveWatchedEvents SUCCESS when key(fileName) not exist. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_RemoveWatchedEvents_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_RemoveWatchedEvents_002"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_RemoveWatchedEvents_002"; + cache.wdFileNameCache_[fileName] = std::make_pair(EXPECTED_WD, IN_ACCESS); + // Do testing + cache.RemoveWatchedEvents("fileName_not_exist"); + // Verify results + EXPECT_EQ(cache.wdFileNameCache_.size(), 1); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_RemoveWatchedEvents_002"; +} + +/** + * @tc.name: WatcherDataCacheTest_UpdateWatchedEvents_001 + * @tc.desc: Test function of WatcherDataCache::UpdateWatchedEvents SUCCESS when key(fileName) exist. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_UpdateWatchedEvents_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_UpdateWatchedEvents_001"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_UpdateWatchedEvents_001"; + cache.wdFileNameCache_[fileName] = std::make_pair(UNEXPECTED_WD, IN_DELETE); + // Do testing + cache.UpdateWatchedEvents(fileName, EXPECTED_WD, EXPECTED_EVENTS); + // Verify results + EXPECT_EQ(cache.wdFileNameCache_.size(), 1); + EXPECT_EQ(cache.wdFileNameCache_[fileName].first, EXPECTED_WD); + EXPECT_EQ(cache.wdFileNameCache_[fileName].second, EXPECTED_EVENTS); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_UpdateWatchedEvents_001"; +} + +/** + * @tc.name: WatcherDataCacheTest_UpdateWatchedEvents_002 + * @tc.desc: Test function of WatcherDataCache::UpdateWatchedEvents SUCCESS when key(fileName) not exist. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_UpdateWatchedEvents_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin " + "WatcherWatcherDataCacheTest_UpdateWatchedEvents_002DataCacheTest_UpdateWatchedEvents_001"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_UpdateWatchedEvents_002"; + // Do testing + cache.UpdateWatchedEvents(fileName, EXPECTED_WD, EXPECTED_EVENTS); + // Verify results + EXPECT_EQ(cache.wdFileNameCache_.size(), 1); + EXPECT_EQ(cache.wdFileNameCache_[fileName].first, EXPECTED_WD); + EXPECT_EQ(cache.wdFileNameCache_[fileName].second, EXPECTED_EVENTS); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_UpdateWatchedEvents_002"; +} + +/** + * @tc.name: WatcherDataCacheTest_FindWatchedEvents_001 + * @tc.desc: Test function of WatcherDataCache::FindWatchedEvents SUCCESS + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_FindWatchedEvents_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_FindWatchedEvents_001"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_FindWatchedEvents_001"; + cache.wdFileNameCache_[fileName] = std::make_pair(EXPECTED_WD, EXPECTED_EVENTS); + // Do testing + auto [isWatched, wd, events] = cache.FindWatchedEvents(fileName, IN_ACCESS); + // Verify results + EXPECT_TRUE(isWatched); + EXPECT_EQ(wd, EXPECTED_WD); + EXPECT_EQ(events, EXPECTED_EVENTS); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_FindWatchedEvents_001"; +} + +/** + * @tc.name: WatcherDataCacheTest_FindWatchedEvents_002 + * @tc.desc: Test function of WatcherDataCache::FindWatchedEvents FAILURE when key(fileName) not exist + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_FindWatchedEvents_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_FindWatchedEvents_002"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_FindWatchedEvents_002"; + // Do testing + auto [isWatched, wd, events] = cache.FindWatchedEvents(fileName, IN_ACCESS); + // Verify results + EXPECT_FALSE(isWatched); + EXPECT_EQ(wd, -1); + EXPECT_EQ(events, 0); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_FindWatchedEvents_002"; +} + +/** + * @tc.name: WatcherDataCacheTest_FindWatchedEvents_003 + * @tc.desc: Test function of WatcherDataCache::FindWatchedEvents FAILURE when event unmatched + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherDataCacheTest, WatcherDataCacheTest_FindWatchedEvents_003, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherDataCacheTest-begin WatcherDataCacheTest_FindWatchedEvents_003"; + // Prepare test condition + WatcherDataCache cache; + auto fileName = "WatcherDataCacheTest_FindWatchedEvents_003"; + cache.wdFileNameCache_[fileName] = std::make_pair(EXPECTED_WD, IN_DELETE); + // Do testing + auto [isWatched, wd, events] = cache.FindWatchedEvents(fileName, IN_ACCESS); + // Verify results + EXPECT_FALSE(isWatched); + EXPECT_EQ(wd, EXPECTED_WD); + EXPECT_EQ(events, IN_DELETE); + cache.wdFileNameCache_.clear(); + GTEST_LOG_(INFO) << "WatcherDataCacheTest-end WatcherDataCacheTest_FindWatchedEvents_003"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp index cda59d9bf..0d05f8b64 100644 --- a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp @@ -121,5 +121,26 @@ ssize_t read(int fd, void *buf, size_t count) return realRead(fd, buf, count); } +ssize_t write(int fd, const void *buf, size_t count) +{ + if (UnistdMock::IsMockable()) { + return UnistdMock::GetMock()->write(fd, buf, count); + } + + static ssize_t (*realWrite)(int fd, const void *buf, size_t count) = []() { + auto func = (ssize_t(*)(int, const void *, size_t))dlsym(RTLD_NEXT, "write"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real write: " << dlerror(); + } + return func; + }(); + + if (!realWrite) { + return 0; + } + + return realWrite(fd, buf, count); +} + } // extern "C" #endif \ 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 index ec6f961e1..3771b1424 100644 --- a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h @@ -30,6 +30,7 @@ public: virtual int access(const char *, int) = 0; virtual int close(int) = 0; virtual ssize_t read(int, void *, size_t) = 0; + virtual ssize_t write(int, const void *, size_t) = 0; }; class UnistdMock : public IUnistdMock { @@ -37,6 +38,7 @@ 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)); + MOCK_METHOD(ssize_t, write, (int, const void *, size_t), (override)); public: static std::shared_ptr GetMock(); 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 index 680a2ce32..f9695cfb0 100644 --- 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 @@ -101,7 +101,7 @@ HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_001, testing:: /** * @tc.name: WatcherCoreMockTest_DoCreateWatcher_002 - * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when InitNotify fails. + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when TryInitNotify fails. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -- Gitee