diff --git a/interfaces/test/unittest/BUILD.gn b/interfaces/test/unittest/BUILD.gn index 9a3e2915ec3f109a57fc3638b5b85cec8f2c784f..4216079bdc2a078d529b4b3ad71fa3880eed3562 100644 --- a/interfaces/test/unittest/BUILD.gn +++ b/interfaces/test/unittest/BUILD.gn @@ -26,6 +26,7 @@ group("file_api_unittest") { "js:ani_file_securitylabel_test", "js:ani_file_statvfs_test", "js:napi_file_fs_test", + "napi_js:napi_fs_test", "remote_uri:remote_uri_test", "task_signal:task_signal_test", ] diff --git a/interfaces/test/unittest/napi_js/BUILD.gn b/interfaces/test/unittest/napi_js/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1b8c707432e4aca0732d30b73625ffdff608f37e --- /dev/null +++ b/interfaces/test/unittest/napi_js/BUILD.gn @@ -0,0 +1,75 @@ +# 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. + +import("//build/test.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +ohos_unittest("napi_fs_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + + 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/mod_fs/", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + "${file_api_path}/interfaces/test/unittest/napi_js/mod_fs/mock", + ] + + sources = [ + "${file_api_path}/interfaces/kits/js/src/common/file_helper/fd_guard.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/common_func.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/close.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/mkdtemp.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/read_text.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/rename.cpp", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/truncate.cpp", + "mod_fs/mock/libn_mock.cpp", + "mod_fs/mock/uv_fs_mock.cpp", + "mod_fs/properties/close_mock_test.cpp", + "mod_fs/properties/mkdtemp_mock_test.cpp", + "mod_fs/properties/read_text_mock_test.cpp", + "mod_fs/properties/rename_mock_test.cpp", + "mod_fs/properties/truncate_mock_test.cpp", + ] + + 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", + "ability_runtime:ability_manager", + "access_token:libtokenid_sdk", + "app_file_service:fileuri_native", + "c_utils:utils", + "dfs_service:distributed_file_daemon_kit_inner", + "dfs_service:libdistributedfileutils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:ipc_single", + "libuv:uv", + "napi:ace_napi", + "samgr:samgr_proxy", + ] + + defines = [ "private=public" ] + + use_exceptions = true +} diff --git a/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.cpp b/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..276aeb25a25c848b237452fe646517465202e5f6 --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.cpp @@ -0,0 +1,565 @@ +/* + * 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 "libn_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace OHOS::FileManagement::ModuleFileIO; + +thread_local std::shared_ptr LibnMock::libnMock = nullptr; +thread_local bool LibnMock::mockable = false; + +std::shared_ptr LibnMock::GetMock() +{ + if (libnMock == nullptr) { + libnMock = std::make_shared(); + } + return libnMock; +} + +void LibnMock::EnableMock() +{ + mockable = true; +} + +void LibnMock::DisableMock() +{ + libnMock = nullptr; + mockable = false; +} + +bool LibnMock::IsMockable() +{ + return mockable; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test + +#ifdef __cplusplus +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +extern "C" { +napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) +{ + if (LibnMock::IsMockable()) { + return LibnMock::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); +} + +} // extern "C" + +bool NFuncArg::InitArgs(std::function argcChecker) +{ + if (LibnMock::IsMockable()) { + return LibnMock::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); +} + +bool NFuncArg::InitArgs(size_t argc) +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->InitArgs(argc); + } + + static bool (*realInitArgs)(size_t) = []() { + auto func = (bool (*)(size_t))dlsym(RTLD_NEXT, "InitArgs"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real InitArgs: " << dlerror(); + } + return func; + }(); + + if (!realInitArgs) { + return false; + } + + return realInitArgs(argc); +} + +bool NFuncArg::InitArgs(size_t minArgc, size_t maxArgc) +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->InitArgs(minArgc, maxArgc); + } + + static bool (*realInitArgs)(size_t, size_t) = []() { + auto func = (bool (*)(size_t, size_t))dlsym(RTLD_NEXT, "InitArgs"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real InitArgs: " << dlerror(); + } + return func; + }(); + + if (!realInitArgs) { + return false; + } + + return realInitArgs(minArgc, maxArgc); +} + +size_t NFuncArg::GetArgc() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->GetArgc(); + } + + static size_t (*realGetArgc)() = []() { + auto func = (size_t (*)())dlsym(RTLD_NEXT, "GetArgc"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real GetArgc: " << dlerror(); + } + return func; + }(); + + if (!realGetArgc) { + return -1; + } + + return realGetArgc(); +} + +napi_value NFuncArg::GetThisVar() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::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(); +} + +napi_value NFuncArg::GetArg(size_t argPos) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->GetArg(argPos); + } + + static napi_value (*realGetArg)(size_t) = []() { + auto func = (napi_value (*)(size_t))dlsym(RTLD_NEXT, "GetArg"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real GetArg: " << dlerror(); + } + return func; + }(); + + if (!realGetArg) { + return nullptr; + } + + return realGetArg(argPos); +} + +void NError::ThrowErr(napi_env env) +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ThrowErr(env); + } + + static void (*realThrowErr)(napi_env) = []() { + auto func = (void (*)(napi_env))dlsym(RTLD_NEXT, "ThrowErr"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ThrowErr: " << dlerror(); + } + return func; + }(); + + if (!realThrowErr) { + return; + } + + return realThrowErr(env); +} + +void NError::ThrowErr(napi_env env, int errCode) +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ThrowErr(env, errCode); + } + + static void (*realThrowErr)(napi_env, int) = []() { + auto func = (void (*)(napi_env, int))dlsym(RTLD_NEXT, "ThrowErr"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ThrowErr: " << dlerror(); + } + return func; + }(); + + if (!realThrowErr) { + return; + } + + return realThrowErr(env, errCode); +} + +void NError::ThrowErr(napi_env env, std::string errMsg) +{ + if (LibnMock::IsMockable()) { + return LibnMock::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); +} + +void NError::ThrowErrAddData(napi_env env, int errCode, napi_value data) +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ThrowErrAddData(env, errCode, data); + } + + static void (*realThrowErr)(napi_env, int, napi_value) = []() { + auto func = (void (*)(napi_env, int, napi_value))dlsym(RTLD_NEXT, "ThrowErrAddData"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ThrowErrAddData: " << dlerror(); + } + return func; + }(); + + if (!realThrowErr) { + return; + } + + return realThrowErr(env, errCode, data); +} + +std::tuple, size_t> NVal::ToUTF8String() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToUTF8String(); + } + + static std::tuple, size_t> (*realToUTF8String)() = []() { + auto func = (std::tuple, size_t> (*)())dlsym(RTLD_NEXT, "ToUTF8String"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToUTF8String: " << dlerror(); + } + return func; + }(); + + if (!realToUTF8String) { + return { false, nullptr, -1 }; + } + + return realToUTF8String(); +} + +std::tuple, size_t> NVal::ToUTF8String(std::string defaultValue) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToUTF8String(defaultValue); + } + + static std::tuple, size_t> (*realToUTF8String)(std::string) = []() { + auto func = (std::tuple, size_t> + (*)(std::string))dlsym(RTLD_NEXT, "ToUTF8String"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToUTF8String: " << dlerror(); + } + return func; + }(); + + if (!realToUTF8String) { + return { false, nullptr, -1 }; + } + + return realToUTF8String(defaultValue); +} + +std::tuple, size_t> NVal::ToUTF8StringPath() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToUTF8StringPath(); + } + + static std::tuple, size_t> (*realToUTF8StringPath)() = []() { + auto func = (std::tuple, size_t>(*)())dlsym(RTLD_NEXT, "ToUTF8StringPath"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToUTF8StringPath: " << dlerror(); + } + return func; + }(); + + if (!realToUTF8StringPath) { + return { false, nullptr, -1 }; + } + + return realToUTF8StringPath(); +} + +std::tuple NVal::ToBool() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToBool(); + } + + static std::tuple (*realToBool)() = []() { + auto func = (std::tuple (*)())dlsym(RTLD_NEXT, "ToBool"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToBool: " << dlerror(); + } + return func; + }(); + + if (!realToBool) { + return { false, false }; + } + + return realToBool(); +} + +std::tuple NVal::ToBool(bool defaultValue) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToBool(defaultValue); + } + + static std::tuple (*realToBool)(bool) = []() { + auto func = (std::tuple (*)(bool))dlsym(RTLD_NEXT, "ToBool"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToBool: " << dlerror(); + } + return func; + }(); + + if (!realToBool) { + return { false, false }; + } + + return realToBool(defaultValue); +} + +std::tuple NVal::ToInt32() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToInt32(); + } + + static std::tuple (*realToInt32)() = []() { + auto func = (std::tuple (*)())dlsym(RTLD_NEXT, "ToInt32"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToInt32: " << dlerror(); + } + return func; + }(); + + if (!realToInt32) { + return { false, 0 }; + } + + return realToInt32(); +} + +std::tuple NVal::ToInt32(int32_t defaultValue) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToInt32(defaultValue); + } + + static std::tuple (*realToInt32)(int32_t) = []() { + auto func = (std::tuple (*)(int32_t))dlsym(RTLD_NEXT, "ToInt32"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToInt32: " << dlerror(); + } + return func; + }(); + + if (!realToInt32) { + return { false, 0 }; + } + + return realToInt32(defaultValue); +} + +std::tuple NVal::ToInt64() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToInt64(); + } + + static std::tuple (*realToInt64)() = []() { + auto func = (std::tuple (*)())dlsym(RTLD_NEXT, "ToInt64"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToInt64: " << dlerror(); + } + return func; + }(); + + if (!realToInt64) { + return { false, 0 }; + } + + return realToInt64(); +} + +std::tuple NVal::ToInt64(int64_t defaultValue) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToInt64(defaultValue); + } + + static std::tuple (*realToInt64)(int64_t) = []() { + auto func = (std::tuple (*)(int64_t))dlsym(RTLD_NEXT, "ToInt64"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToInt64: " << dlerror(); + } + return func; + }(); + + if (!realToInt64) { + return { false, 0 }; + } + + return realToInt64(defaultValue); +} + +std::tuple NVal::ToDouble() const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->ToDouble(); + } + + static std::tuple (*realToDouble)() = []() { + auto func = (std::tuple (*)())dlsym(RTLD_NEXT, "ToDouble"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ToDouble: " << dlerror(); + } + return func; + }(); + + if (!realToDouble) { + return { false, 0 }; + } + + return realToDouble(); +} + +bool NVal::HasProp(std::string propName) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->HasProp(propName); + } + + static bool (*realHasProp)(std::string) = []() { + auto func = (bool (*)(std::string))dlsym(RTLD_NEXT, "HasProp"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real HasProp: " << dlerror(); + } + return func; + }(); + + if (!realHasProp) { + return false; + } + + return realHasProp(propName); +} + +NVal NVal::GetProp(std::string propName) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->GetProp(propName); + } + + static NVal (*realGetProp)(std::string) = []() { + auto func = (NVal (*)(std::string))dlsym(RTLD_NEXT, "GetProp"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real GetProp: " << dlerror(); + } + return func; + }(); + + if (!realGetProp) { + napi_env env = reinterpret_cast(0x1000); + napi_value val = reinterpret_cast(0x1000); + NVal myOp(env, val); + return myOp; + } + + return realGetProp(propName); +} + +bool NVal::TypeIs(napi_valuetype expType) const +{ + if (LibnMock::IsMockable()) { + return LibnMock::GetMock()->TypeIs(expType); + } + + static bool (*realTypeIs)(napi_valuetype) = []() { + auto func = (bool (*)(napi_valuetype))dlsym(RTLD_NEXT, "TypeIs"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real TypeIs: " << dlerror(); + } + return func; + }(); + + if (!realTypeIs) { + return false; + } + + return realTypeIs(expType); +} +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.h b/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..25b3d9b4811564d17d652f27b4bfd2e2b16eefe5 --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/mock/libn_mock.h @@ -0,0 +1,111 @@ +/* + * 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_NAPI_JS_MOD_FS_MOCK_LIBN_MOCK_H +#define INTERFACES_TEST_UNITTEST_NAPI_JS_MOD_FS_MOCK_LIBN_MOCK_H + +#include +#include + +#include "filemgmt_libn.h" +#include "n_napi.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::LibN; + +class ILibnMock { +public: + virtual ~ILibnMock() = default; + + // n_func_arg + virtual bool InitArgs(std::function argcChecker) = 0; + virtual bool InitArgs(size_t argc) = 0; + virtual bool InitArgs(size_t minArgc, size_t maxArgc) = 0; + virtual size_t GetArgc() = 0; + virtual napi_value GetArg(size_t argPos) = 0; + virtual napi_value GetThisVar() = 0; + + // n_class GetEntityOf + virtual napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) = 0; + + // n_error + virtual void ThrowErr(napi_env env) = 0; + virtual void ThrowErr(napi_env env, int errCode) = 0; + virtual void ThrowErr(napi_env env, std::string errMsg) = 0; + virtual void ThrowErrAddData(napi_env env, int errCode, napi_value data) = 0; + + // n_val + virtual std::tuple, size_t> ToUTF8String() = 0; + virtual std::tuple, size_t> ToUTF8String(std::string defaultValue) = 0; + virtual std::tuple, size_t> ToUTF8StringPath() = 0; + virtual std::tuple ToBool() = 0; + virtual std::tuple ToBool(bool defaultValue) = 0; + virtual std::tuple ToInt32() = 0; + virtual std::tuple ToInt32(int32_t defaultValue) = 0; + virtual std::tuple ToInt64() = 0; + virtual std::tuple ToInt64(int64_t defaultValue) = 0; + virtual std::tuple ToDouble() = 0; + + virtual bool HasProp(std::string propName) = 0; + virtual NVal GetProp(std::string propName) = 0; + virtual bool TypeIs(napi_valuetype expType) = 0; +}; + +class LibnMock : public ILibnMock { +public: + MOCK_METHOD(bool, InitArgs, (std::function), (override)); + MOCK_METHOD(bool, InitArgs, (size_t), (override)); + MOCK_METHOD(bool, InitArgs, (size_t, size_t), (override)); + MOCK_METHOD(size_t, GetArgc, (), (override)); + MOCK_METHOD(napi_value, GetArg, (size_t), (override)); + MOCK_METHOD(napi_value, GetThisVar, (), (override)); + + MOCK_METHOD(napi_status, napi_unwrap, (napi_env, napi_value, void **), (override)); + + MOCK_METHOD(void, ThrowErr, (napi_env), (override)); + MOCK_METHOD(void, ThrowErr, (napi_env, int), (override)); + MOCK_METHOD(void, ThrowErr, (napi_env, std::string), (override)); + MOCK_METHOD(void, ThrowErrAddData, (napi_env, int, napi_value), (override)); + + MOCK_METHOD((std::tuple, size_t>), ToUTF8String, (), (override)); + MOCK_METHOD((std::tuple, size_t>), ToUTF8String, (std::string), (override)); + MOCK_METHOD((std::tuple, size_t>), ToUTF8StringPath, (), (override)); + MOCK_METHOD((std::tuple), ToBool, (), (override)); + MOCK_METHOD((std::tuple), ToBool, (bool), (override)); + MOCK_METHOD((std::tuple), ToInt32, (), (override)); + MOCK_METHOD((std::tuple), ToInt32, (int32_t), (override)); + MOCK_METHOD((std::tuple), ToInt64, (), (override)); + MOCK_METHOD((std::tuple), ToInt64, (int64_t), (override)); + MOCK_METHOD((std::tuple), ToDouble, (), (override)); + + MOCK_METHOD(bool, HasProp, (std::string), (override)); + MOCK_METHOD(NVal, GetProp, (std::string), (override)); + MOCK_METHOD(bool, TypeIs, (napi_valuetype), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr libnMock; + static thread_local bool mockable; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::Test +#endif // INTERFACES_TEST_UNITTEST_NAPI_JS_MOD_FS_MOCK_LIBN_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.cpp b/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af939f1375ba058d8e2c4887a35264d3dce97fc6 --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.cpp @@ -0,0 +1,183 @@ +/* + * 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 "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace OHOS::FileManagement::ModuleFileIO; + +thread_local std::shared_ptr UvfsMock::uvfsMock = nullptr; +thread_local bool UvfsMock::mockable = false; + +std::shared_ptr UvfsMock::GetMock() +{ + if (uvfsMock == nullptr) { + uvfsMock = std::make_shared(); + } + return uvfsMock; +} + +void UvfsMock::EnableMock() +{ + mockable = true; +} + +void UvfsMock::DisableMock() +{ + uvfsMock = nullptr; + mockable = false; +} + +bool UvfsMock::IsMockable() +{ + return mockable; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test + +#ifdef __cplusplus +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_close(loop, req, file, cb); + } + + static int (*realUvFsClose)(uv_loop_t *, uv_fs_t *, uv_file, uv_fs_cb) = []() { + auto func = (int (*)(uv_loop_t *, uv_fs_t *, uv_file, uv_fs_cb))dlsym(RTLD_NEXT, "uv_fs_close"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_close: " << dlerror(); + } + return func; + }(); + + if (!realUvFsClose) { + return -1; + } + + return realUvFsClose(loop, req, file, cb); +} + +int uv_fs_mkdtemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_mkdtemp(loop, req, tpl, cb); + } + + static int (*realUvFsMkdtemp)(uv_loop_t *, uv_fs_t *, const char *, uv_fs_cb) = []() { + auto func = (int (*)(uv_loop_t *, uv_fs_t *, const char *, uv_fs_cb))dlsym(RTLD_NEXT, "uv_fs_mkdtemp"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_mkdtemp: " << dlerror(); + } + return func; + }(); + + if (!realUvFsMkdtemp) { + return -1; + } + + return realUvFsMkdtemp(loop, req, tpl, cb); +} + +int uv_fs_rename(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *newPath, uv_fs_cb cb) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_rename(loop, req, path, newPath, cb); + } + + static int (*realUvFsRename)(uv_loop_t *, uv_fs_t *, const char *, const char *, uv_fs_cb) = []() { + auto func = + (int (*)(uv_loop_t *, uv_fs_t *, const char *, const char *, uv_fs_cb))dlsym(RTLD_NEXT, "uv_fs_rename"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_rename: " << dlerror(); + } + return func; + }(); + + if (!realUvFsRename) { + return -1; + } + + return realUvFsRename(loop, req, path, newPath, cb); +} + +int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_open(loop, req, path, flags, mode, cb); + } + + static int (*realUvFsOpen)(uv_loop_t *, uv_fs_t *, const char *, int, int, uv_fs_cb) = []() { + auto func = + (int (*)(uv_loop_t *, uv_fs_t *, const char *, int, int, uv_fs_cb))dlsym(RTLD_NEXT, "uv_fs_open"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_open: " << dlerror(); + } + return func; + }(); + + if (!realUvFsOpen) { + return -1; + } + + return realUvFsOpen(loop, req, path, flags, mode, cb); +} + +int uv_fs_ftruncate(uv_loop_t *loop, uv_fs_t *req, uv_file fd, int64_t offset, uv_fs_cb cb) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_ftruncate(loop, req, fd, offset, cb); + } + + static int (*realUvFsTruncate)(uv_loop_t *, uv_fs_t *, uv_file, int64_t, uv_fs_cb) = []() { + auto func = + (int (*)(uv_loop_t *, uv_fs_t *, uv_file, int64_t, uv_fs_cb))dlsym(RTLD_NEXT, "uv_fs_ftruncate"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_ftruncate: " << dlerror(); + } + return func; + }(); + + if (!realUvFsTruncate) { + return -1; + } + + return realUvFsTruncate(loop, req, fd, offset, cb); +} + +void uv_fs_req_cleanup(uv_fs_t* req) +{ + if (UvfsMock::IsMockable()) { + return UvfsMock::GetMock()->uv_fs_req_cleanup(req); + } + + static void (*realUvFsReqCleanup)(uv_fs_t *) = []() { + auto func = (void (*)(uv_fs_t *))dlsym(RTLD_NEXT, "uv_fs_req_cleanup"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real uv_fs_req_cleanup: " << dlerror(); + } + return func; + }(); + + if (!realUvFsReqCleanup) { + return; + } + + return realUvFsReqCleanup(req); +} +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.h b/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..7cf60d72464239c6e8a2de139d15a4500eeff95d --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/mock/uv_fs_mock.h @@ -0,0 +1,62 @@ +/* + * 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_NAPI_JS_MOD_FS_MOCK_UV_FS_MOCK_H +#define INTERFACES_TEST_UNITTEST_NAPI_JS_MOD_FS_MOCK_UV_FS_MOCK_H + +#include "uv.h" +#include "filemgmt_libn.h" + +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::LibN; + +class IUvfsMock { +public: + virtual ~IUvfsMock() = default; + virtual int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb) = 0; + virtual int uv_fs_mkdtemp(uv_loop_t *loop, uv_fs_t *req, const char *tpl, uv_fs_cb cb) = 0; + virtual int uv_fs_rename(uv_loop_t *loop, uv_fs_t *req, const char *path, const char *newPath, uv_fs_cb cb) = 0; + virtual int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb) = 0; + virtual int uv_fs_ftruncate(uv_loop_t *loop, uv_fs_t *req, uv_file fd, int64_t offset, uv_fs_cb cb) = 0; + virtual void uv_fs_req_cleanup(uv_fs_t* req) = 0; +}; + +class UvfsMock : public IUvfsMock { +public: + MOCK_METHOD(int, uv_fs_close, (uv_loop_t *, uv_fs_t *, uv_file, uv_fs_cb), (override)); + MOCK_METHOD(int, uv_fs_mkdtemp, (uv_loop_t *, uv_fs_t *, const char *, uv_fs_cb), (override)); + MOCK_METHOD(int, uv_fs_rename, (uv_loop_t *, uv_fs_t *, const char *, const char *, uv_fs_cb), (override)); + MOCK_METHOD(int, uv_fs_open, (uv_loop_t *, uv_fs_t *, const char *, int, int, uv_fs_cb), (override)); + MOCK_METHOD(int, uv_fs_ftruncate, (uv_loop_t *, uv_fs_t *, uv_file, int64_t, uv_fs_cb), (override)); + MOCK_METHOD(void, uv_fs_req_cleanup, (uv_fs_t *), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr uvfsMock; + static thread_local bool mockable; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::Test +#endif // INTERFACES_TEST_UNITTEST_NAPI_JS_MOD_FS_MOCK_UV_FS_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/properties/close_mock_test.cpp b/interfaces/test/unittest/napi_js/mod_fs/properties/close_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a51a61771557a7c4d0eaccf0b38f8c3777df9e9 --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/properties/close_mock_test.cpp @@ -0,0 +1,79 @@ +/* + * 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 "close.h" +#include "libn_mock.h" +#include "uv_fs_mock.h" + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +class CloseMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + LibnMock::EnableMock(); + UvfsMock::EnableMock(); + }; + static void TearDownTestCase() + { + LibnMock::DisableMock(); + UvfsMock::DisableMock(); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: CloseFd_0001 + * @tc.desc: Test function of CloseFd() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CloseMockTest, CloseFd_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseMockTest-begin CloseFd_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + + tuple isFd = { true, 1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::A())).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToInt32()).WillOnce(testing::Return(isFd)); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)); + EXPECT_CALL(*uvMock_, uv_fs_close(testing::_, testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = Close::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "CloseMockTest-end CloseFd_0001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/properties/mkdtemp_mock_test.cpp b/interfaces/test/unittest/napi_js/mod_fs/properties/mkdtemp_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d81e1752e3d33757c95af888bd5b1234fd1ae724 --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/properties/mkdtemp_mock_test.cpp @@ -0,0 +1,90 @@ +/* + * 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 "mkdtemp.h" + +#include +#include +#include +#include + +#include "libn_mock.h" +#include "securec.h" +#include "uv_fs_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +class MkdtempMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + LibnMock::EnableMock(); + UvfsMock::EnableMock(); + }; + static void TearDownTestCase() + { + LibnMock::DisableMock(); + UvfsMock::DisableMock(); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: MkdtempSync_0001 + * @tc.desc: Test function of MkdtempSync() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MkdtempMockTest, MkdtempSync_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdtempMockTest-begin MkdtempSync_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + + const char *initStr = "hello world"; + size_t strLen = strlen(initStr) + 1; + auto strPtr = make_unique(strLen); + ASSERT_NE(strPtr, nullptr); + auto ret = strncpy_s(strPtr.get(), strLen, initStr, strLen - 1); + ASSERT_EQ(ret, EOK); + + tuple, size_t> toUtfRes = { true, move(strPtr), 1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::A())).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToUTF8StringPath()).WillOnce(testing::Return(move(toUtfRes))); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)); + EXPECT_CALL(*uvMock_, uv_fs_mkdtemp(testing::_, testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = Mkdtemp::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "MkdtempMockTest-end MkdtempSync_0001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/properties/read_text_mock_test.cpp b/interfaces/test/unittest/napi_js/mod_fs/properties/read_text_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a0394dfc9d1321878c249bfae3705f2fcf7428c --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/properties/read_text_mock_test.cpp @@ -0,0 +1,96 @@ +/* + * 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 "read_text.h" + +#include +#include +#include +#include + +#include "libn_mock.h" +#include "securec.h" +#include "uv_fs_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +class ReadTextMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + LibnMock::EnableMock(); + UvfsMock::EnableMock(); + }; + static void TearDownTestCase() + { + LibnMock::DisableMock(); + UvfsMock::DisableMock(); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: ReadTextSync_0001 + * @tc.desc: Test function of ReadTextSync() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadTextMockTest, ReadTextSync_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadTextMockTest-begin ReadTextSync_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + napi_value val = reinterpret_cast(0x1000); + NVal myOp(env, val); + + const char *initStr = "hello world"; + size_t strLen = strlen(initStr) + 1; + auto strPtr = make_unique(strLen); + ASSERT_NE(strPtr, nullptr); + auto ret = strncpy_s(strPtr.get(), strLen, initStr, strLen - 1); + ASSERT_EQ(ret, EOK); + + tuple, size_t> toUtfRes = { true, move(strPtr), 1 }; + tuple toIntRes = { false, -1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::_, testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToUTF8StringPath()).WillOnce(testing::Return(move(toUtfRes))); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)); + EXPECT_CALL(*libnMock_, HasProp(testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, GetProp(testing::_)).Times(2).WillRepeatedly(testing::Return(myOp)); + EXPECT_CALL(*libnMock_, TypeIs(testing::_)).WillOnce(testing::Return(false)); + EXPECT_CALL(*libnMock_, ToInt64()).WillOnce(testing::Return(toIntRes)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = ReadText::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "ReadTextMockTest-end ReadTextSync_0001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/properties/rename_mock_test.cpp b/interfaces/test/unittest/napi_js/mod_fs/properties/rename_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92cea27cd87dbf9cfa7b8d1c9f9d6d8263ee3dcb --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/properties/rename_mock_test.cpp @@ -0,0 +1,103 @@ +/* + * 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 "rename.h" + +#include +#include +#include +#include + +#include "libn_mock.h" +#include "securec.h" +#include "uv_fs_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +class RenameMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + LibnMock::EnableMock(); + UvfsMock::EnableMock(); + }; + static void TearDownTestCase() + { + LibnMock::DisableMock(); + UvfsMock::DisableMock(); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: RenameSync_0001 + * @tc.desc: Test function of RenameSync() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(RenameMockTest, RenameSync_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "RenameMockTest-begin RenameSync_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + napi_value val = reinterpret_cast(0x1000); + NVal myOp(env, val); + + const char *initSrc = "hello world"; + size_t strLen = strlen(initSrc) + 1; + auto srcPtr = make_unique(strLen); + ASSERT_NE(srcPtr, nullptr); + auto ret = strncpy_s(srcPtr.get(), strLen, initSrc, strLen - 1); + ASSERT_EQ(ret, EOK); + + const char *initDest = "hello world"; + strLen = strlen(initDest) + 1; + auto destPtr = make_unique(strLen); + ASSERT_NE(destPtr, nullptr); + ret = strncpy_s(destPtr.get(), strLen, initDest, strLen - 1); + ASSERT_EQ(ret, EOK); + + tuple, size_t> srcRes = { true, move(srcPtr), 1 }; + tuple, size_t> destRes = { true, move(destPtr), 1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::_, testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToUTF8StringPath()) + .WillOnce(testing::Return(move(srcRes))) + .WillOnce(testing::Return(move(destRes))); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)); + EXPECT_CALL(*uvMock_, uv_fs_rename(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(-1)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = Rename::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "RenameMockTest-end RenameSync_0001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/napi_js/mod_fs/properties/truncate_mock_test.cpp b/interfaces/test/unittest/napi_js/mod_fs/properties/truncate_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dea6e7a03c4d4f69930c18d39065f08bf5ffd6b --- /dev/null +++ b/interfaces/test/unittest/napi_js/mod_fs/properties/truncate_mock_test.cpp @@ -0,0 +1,139 @@ +/* + * 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 "truncate.h" + +#include +#include +#include +#include + +#include "libn_mock.h" +#include "securec.h" +#include "uv_fs_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; +using namespace std::filesystem; +using namespace OHOS::FileManagement::ModuleFileIO; + +class TruncateMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + LibnMock::EnableMock(); + UvfsMock::EnableMock(); + }; + static void TearDownTestCase() + { + LibnMock::DisableMock(); + UvfsMock::DisableMock(); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: TruncateSync_0001 + * @tc.desc: Test function of TruncateSync() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TruncateMockTest, TruncateSync_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TruncateMockTest-begin TruncateSync_0001"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + napi_value val = reinterpret_cast(0x1000); + NVal myOp(env, val); + + const char *initSrc = "hello world"; + size_t strLen = strlen(initSrc) + 1; + auto srcPtr = make_unique(strLen); + ASSERT_NE(srcPtr, nullptr); + auto ret = strncpy_s(srcPtr.get(), strLen, initSrc, strLen - 1); + ASSERT_EQ(ret, EOK); + + tuple, size_t> srcRes = { true, move(srcPtr), 1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::_, testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToUTF8StringPath()).WillOnce(testing::Return(move(srcRes))); + EXPECT_CALL(*libnMock_, GetArgc()).WillOnce(testing::Return(move(NARG_CNT::ONE))); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)).Times(2); + EXPECT_CALL(*uvMock_, uv_fs_open(testing::_, testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(1)); + EXPECT_CALL(*uvMock_, uv_fs_ftruncate(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(-1)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = Truncate::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "TruncateMockTest-end TruncateSync_0001"; +} + +/** + * @tc.name: TruncateSync_0002 + * @tc.desc: Test function of TruncateSync() interface for fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TruncateMockTest, TruncateSync_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TruncateMockTest-begin TruncateSync_0002"; + napi_env env = reinterpret_cast(0x1000); + napi_callback_info info = reinterpret_cast(0x1000); + napi_value val = reinterpret_cast(0x1000); + NVal myOp(env, val); + + const char *initSrc = "hello world"; + size_t strLen = strlen(initSrc) + 1; + auto srcPtr = make_unique(strLen); + ASSERT_NE(srcPtr, nullptr); + auto ret = strncpy_s(srcPtr.get(), strLen, initSrc, strLen - 1); + ASSERT_EQ(ret, EOK); + + tuple, size_t> srcRes = { false, move(srcPtr), 1 }; + tuple isFd = { true, 1 }; + + auto libnMock_ = LibnMock::GetMock(); + auto uvMock_ = UvfsMock::GetMock(); + EXPECT_CALL(*libnMock_, InitArgs(testing::_, testing::_)).WillOnce(testing::Return(true)); + EXPECT_CALL(*libnMock_, ToUTF8StringPath()).WillOnce(testing::Return(move(srcRes))); + EXPECT_CALL(*libnMock_, ToInt32()).WillOnce(testing::Return(isFd)); + + EXPECT_CALL(*libnMock_, GetArgc()).WillOnce(testing::Return(move(NARG_CNT::ONE))); + EXPECT_CALL(*uvMock_, uv_fs_req_cleanup(testing::_)); + EXPECT_CALL(*uvMock_, uv_fs_ftruncate(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(-1)); + EXPECT_CALL(*libnMock_, ThrowErr(testing::_)); + + auto res = Truncate::Sync(env, info); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "TruncateMockTest-end TruncateSync_0002"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file