From 1da940d0cee33e851d9e132801f522734e6fcdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Thu, 17 Jul 2025 11:56:23 +0800 Subject: [PATCH 1/3] atomicfile_tdd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 --- interfaces/test/unittest/BUILD.gn | 1 + .../test/unittest/class_atomicfile/BUILD.gn | 64 +++++ .../class_atomicfile/atomicfile_mock_test.cpp | 258 ++++++++++++++++++ .../class_atomicfile/mock/atomicfile_mock.cpp | 230 ++++++++++++++++ .../class_atomicfile/mock/atomicfile_mock.h | 70 +++++ 5 files changed, 623 insertions(+) create mode 100644 interfaces/test/unittest/class_atomicfile/BUILD.gn create mode 100644 interfaces/test/unittest/class_atomicfile/atomicfile_mock_test.cpp create mode 100644 interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.cpp create mode 100644 interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.h diff --git a/interfaces/test/unittest/BUILD.gn b/interfaces/test/unittest/BUILD.gn index 20af46a08..c6df1457c 100644 --- a/interfaces/test/unittest/BUILD.gn +++ b/interfaces/test/unittest/BUILD.gn @@ -16,6 +16,7 @@ import("//foundation/filemanagement/file_api/file_api.gni") group("file_api_unittest") { testonly = true deps = [ + "class_atomicfile:class_atomicfile_test", "class_file:class_file_test", "filemgmt_libn_test:filemgmt_libn_test", "js:ani_file_fs_mock_test", diff --git a/interfaces/test/unittest/class_atomicfile/BUILD.gn b/interfaces/test/unittest/class_atomicfile/BUILD.gn new file mode 100644 index 000000000..e53b3cfdb --- /dev/null +++ b/interfaces/test/unittest/class_atomicfile/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2023 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. + +import("//build/test.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +ohos_unittest("class_atomicfile_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp", + "mock/atomicfile_mock.cpp", + "./atomicfile_mock_test.cpp", + ] + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/common", + "${file_api_path}/interfaces/kits/js/src/common/file_helper", + # "${file_api_path}/interfaces/kits/js/src/common/napi", + "${file_api_path}/interfaces/kits/js/src/mod_fs", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + "${file_api_path}/interfaces/test/unittest/class_atomicfile/mock", + # "${filemanagement_service_path}/distributedfiledaemon/include/ipc", + ] + + use_exceptions = true + + deps = [ + "${file_api_path}/interfaces/kits/js:fs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + "${utils_path}/filemgmt_libn:filemgmt_libn", + ] + + external_deps = [ + "ability_base:zuri", + "app_file_service:fileuri_native", + "c_utils:utils", + "c_utils:utilsbase", + "dfs_service:distributed_file_daemon_kit_inner", + "dfs_service:libdistributedfileutils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "napi:ace_napi", + ] + + defines = [ + "private=public", + ] +} \ No newline at end of file diff --git a/interfaces/test/unittest/class_atomicfile/atomicfile_mock_test.cpp b/interfaces/test/unittest/class_atomicfile/atomicfile_mock_test.cpp new file mode 100644 index 000000000..98a057a7c --- /dev/null +++ b/interfaces/test/unittest/class_atomicfile/atomicfile_mock_test.cpp @@ -0,0 +1,258 @@ +/* + * 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 "atomicfile_mock.h" +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +static const string g_atomicfilePath = "/data/test/AtomicfileMockTest.txt"; + +class AtomicfileMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + AtomicfileMock::EnableMock(); + int32_t fd = open(g_atomicfilePath.c_str(), O_CREAT | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + AtomicfileMock::DisableMock(); + rmdir(g_atomicfilePath.c_str()); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: AtomicfileFailWrite_0001 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFailWrite_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFailWrite_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, remove(testing::_)).WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + + auto res = AtomicFileNExporter::FailWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFailWrite_0001"; +} + +/** + * @tc.name: AtomicfileFailWrite_0002 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFailWrite_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFailWrite_0002"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, remove(testing::_)).WillOnce(testing::Return(-1)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, ThrowErr(testing::_, testing::_)); + + auto res = AtomicFileNExporter::FailWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFailWrite_0002"; +} + +/** + * @tc.name: AtomicfileFailWrite_0003 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFailWrite_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFailWrite_0003"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, remove(testing::_)).WillOnce(testing::Return(-1)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_invalid_arg)); + EXPECT_CALL(*mock_, ThrowErr(testing::_, testing::_)); + + auto res = AtomicFileNExporter::FailWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFailWrite_0003"; +} + +/** + * @tc.name: AtomicfileFinishWrite_0001 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFinishWrite_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFinishWrite_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, rename(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + + auto res = AtomicFileNExporter::FinishWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFinishWrite_0001"; +} + +/** + * @tc.name: AtomicfileFinishWrite_0002 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFinishWrite_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFinishWrite_0002"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, rename(testing::_, testing::_)).WillOnce(testing::Return(-1)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, ThrowErr(testing::_, testing::_)); + + auto res = AtomicFileNExporter::FinishWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFinishWrite_0002"; +} + +/** + * @tc.name: AtomicfileFinishWrite_0003 + * @tc.desc: Test function of FailWrite() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(AtomicfileMockTest, AtomicfileFinishWrite_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AtomicfileMockTest-begin AtomicfileFinishWrite_0003"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + AtomicFileEntity entity; + std::tuple tmp(&entity, 1); + + auto mock_ = AtomicfileMock::GetMock(); + EXPECT_CALL(*mock_, InitArgs(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_, GetThisVar()).WillOnce(testing::Return(reinterpret_cast(&entity))); + EXPECT_CALL(*mock_, napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(static_cast(&entity)), testing::Return(napi_ok))); + EXPECT_CALL(*mock_, napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_typeof(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(napi_undefined), testing::Return(napi_ok))); + + EXPECT_CALL(*mock_, rename(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + EXPECT_CALL(*mock_, napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_invalid_arg)); + EXPECT_CALL(*mock_, ThrowErr(testing::_, testing::_)); + + auto res = AtomicFileNExporter::FinishWrite(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "AtomicfileMockTest-end AtomicfileFinishWrite_0003"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.cpp b/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.cpp new file mode 100644 index 000000000..1bad899d9 --- /dev/null +++ b/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.cpp @@ -0,0 +1,230 @@ +/* + * 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 "atomicfile_mock.h" + +#include + +using namespace OHOS::FileManagement::ModuleFileIO; + +namespace OHOS::FileManagement::ModuleFileIO::Test { + +thread_local std::shared_ptr AtomicfileMock::atomicfileMock = nullptr; +thread_local bool AtomicfileMock::mockable = false; + +std::shared_ptr AtomicfileMock::GetMock() +{ + if (atomicfileMock == nullptr) { + atomicfileMock = std::make_shared(); + } + return atomicfileMock; +} + +void AtomicfileMock::EnableMock() +{ + mockable = true; +} + +void AtomicfileMock::DisableMock() +{ + atomicfileMock = nullptr; + mockable = false; +} + +bool AtomicfileMock::IsMockable() +{ + return mockable; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test + +#ifdef __cplusplus +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +extern "C" { +int rename(const char *old_filename, const char *new_filename) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->rename(old_filename, new_filename); + } + + static int (*realRename)(const char *, const char *) = []() { + auto func = (int (*)(const char *, const char *))dlsym(RTLD_NEXT, "rename"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real rename: " << dlerror(); + } + return func; + }(); + + if (!realRename) { + return -1; + } + + return realRename(old_filename, new_filename); +} + +int remove(const char *filename) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->remove(filename); + } + + static int (*realRemove)(const char *) = []() { + auto func = (int (*)(const char *))dlsym(RTLD_NEXT, "remove"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real remove: " << dlerror(); + } + return func; + }(); + + if (!realRemove) { + return -1; + } + + return realRemove(filename); +} + +napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->napi_get_reference_value(env, ref, result); + } + + static napi_status (*realNapi)(napi_env, napi_ref, napi_value *) = []() { + auto func = (napi_status(*)(napi_env, napi_ref, napi_value *))dlsym(RTLD_NEXT, "napi_get_reference_value"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real napi_get_reference_value: " << dlerror(); + } + return func; + }(); + + if (!realNapi) { + return napi_ok; + } + + return realNapi(env, ref, result); +} + +napi_status napi_delete_reference(napi_env env, napi_ref ref) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->napi_delete_reference(env, ref); + } + + static napi_status (*realNapi)(napi_env, napi_ref) = []() { + auto func = (napi_status(*)(napi_env, napi_ref))dlsym(RTLD_NEXT, "napi_delete_reference"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real napi_delete_reference: " << dlerror(); + } + return func; + }(); + + if (!realNapi) { + return napi_ok; + } + + return realNapi(env, ref); +} + +napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->napi_unwrap(env, js_object, result); + } + + static napi_status (*realNapi)(napi_env, napi_value, void **) = []() { + auto func = (napi_status(*)(napi_env, napi_value, void **))dlsym(RTLD_NEXT, "napi_unwrap"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real napi_unwrap: " << dlerror(); + } + return func; + }(); + + if (!realNapi) { + return napi_ok; + } + + return realNapi(env, js_object, result); +} + +napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype *result) +{ + return AtomicfileMock::GetMock()->napi_typeof(env, value, result); +} +} // extern "C" + +bool NFuncArg::InitArgs(std::function argcChecker) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->InitArgs(argcChecker); + } + + static bool (*realInitArgs)(std::function) = []() { + auto func = (bool (*)(std::function))dlsym(RTLD_NEXT, "InitArgs"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real InitArgs: " << dlerror(); + } + return func; + }(); + + if (!realInitArgs) { + return false; + } + + return realInitArgs(argcChecker); +} + +napi_value NFuncArg::GetThisVar() const +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->GetThisVar(); + } + + static napi_value (*realGetThisVar)() = []() { + auto func = (napi_value(*)())dlsym(RTLD_NEXT, "GetThisVar"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real GetThisVar: " << dlerror(); + } + return func; + }(); + + if (!realGetThisVar) { + return nullptr; + } + + return realGetThisVar(); +} + +void NError::ThrowErr(napi_env env, std::string errMsg) +{ + if (AtomicfileMock::IsMockable()) { + return AtomicfileMock::GetMock()->ThrowErr(env, errMsg); + } + + static void (*realThrowErr)(napi_env, std::string) = []() { + auto func = (void (*)(napi_env, std::string))dlsym(RTLD_NEXT, "ThrowErr"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ThrowErr: " << dlerror(); + } + return func; + }(); + + if (!realThrowErr) { + return; + } + + return realThrowErr(env, errMsg); +} +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.h b/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.h new file mode 100644 index 000000000..125bf88af --- /dev/null +++ b/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.h @@ -0,0 +1,70 @@ +/* + * 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_CLASS_ATOMICFILE_MOCK_ATOMICFILE_MOCK_H +#define INTERFACES_TEST_UNITTEST_CLASS_ATOMICFILE_MOCK_ATOMICFILE_MOCK_H + +#include +#include +#include +#include "n_napi.h" +#include "atomicfile_entity.h" +#include "atomicfile_n_exporter.h" +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::LibN; + +class IAtomicfileMock { +public: + virtual ~IAtomicfileMock() = default; + virtual int rename(const char *old_filename, const char *new_filename) = 0; + virtual int remove(const char *filename) = 0; + virtual napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result) = 0; + virtual napi_status napi_delete_reference(napi_env env, napi_ref ref) = 0; + virtual bool InitArgs(std::function argcChecker) = 0; + virtual napi_value GetThisVar() = 0; + virtual napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) = 0; + virtual napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype *result) = 0; + virtual void ThrowErr(napi_env env, std::string errMsg) = 0; +}; + +class AtomicfileMock : public IAtomicfileMock { +public: + MOCK_METHOD(int, rename, (const char *, const char *), (override)); + MOCK_METHOD(int, remove, (const char *), (override)); + MOCK_METHOD(napi_status, napi_get_reference_value, (napi_env, napi_ref, napi_value *), (override)); + MOCK_METHOD(napi_status, napi_delete_reference, (napi_env, napi_ref), (override)); + MOCK_METHOD(bool, InitArgs, (std::function), (override)); + MOCK_METHOD(napi_value, GetThisVar, (), (override)); + MOCK_METHOD(napi_status, napi_unwrap, (napi_env, napi_value, void **), (override)); + MOCK_METHOD(napi_status, napi_typeof, (napi_env, napi_value, napi_valuetype *), (override)); + MOCK_METHOD(void, ThrowErr, (napi_env, std::string), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr atomicfileMock; + static thread_local bool mockable; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::Test +#endif // INTERFACES_TEST_UNITTEST_CLASS_ATOMICFILE_MOCK_ATOMICFILE_MOCK_H \ No newline at end of file -- Gitee From c6f6498d9707206e88f6ad555b4eb5c78e3e5f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Sat, 19 Jul 2025 16:59:58 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=84=8F=E8=A7=81=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 --- interfaces/test/unittest/class_atomicfile/BUILD.gn | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/interfaces/test/unittest/class_atomicfile/BUILD.gn b/interfaces/test/unittest/class_atomicfile/BUILD.gn index e53b3cfdb..70929306b 100644 --- a/interfaces/test/unittest/class_atomicfile/BUILD.gn +++ b/interfaces/test/unittest/class_atomicfile/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# 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 @@ -17,23 +17,19 @@ import("//foundation/filemanagement/file_api/file_api.gni") ohos_unittest("class_atomicfile_test") { module_out_path = "file_api/file_api" - resource_config_file = "../resource/ohos_test.xml" - sources = [ "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp", - "mock/atomicfile_mock.cpp", - "./atomicfile_mock_test.cpp", + "${file_api_path}/interfaces/test/unitest/class_atomicfile/mock/atomicfile_mock.cpp", + "${file_api_path}/interfaces/test/unitest/class_atomicfile/atomicfile_mock_test.cpp", ] include_dirs = [ "${file_api_path}/interfaces/kits/js/src/common", "${file_api_path}/interfaces/kits/js/src/common/file_helper", - # "${file_api_path}/interfaces/kits/js/src/common/napi", "${file_api_path}/interfaces/kits/js/src/mod_fs", "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", "${file_api_path}/interfaces/test/unittest/class_atomicfile/mock", - # "${filemanagement_service_path}/distributedfiledaemon/include/ipc", ] use_exceptions = true -- Gitee From c4443c478b1e6eea8d8603f2e054fe2a9b2e568f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E9=91=AB?= Date: Tue, 22 Jul 2025 01:24:18 +0000 Subject: [PATCH 3/3] update interfaces/test/unittest/class_atomicfile/BUILD.gn. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周鑫 --- interfaces/test/unittest/class_atomicfile/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/test/unittest/class_atomicfile/BUILD.gn b/interfaces/test/unittest/class_atomicfile/BUILD.gn index 70929306b..2b30daf8d 100644 --- a/interfaces/test/unittest/class_atomicfile/BUILD.gn +++ b/interfaces/test/unittest/class_atomicfile/BUILD.gn @@ -19,8 +19,8 @@ ohos_unittest("class_atomicfile_test") { sources = [ "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile/atomicfile_n_exporter.cpp", - "${file_api_path}/interfaces/test/unitest/class_atomicfile/mock/atomicfile_mock.cpp", - "${file_api_path}/interfaces/test/unitest/class_atomicfile/atomicfile_mock_test.cpp", + "${file_api_path}/interfaces/test/unittest/class_atomicfile/mock/atomicfile_mock.cpp", + "${file_api_path}/interfaces/test/unittest/class_atomicfile/atomicfile_mock_test.cpp", ] include_dirs = [ -- Gitee