From 07cb15b2731e2918f9ac6ef252bc6929ab89a1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=9C=E5=B0=8F=E6=9E=97?= Date: Sat, 6 Sep 2025 16:30:24 +0800 Subject: [PATCH 1/2] =?UTF-8?q?FileWatcher::InitNotify=E6=8E=A5=E5=8F=A3bu?= =?UTF-8?q?g=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I6cbc898a08cf016bc1478d73c6db4f4db18aa40d Signed-off-by: 姜小林 --- .../mod_fs/class_watcher/watcher_entity.cpp | 23 ++-- interfaces/test/unittest/js/BUILD.gn | 9 +- .../class_watcher/watcher_entity_test.cpp | 125 ++++++++++++++++++ 3 files changed, 145 insertions(+), 12 deletions(-) diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp index 11249146b..c0ecc8258 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp @@ -49,6 +49,8 @@ bool FileWatcher::InitNotify() eventFd_ = eventfd(0, EFD_CLOEXEC); if (eventFd_ < 0) { HILOGE("Failed to init eventfd errCode:%{public}d", errno); + close(notifyFd_); // Ignore the result of close + notifyFd_ = -1; return false; } return true; @@ -59,13 +61,13 @@ tuple FileWatcher::CheckEventWatched(const string &fileName, const ui int wd = -1; auto iter = wdFileNameMap_.find(fileName); if (iter == wdFileNameMap_.end()) { - return {false, wd}; + return { false, wd }; } wd = iter->second.first; if ((iter->second.second & event) == event) { - return {true, wd}; + return { true, wd }; } - return {false, wd}; + return { false, wd }; } int FileWatcher::StartNotify(shared_ptr arg) @@ -190,21 +192,20 @@ void FileWatcher::ReadNotifyEvent(WatcherCallback callback) { int len = 0; int index = 0; - char buf[BUF_SIZE] = {0}; + char buf[BUF_SIZE] = { 0 }; struct inotify_event *event = nullptr; while (((len = read(notifyFd_, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; while (index < len) { event = reinterpret_cast(buf + index); if ((len - index) < sizeof(struct inotify_event)) { - HILOGE("out of bounds access, len:%{public}d, index: %{public}d, inotify: %{public}zu", - len, index, sizeof(struct inotify_event)); + HILOGE("out of bounds access, len:%{public}d, index: %{public}d, inotify: %{public}zu", len, index, + sizeof(struct inotify_event)); break; } if (event->len > (static_cast(len - index - sizeof(struct inotify_event)))) { HILOGE("out of bounds access, index: %{public}d, inotify: %{public}zu, " "event :%{public}u, len: %{public}d", - index, sizeof(struct inotify_event), - event->len, len); + index, sizeof(struct inotify_event), event->len, len); break; } NotifyEvent(event, callback); @@ -307,10 +308,10 @@ void FileWatcher::NotifyEvent(const struct inotify_event *event, WatcherCallback { lock_guard lock(watchMutex_); string tempFileName; - auto found = find_if(wdFileNameMap_.begin(), wdFileNameMap_.end(), - [event](const pair> &iter) { + 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; } diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn index 571257d36..f824a60a9 100644 --- a/interfaces/test/unittest/js/BUILD.gn +++ b/interfaces/test/unittest/js/BUILD.gn @@ -327,11 +327,17 @@ ohos_unittest("napi_file_fs_test") { module_out_path = "file_api/file_api" - include_dirs = [ "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher" ] + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/mock", + ] sources = [ "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp", "mod_fs/class_watcher/watcher_entity_test.cpp", + "mod_fs/mock/eventfd_mock.cpp", + "mod_fs/mock/inotify_mock.cpp", + "mod_fs/mock/unistd_mock.cpp", ] deps = [ @@ -342,6 +348,7 @@ ohos_unittest("napi_file_fs_test") { external_deps = [ "c_utils:utils", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", "libuv:uv", diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp index 04dd5cd0f..e50919a0b 100644 --- a/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp @@ -16,8 +16,13 @@ #include "watcher_entity.h" #include +#include #include +#include "eventfd_mock.h" +#include "inotify_mock.h" +#include "unistd_mock.h" + namespace OHOS::FileManagement::ModuleFileIO::Test { class WatcherEntityTest : public testing::Test { @@ -41,13 +46,35 @@ void WatcherEntityTest::TearDownTestCase(void) void WatcherEntityTest::SetUp(void) { GTEST_LOG_(INFO) << "SetUp"; + EventfdMock::EnableMock(); + InotifyMock::EnableMock(); + UnistdMock::EnableMock(); + errno = 0; } void WatcherEntityTest::TearDown(void) { + // Reset all mocks + EventfdMock::DisableMock(); + InotifyMock::DisableMock(); + UnistdMock::DisableMock(); + // Reset FileWatcher stat + auto &watcher = FileWatcher::GetInstance(); + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.watcherInfoSet_.clear(); + watcher.wdFileNameMap_.clear(); GTEST_LOG_(INFO) << "TearDown"; } +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: WatcherEntityTest_CloseNotifyFd_001 * @tc.desc: Test function of WatcherEntityTest::CloseNotifyFd interface for SUCCESS without close. @@ -78,6 +105,9 @@ HWTEST_F(WatcherEntityTest, WatcherEntityTest_CloseNotifyFd_002, testing::ext::T { GTEST_LOG_(INFO) << "WatcherEntityTest-begin WatcherEntityTest_CloseNotifyFd_002"; + EventfdMock::DisableMock(); + InotifyMock::DisableMock(); + UnistdMock::DisableMock(); auto &watcher = FileWatcher::GetInstance(); watcher.run_ = true; watcher.InitNotify(); @@ -98,6 +128,7 @@ HWTEST_F(WatcherEntityTest, WatcherEntityTest_CloseNotifyFd_003, testing::ext::T { GTEST_LOG_(INFO) << "WatcherEntityTest-begin WatcherEntityTest_CloseNotifyFd_003"; + UnistdMock::DisableMock(); auto &watcher = FileWatcher::GetInstance(); watcher.run_ = true; auto ret = watcher.CloseNotifyFd(); @@ -106,4 +137,98 @@ HWTEST_F(WatcherEntityTest, WatcherEntityTest_CloseNotifyFd_003, testing::ext::T GTEST_LOG_(INFO) << "WatcherEntityTest-end WatcherEntityTest_CloseNotifyFd_003"; } +/** + * @tc.name: WatcherEntityTest_InitNotify_001 + * @tc.desc: Test function of FileWatcher::InitNotify interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherEntityTest, WatcherEntityTest_InitNotify_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherEntityTest-begin WatcherEntityTest_InitNotify_001"; + + // Prepare test condition + FileWatcher &watcher = FileWatcher::GetInstance(); + // Set mock behaviors + auto eventfdMock = EventfdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + 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(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result); + EXPECT_EQ(watcher.notifyFd_, INITIALIZED_NOTIFYFD); + EXPECT_EQ(watcher.eventFd_, INITIALIZED_EVENTFD); + + GTEST_LOG_(INFO) << "WatcherEntityTest-end WatcherEntityTest_InitNotify_001"; +} + +/** + * @tc.name: WatcherEntityTest_InitNotify_002 + * @tc.desc: Test function of FileWatcher::InitNotify interface for FAILURE when inotify_init fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherEntityTest, WatcherEntityTest_InitNotify_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherEntityTest-begin WatcherEntityTest_InitNotify_002"; + + // Prepare test condition + FileWatcher &watcher = FileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, UNINITIALIZED_NOTIFYFD)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_EVENTFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); + + GTEST_LOG_(INFO) << "WatcherEntityTest-end WatcherEntityTest_InitNotify_002"; +} + +/** + * @tc.name: WatcherEntityTest_InitNotify_003 + * @tc.desc: Test function of FileWatcher::InitNotify interface for FAILURE when eventfd fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherEntityTest, WatcherEntityTest_InitNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherEntityTest-begin WatcherEntityTest_InitNotify_003"; + + // Prepare test condition + FileWatcher &watcher = FileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto eventfdMock = EventfdMock::GetMock(); + auto unistdMock = UnistdMock::GetMock(); + 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)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(1).WillOnce(testing::Return(0)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, UNINITIALIZED_EVENTFD); + EXPECT_EQ(watcher.eventFd_, UNINITIALIZED_EVENTFD); + + GTEST_LOG_(INFO) << "WatcherEntityTest-end WatcherEntityTest_InitNotify_003"; +} + } // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file -- Gitee From a7b4acc91b97725918937258075545ed594de8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=9C=E5=B0=8F=E6=9E=97?= Date: Sat, 6 Sep 2025 17:58:51 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A3=80=E8=A7=86?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E8=BF=9B=E8=A1=8C=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib75b4430c2105148adce65e572dbc22b3c0d6803 Signed-off-by: 姜小林 --- .../mod_fs/class_watcher/watcher_entity.cpp | 21 ++++++++++--------- .../class_watcher/watcher_entity_test.cpp | 3 +-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp index c0ecc8258..700daf193 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp @@ -61,13 +61,13 @@ tuple FileWatcher::CheckEventWatched(const string &fileName, const ui int wd = -1; auto iter = wdFileNameMap_.find(fileName); if (iter == wdFileNameMap_.end()) { - return { false, wd }; + return {false, wd}; } wd = iter->second.first; if ((iter->second.second & event) == event) { - return { true, wd }; + return {true, wd}; } - return { false, wd }; + return {false, wd}; } int FileWatcher::StartNotify(shared_ptr arg) @@ -192,20 +192,21 @@ void FileWatcher::ReadNotifyEvent(WatcherCallback callback) { int len = 0; int index = 0; - char buf[BUF_SIZE] = { 0 }; + char buf[BUF_SIZE] = {0}; struct inotify_event *event = nullptr; while (((len = read(notifyFd_, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; while (index < len) { event = reinterpret_cast(buf + index); if ((len - index) < sizeof(struct inotify_event)) { - HILOGE("out of bounds access, len:%{public}d, index: %{public}d, inotify: %{public}zu", len, index, - sizeof(struct inotify_event)); + HILOGE("out of bounds access, len:%{public}d, index: %{public}d, inotify: %{public}zu", + len, index, sizeof(struct inotify_event)); break; } if (event->len > (static_cast(len - index - sizeof(struct inotify_event)))) { HILOGE("out of bounds access, index: %{public}d, inotify: %{public}zu, " "event :%{public}u, len: %{public}d", - index, sizeof(struct inotify_event), event->len, len); + index, sizeof(struct inotify_event), + event->len, len); break; } NotifyEvent(event, callback); @@ -308,10 +309,10 @@ void FileWatcher::NotifyEvent(const struct inotify_event *event, WatcherCallback { lock_guard lock(watchMutex_); string tempFileName; - auto found = find_if( - wdFileNameMap_.begin(), wdFileNameMap_.end(), [event](const pair> &iter) { + 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; } diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp index e50919a0b..f3924031b 100644 --- a/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/watcher_entity_test.cpp @@ -15,9 +15,8 @@ #include "watcher_entity.h" -#include #include -#include +#include #include "eventfd_mock.h" #include "inotify_mock.h" -- Gitee