From ab06d9bd4e0588dac0dd5a830269d8a5eed0c353 Mon Sep 17 00:00:00 2001 From: zxl <1554188414@qq.com> Date: Sat, 5 Jul 2025 21:18:11 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=9B=9E=E5=90=880702?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I772039d30896086fa488f361c7c5c95af1049c1f Signed-off-by: liyuke --- interfaces/kits/js/BUILD.gn | 223 ++- .../js/src/common/ani_helper/ani_helper.h | 2 +- .../src/common/ani_helper/ani_signature.cpp | 17 + .../js/src/common/ani_helper/ani_signature.h | 29 + .../src/common/ani_helper/type_converter.cpp | 40 +- .../js/src/common/ani_helper/type_converter.h | 4 +- interfaces/kits/js/src/common/fs_filefiter.h | 117 ++ .../ani/bind_function_class.cpp | 73 + .../mod_environment/ani/environment_ani.cpp | 175 +++ .../src/mod_environment/ani/environment_ani.h | 42 + .../ani/ets/@ohos.file.environment.ets | 103 ++ .../src/mod_environment/environment_core.cpp | 204 +++ .../js/src/mod_environment/environment_core.h | 36 + .../js/src/mod_fs/ani/bind_function_class.cpp | 173 ++- .../js/src/mod_fs/ani/ets/@ohos.file.fs.ets | 765 +++++----- .../class_atomicfile/ani/atomicfile_ani.cpp | 367 +++++ .../class_atomicfile/ani/atomicfile_ani.h | 43 + .../mod_fs/class_atomicfile/fs_atomicfile.cpp | 235 +++ .../mod_fs/class_atomicfile/fs_atomicfile.h | 57 + .../class_atomicfile/fs_atomicfile_entity.h | 31 + .../ani/randomaccessfile_ani.cpp | 488 ++++++ .../ani/randomaccessfile_ani.h | 40 + .../fs_randomaccessfile.cpp | 287 ++++ .../fs_randomaccessfile.h | 84 ++ .../randomaccessfile_entity.h | 2 +- .../ani/reader_iterator_ani.cpp | 104 ++ .../ani/reader_iterator_ani.h | 39 + .../ani/reader_iterator_result_ani.cpp | 78 + .../ani/reader_iterator_result_ani.h | 37 + .../fs_reader_iterator.cpp | 70 + .../class_readeriterator/fs_reader_iterator.h | 45 + .../src/mod_fs/class_stat/ani/lstat_ani.cpp | 66 + .../js/src/mod_fs/class_stat/ani/lstat_ani.h | 33 + .../mod_fs/class_stat/ani/stat_wrapper.cpp | 9 +- .../mod_fs/class_stream/ani/stream_ani.cpp | 290 ++++ .../src/mod_fs/class_stream/ani/stream_ani.h | 40 + .../class_stream/ani/stream_wrapper.cpp | 78 + .../mod_fs/class_stream/ani/stream_wrapper.h | 37 + .../js/src/mod_fs/class_stream/fs_stream.cpp | 292 ++++ .../js/src/mod_fs/class_stream/fs_stream.h | 74 + .../class_stream/stream_instantiator.cpp | 79 + .../mod_fs/class_stream/stream_instantiator.h | 35 + .../class_tasksignal/ani/task_signal_ani.cpp | 70 + .../class_tasksignal/ani/task_signal_ani.h | 36 + .../ani/task_signal_listener_ani.cpp | 63 + .../ani/task_signal_listener_ani.h | 47 + .../ani/task_signal_wrapper.cpp | 71 + .../ani/task_signal_wrapper.h | 37 + .../class_tasksignal/fs_task_signal.cpp | 79 + .../mod_fs/class_tasksignal/fs_task_signal.h | 50 + .../class_watcher/ani/fs_watcher_ani.cpp | 68 + .../mod_fs/class_watcher/ani/fs_watcher_ani.h | 36 + .../class_watcher/ani/fs_watcher_wrapper.cpp | 73 + .../class_watcher/ani/fs_watcher_wrapper.h | 37 + .../ani/watch_event_listener.cpp | 114 ++ .../class_watcher/ani/watch_event_listener.h | 48 + .../class_watcher/ani/watch_event_wrapper.cpp | 66 + .../class_watcher/ani/watch_event_wrapper.h | 37 + .../mod_fs/class_watcher/fs_file_watcher.cpp | 348 +++++ .../mod_fs/class_watcher/fs_file_watcher.h | 79 + .../mod_fs/class_watcher/fs_watch_entity.h | 50 + .../src/mod_fs/class_watcher/fs_watcher.cpp | 78 + .../js/src/mod_fs/class_watcher/fs_watcher.h | 48 + .../mod_fs/class_watcher/i_watcher_callback.h | 32 + .../class_watcher/watcher_data_cache.cpp | 162 ++ .../mod_fs/class_watcher/watcher_data_cache.h | 54 + .../src/mod_fs/properties/ani/close_ani.cpp | 2 +- .../mod_fs/properties/ani/connectdfs_ani.cpp | 95 ++ .../mod_fs/properties/ani/connectdfs_ani.h | 54 + .../js/src/mod_fs/properties/ani/copy_ani.cpp | 170 +++ .../js/src/mod_fs/properties/ani/copy_ani.h | 34 + .../mod_fs/properties/ani/copy_dir_ani.cpp | 165 ++ .../src/mod_fs/properties/ani/copy_dir_ani.h | 34 + .../ani/create_randomaccessfile_ani.cpp | 218 +++ .../ani/create_randomaccessfile_ani.h | 37 + .../properties/ani/create_stream_ani.cpp | 71 + .../mod_fs/properties/ani/create_stream_ani.h | 34 + .../properties/ani/disconnectdfs_ani.cpp | 46 + .../mod_fs/properties/ani/disconnectdfs_ani.h | 38 + .../js/src/mod_fs/properties/ani/dup_ani.cpp | 52 + .../js/src/mod_fs/properties/ani/dup_ani.h | 35 + .../mod_fs/properties/ani/fdatasync_ani.cpp | 44 + .../src/mod_fs/properties/ani/fdatasync_ani.h | 36 + .../properties/ani/fdopen_stream_ani.cpp | 62 + .../mod_fs/properties/ani/fdopen_stream_ani.h | 33 + .../src/mod_fs/properties/ani/fsync_ani.cpp | 41 + .../js/src/mod_fs/properties/ani/fsync_ani.h | 35 + .../mod_fs/properties/ani/listfile_ani.cpp | 8 +- .../src/mod_fs/properties/ani/listfile_ani.h | 4 +- .../src/mod_fs/properties/ani/lseek_ani.cpp | 63 + .../js/src/mod_fs/properties/ani/lseek_ani.h | 34 + .../src/mod_fs/properties/ani/mkdtemp_ani.cpp | 60 + .../src/mod_fs/properties/ani/mkdtemp_ani.h | 36 + .../src/mod_fs/properties/ani/movedir_ani.cpp | 155 ++ .../src/mod_fs/properties/ani/movedir_ani.h | 36 + .../mod_fs/properties/ani/read_lines_ani.cpp | 88 ++ .../mod_fs/properties/ani/read_lines_ani.h | 36 + .../src/mod_fs/properties/ani/rename_ani.cpp | 54 + .../js/src/mod_fs/properties/ani/rename_ani.h | 35 + .../src/mod_fs/properties/ani/symlink_ani.cpp | 53 + .../src/mod_fs/properties/ani/symlink_ani.h | 35 + .../src/mod_fs/properties/ani/utimes_ani.cpp | 48 + .../js/src/mod_fs/properties/ani/utimes_ani.h | 36 + .../src/mod_fs/properties/ani/watcher_ani.cpp | 79 + .../src/mod_fs/properties/ani/watcher_ani.h | 36 + .../src/mod_fs/properties/ani/xattr_ani.cpp | 98 ++ .../js/src/mod_fs/properties/ani/xattr_ani.h | 38 + .../src/mod_fs/properties/connectdfs_core.cpp | 50 + .../src/mod_fs/properties/connectdfs_core.h | 41 + .../js/src/mod_fs/properties/copy_core.cpp | 887 +++++++++++ .../kits/js/src/mod_fs/properties/copy_core.h | 192 +++ .../src/mod_fs/properties/copy_dir_core.cpp | 257 ++++ .../js/src/mod_fs/properties/copy_dir_core.h | 59 + .../ani/progress_listener_ani.cpp | 93 ++ .../copy_listener/ani/progress_listener_ani.h | 39 + .../copy_listener/i_progress_listener.h | 31 + .../copy_listener/trans_listener_core.cpp | 318 ++++ .../copy_listener/trans_listener_core.h | 70 + .../create_randomaccessfile_core.cpp | 208 +++ .../properties/create_randomaccessfile_core.h | 45 + .../mod_fs/properties/create_stream_core.cpp | 44 + .../mod_fs/properties/create_stream_core.h | 39 + .../dfs_listener/file_dfs_listener_stub.cpp | 74 + .../dfs_listener/file_dfs_listener_stub.h | 46 + .../mod_fs/properties/disconnectdfs_core.cpp | 50 + .../mod_fs/properties/disconnectdfs_core.h | 33 + .../js/src/mod_fs/properties/dup_core.cpp | 65 + .../kits/js/src/mod_fs/properties/dup_core.h | 30 + .../src/mod_fs/properties/fdatasync_core.cpp | 45 + .../js/src/mod_fs/properties/fdatasync_core.h | 29 + .../mod_fs/properties/fdopen_stream_core.cpp | 49 + .../mod_fs/properties/fdopen_stream_core.h | 39 + .../js/src/mod_fs/properties/fsync_core.cpp | 42 + .../js/src/mod_fs/properties/fsync_core.h | 29 + .../js/src/mod_fs/properties/lseek_core.cpp | 53 + .../js/src/mod_fs/properties/lseek_core.h | 33 + .../js/src/mod_fs/properties/lstat_core.cpp | 68 + .../js/src/mod_fs/properties/lstat_core.h | 30 + .../js/src/mod_fs/properties/mkdtemp_core.cpp | 44 + .../js/src/mod_fs/properties/mkdtemp_core.h | 34 + .../js/src/mod_fs/properties/movedir_core.cpp | 302 ++++ .../js/src/mod_fs/properties/movedir_core.h | 64 + .../src/mod_fs/properties/read_lines_core.cpp | 106 ++ .../src/mod_fs/properties/read_lines_core.h | 43 + .../js/src/mod_fs/properties/rename_core.cpp | 46 + .../js/src/mod_fs/properties/rename_core.h | 35 + .../js/src/mod_fs/properties/symlink_core.cpp | 47 + .../js/src/mod_fs/properties/symlink_core.h | 32 + .../js/src/mod_fs/properties/utimes_core.cpp | 64 + .../js/src/mod_fs/properties/utimes_core.h | 32 + .../js/src/mod_fs/properties/watcher_core.cpp | 108 ++ .../js/src/mod_fs/properties/watcher_core.h | 32 + .../js/src/mod_fs/properties/xattr_core.cpp | 87 ++ .../js/src/mod_fs/properties/xattr_core.h | 35 + .../src/mod_hash/ani/bind_function_class.cpp | 22 +- .../src/mod_hash/ani/ets/@ohos.file.hash.ets | 102 +- .../class_hashstream/ani/hashstream_ani.cpp | 123 ++ .../class_hashstream/ani/hashstream_ani.h | 37 + .../class_hashstream/hs_hashstream.cpp | 161 ++ .../mod_hash/class_hashstream/hs_hashstream.h | 46 + .../class_hashstream/hs_hashstream_entity.h | 37 + .../ani/ets/@ohos.file.securityLabel.ets | 16 +- .../mod_statvfs/ani/bind_function_class.cpp | 62 + .../ani/ets/@ohos.file.statvfs.ets | 86 ++ .../js/src/mod_statvfs/ani/statvfs_ani.cpp | 75 + .../kits/js/src/mod_statvfs/ani/statvfs_ani.h | 37 + .../kits/js/src/mod_statvfs/statvfs_core.cpp | 52 + .../kits/js/src/mod_statvfs/statvfs_core.h | 35 + interfaces/test/unittest/BUILD.gn | 2 + .../test/unittest/filemgmt_libn_test/BUILD.gn | 16 +- .../filemgmt_libn_test/include/napi_mock.h | 114 ++ .../filemgmt_libn_test/src/n_class_test.cpp | 583 +++++++- .../filemgmt_libn_test/src/napi_mock.cpp | 106 ++ interfaces/test/unittest/js/BUILD.gn | 497 ++++--- .../environment_core_mock_test.cpp | 521 +++++++ .../mock/accesstoken_kit_mock.cpp | 29 + .../mock/accesstoken_kit_mock.h | 44 + .../mock/ipc_skeleton_mock.cpp | 33 + .../mod_environment/mock/ipc_skeleton_mock.h | 46 + .../mod_environment/mock/parameter_mock.cpp} | 27 +- .../js/mod_environment/mock/parameter_mock.h | 41 + .../class_atomicfile/fs_atomicfile_test.cpp | 366 +++++ .../mod_fs/class_file/fs_file_mock_test.cpp | 180 +-- .../js/mod_fs/class_file/fs_file_test.cpp | 168 +-- .../fs_randomaccessfile_mock_test.cpp | 250 ++++ .../fs_randomaccessfile_test.cpp | 417 ++++++ .../fs_reader_iterator_mock_test.cpp | 102 ++ .../fs_reader_iterator_test.cpp | 80 + .../mod_fs/class_stat/fs_stat_mock_test.cpp | 30 +- .../js/mod_fs/class_stat/fs_stat_test.cpp | 1 - .../class_stream/fs_stream_mock_test.cpp | 191 +++ .../js/mod_fs/class_stream/fs_stream_test.cpp | 791 ++++++++++ .../js/mod_fs/class_stream/mock/c_mock.cpp | 97 ++ .../js/mod_fs/class_stream/mock/c_mock.h | 49 + .../class_tasksignal/fs_task_signal_test.cpp | 202 +++ .../fs_file_watcher_mock_test.cpp | 1324 +++++++++++++++++ .../class_watcher/fs_watcher_mock_test.cpp | 266 ++++ .../unittest/js/mod_fs/common/fs_err_code.h | 34 + .../unittest/js/mod_fs/mock/eventfd_mock.cpp | 83 ++ .../unittest/js/mod_fs/mock/eventfd_mock.h | 53 + .../unittest/js/mod_fs/mock/inotify_mock.cpp | 125 ++ .../unittest/js/mod_fs/mock/inotify_mock.h | 57 + .../js/mod_fs/mock/mock_progress_listener.h | 29 + .../js/mod_fs/mock/mock_watcher_callback.h | 41 + .../unittest/js/mod_fs/mock/poll_mock.cpp | 83 ++ .../test/unittest/js/mod_fs/mock/poll_mock.h | 53 + .../unittest/js/mod_fs/mock/unistd_mock.cpp | 125 ++ .../unittest/js/mod_fs/mock/unistd_mock.h | 57 + .../properties/access_core_mock_test.cpp | 23 - .../js/mod_fs/properties/access_core_test.cpp | 9 +- .../js/mod_fs/properties/close_core_test.cpp | 61 +- .../mod_fs/properties/copy_core_mock_test.cpp | 548 +++++++ .../js/mod_fs/properties/copy_core_test.cpp | 1145 ++++++++++++++ .../mod_fs/properties/copy_dir_core_test.cpp | 295 ++++ .../properties/copy_file_core_mock_test.cpp | 123 +- .../mod_fs/properties/copy_file_core_test.cpp | 26 +- ...create_randomaccessfile_core_mock_test.cpp | 108 ++ .../create_randomaccessfile_core_test.cpp | 189 +++ .../properties/create_stream_core_test.cpp | 81 + .../mod_fs/properties/dup_core_mock_test.cpp | 79 + .../js/mod_fs/properties/dup_core_test.cpp | 94 ++ .../properties/fdatasync_core_mock_test.cpp | 102 ++ .../properties/fdopen_stream_core_test.cpp | 117 ++ .../properties/fsync_core_mock_test.cpp | 98 ++ .../mod_fs/properties/listfile_core_test.cpp | 17 - .../js/mod_fs/properties/lseek_core_test.cpp | 115 ++ .../properties/lstat_core_mock_test.cpp | 79 + .../js/mod_fs/properties/lstat_core_test.cpp | 94 ++ .../properties/mkdir_core_mock_test.cpp | 17 +- .../properties/mkdtemp_core_mock_test.cpp | 114 ++ .../js/mod_fs/properties/mock/system_mock.cpp | 2 +- .../js/mod_fs/properties/mock/system_mock.h | 4 +- .../js/mod_fs/properties/mock/uv_fs_mock.h | 6 +- .../mod_fs/properties/movedir_core_test.cpp | 333 +++++ .../mod_fs/properties/open_core_mock_test.cpp | 77 +- .../js/mod_fs/properties/open_core_test.cpp | 88 +- .../properties/read_lines_core_mock_test.cpp | 133 ++ .../properties/read_lines_core_test.cpp | 102 ++ .../mod_fs/properties/read_text_core_test.cpp | 9 - .../properties/rename_core_mock_test.cpp | 102 ++ .../mod_fs/properties/stat_core_mock_test.cpp | 29 +- .../js/mod_fs/properties/stat_core_test.cpp | 4 +- .../properties/symlink_core_mock_test.cpp | 104 ++ .../properties/trans_listener_mock_test.cpp | 237 +++ .../mod_fs/properties/trans_listener_test.cpp | 577 +++++++ .../properties/unlink_core_mock_test.cpp | 5 +- .../properties/utimes_core_mock_test.cpp | 124 ++ .../js/mod_fs/properties/utimes_core_test.cpp | 73 + .../properties/watcher_core_mock_test.cpp | 193 +++ .../properties/xattr_core_mock_test.cpp | 179 +++ .../js/mod_fs/properties/xattr_core_test.cpp | 143 ++ .../unittest/js/mod_hash/hash_core_test.cpp | 5 - .../securitylabel_core_test.cpp | 5 - .../js/mod_statvfs/statvfs_core_test.cpp | 142 ++ utils/filemgmt_libn/include/n_error.h | 23 +- 255 files changed, 26645 insertions(+), 1185 deletions(-) create mode 100644 interfaces/kits/js/src/common/fs_filefiter.h create mode 100644 interfaces/kits/js/src/mod_environment/ani/bind_function_class.cpp create mode 100644 interfaces/kits/js/src/mod_environment/ani/environment_ani.cpp create mode 100644 interfaces/kits/js/src/mod_environment/ani/environment_ani.h create mode 100644 interfaces/kits/js/src/mod_environment/ani/ets/@ohos.file.environment.ets create mode 100644 interfaces/kits/js/src/mod_environment/environment_core.cpp create mode 100644 interfaces/kits/js/src/mod_environment/environment_core.h create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.h create mode 100644 interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile_entity.h create mode 100644 interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.h create mode 100644 interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.h create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/fs_stream.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.h create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.h create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/i_watcher_callback.h create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp create mode 100644 interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/connectdfs_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/connectdfs_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_dir_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_dir_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_listener/i_progress_listener.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/create_stream_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/create_stream_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/dup_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/dup_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/fdatasync_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/fdatasync_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/fsync_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/fsync_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/lseek_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/lseek_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/lstat_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/lstat_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/movedir_core.cpp create mode 100755 interfaces/kits/js/src/mod_fs/properties/movedir_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/read_lines_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/read_lines_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/rename_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/rename_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/symlink_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/symlink_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/utimes_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/utimes_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/watcher_core.h create mode 100644 interfaces/kits/js/src/mod_fs/properties/xattr_core.cpp create mode 100644 interfaces/kits/js/src/mod_fs/properties/xattr_core.h create mode 100644 interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp create mode 100644 interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.h create mode 100644 interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.cpp create mode 100644 interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.h create mode 100644 interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream_entity.h create mode 100644 interfaces/kits/js/src/mod_statvfs/ani/bind_function_class.cpp create mode 100644 interfaces/kits/js/src/mod_statvfs/ani/ets/@ohos.file.statvfs.ets create mode 100644 interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.cpp create mode 100644 interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.h create mode 100644 interfaces/kits/js/src/mod_statvfs/statvfs_core.cpp create mode 100644 interfaces/kits/js/src/mod_statvfs/statvfs_core.h create mode 100644 interfaces/test/unittest/filemgmt_libn_test/include/napi_mock.h create mode 100644 interfaces/test/unittest/filemgmt_libn_test/src/napi_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_environment/environment_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.h create mode 100644 interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.h rename interfaces/test/unittest/{filemgmt_libn_test/include/n_class_test.h => js/mod_environment/mock/parameter_mock.cpp} (61%) create mode 100644 interfaces/test/unittest/js/mod_environment/mock/parameter_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/class_atomicfile/fs_atomicfile_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/class_tasksignal/fs_task_signal_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/common/fs_err_code.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/mock_progress_listener.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/mock/poll_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h create mode 100644 interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/copy_dir_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/create_stream_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/fdatasync_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/fdopen_stream_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/fsync_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/lseek_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/lstat_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/lstat_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/mkdtemp_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/movedir_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/read_lines_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/read_lines_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/rename_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/symlink_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/trans_listener_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/utimes_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/utimes_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp create mode 100644 interfaces/test/unittest/js/mod_fs/properties/xattr_core_test.cpp create mode 100644 interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index f9fd98aa6..25490bdae 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -628,14 +628,17 @@ group("build_kits_js") { group("ani_file_api") { deps = [ + ":ani_file_environment", ":ani_file_fs", ":ani_file_hash", ":ani_file_securitylabel", + ":ani_file_statvfs", ] } config("ani_config") { include_dirs = [ + "./include", "${file_api_path}/interfaces/kits/rust/include", "${utils_path}/common/include", "${utils_path}/filemgmt_libfs/include", @@ -661,13 +664,28 @@ config("ani_config") { ohos_shared_library("ani_file_fs") { public_configs = [ ":ani_config" ] include_dirs = [ + "include/ipc", "src/mod_fs/ani", + "src/mod_fs/class_atomicfile", + "src/mod_fs/class_atomicfile/ani", "src/mod_fs/class_file", "src/mod_fs/class_file/ani", + "src/mod_fs/class_randomaccessfile", + "src/mod_fs/class_randomaccessfile/ani", + "src/mod_fs/class_readeriterator", + "src/mod_fs/class_readeriterator/ani", "src/mod_fs/class_stat", "src/mod_fs/class_stat/ani", + "src/mod_fs/class_stream", + "src/mod_fs/class_stream/ani", + "src/mod_fs/class_tasksignal", + "src/mod_fs/class_tasksignal/ani", + "src/mod_fs/class_watcher", + "src/mod_fs/class_watcher/ani", "src/mod_fs/properties", "src/mod_fs/properties/ani", + "src/mod_fs/properties/copy_listener", + "src/mod_fs/properties/copy_listener/ani", ] sources = [ "src/common/ani_helper/ani_signature.cpp", @@ -675,42 +693,107 @@ ohos_shared_library("ani_file_fs") { "src/common/ani_helper/type_converter.cpp", "src/common/file_helper/fd_guard.cpp", "src/mod_fs/ani/bind_function_class.cpp", + "src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp", + "src/mod_fs/class_atomicfile/fs_atomicfile.cpp", "src/mod_fs/class_file/ani/file_ani.cpp", "src/mod_fs/class_file/ani/file_wrapper.cpp", "src/mod_fs/class_file/file_instantiator.cpp", "src/mod_fs/class_file/fs_file.cpp", + "src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp", + "src/mod_fs/class_randomaccessfile/fs_randomaccessfile.cpp", + "src/mod_fs/class_readeriterator/ani/reader_iterator_ani.cpp", + "src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.cpp", + "src/mod_fs/class_readeriterator/fs_reader_iterator.cpp", + "src/mod_fs/class_stat/ani/lstat_ani.cpp", "src/mod_fs/class_stat/ani/stat_ani.cpp", "src/mod_fs/class_stat/ani/stat_wrapper.cpp", "src/mod_fs/class_stat/fs_stat.cpp", "src/mod_fs/class_stat/stat_instantiator.cpp", + "src/mod_fs/class_stream/ani/stream_ani.cpp", + "src/mod_fs/class_stream/ani/stream_wrapper.cpp", + "src/mod_fs/class_stream/fs_stream.cpp", + "src/mod_fs/class_stream/stream_instantiator.cpp", + "src/mod_fs/class_tasksignal/ani/task_signal_ani.cpp", + "src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.cpp", + "src/mod_fs/class_tasksignal/ani/task_signal_wrapper.cpp", + "src/mod_fs/class_tasksignal/fs_task_signal.cpp", + "src/mod_fs/class_watcher/ani/fs_watcher_ani.cpp", + "src/mod_fs/class_watcher/ani/fs_watcher_wrapper.cpp", + "src/mod_fs/class_watcher/ani/watch_event_listener.cpp", + "src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp", + "src/mod_fs/class_watcher/fs_file_watcher.cpp", + "src/mod_fs/class_watcher/fs_watcher.cpp", + "src/mod_fs/class_watcher/watcher_data_cache.cpp", "src/mod_fs/fs_utils.cpp", "src/mod_fs/properties/access_core.cpp", "src/mod_fs/properties/ani/access_ani.cpp", "src/mod_fs/properties/ani/close_ani.cpp", + "src/mod_fs/properties/ani/connectdfs_ani.cpp", + "src/mod_fs/properties/ani/copy_ani.cpp", + "src/mod_fs/properties/ani/copy_dir_ani.cpp", "src/mod_fs/properties/ani/copy_file_ani.cpp", + "src/mod_fs/properties/ani/create_randomaccessfile_ani.cpp", + "src/mod_fs/properties/ani/create_stream_ani.cpp", + "src/mod_fs/properties/ani/disconnectdfs_ani.cpp", + "src/mod_fs/properties/ani/dup_ani.cpp", + "src/mod_fs/properties/ani/fdatasync_ani.cpp", + "src/mod_fs/properties/ani/fdopen_stream_ani.cpp", + "src/mod_fs/properties/ani/fsync_ani.cpp", "src/mod_fs/properties/ani/listfile_ani.cpp", + "src/mod_fs/properties/ani/lseek_ani.cpp", "src/mod_fs/properties/ani/mkdir_ani.cpp", + "src/mod_fs/properties/ani/mkdtemp_ani.cpp", "src/mod_fs/properties/ani/move_ani.cpp", + "src/mod_fs/properties/ani/movedir_ani.cpp", "src/mod_fs/properties/ani/open_ani.cpp", "src/mod_fs/properties/ani/read_ani.cpp", + "src/mod_fs/properties/ani/read_lines_ani.cpp", "src/mod_fs/properties/ani/read_text_ani.cpp", + "src/mod_fs/properties/ani/rename_ani.cpp", "src/mod_fs/properties/ani/rmdir_ani.cpp", + "src/mod_fs/properties/ani/symlink_ani.cpp", "src/mod_fs/properties/ani/truncate_ani.cpp", "src/mod_fs/properties/ani/unlink_ani.cpp", + "src/mod_fs/properties/ani/utimes_ani.cpp", + "src/mod_fs/properties/ani/watcher_ani.cpp", "src/mod_fs/properties/ani/write_ani.cpp", + "src/mod_fs/properties/ani/xattr_ani.cpp", "src/mod_fs/properties/close_core.cpp", + "src/mod_fs/properties/connectdfs_core.cpp", + "src/mod_fs/properties/copy_core.cpp", + "src/mod_fs/properties/copy_dir_core.cpp", "src/mod_fs/properties/copy_file_core.cpp", + "src/mod_fs/properties/copy_listener/ani/progress_listener_ani.cpp", + "src/mod_fs/properties/copy_listener/trans_listener_core.cpp", + "src/mod_fs/properties/create_randomaccessfile_core.cpp", + "src/mod_fs/properties/create_stream_core.cpp", + "src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.cpp", + "src/mod_fs/properties/disconnectdfs_core.cpp", + "src/mod_fs/properties/dup_core.cpp", + "src/mod_fs/properties/fdatasync_core.cpp", + "src/mod_fs/properties/fdopen_stream_core.cpp", + "src/mod_fs/properties/fsync_core.cpp", "src/mod_fs/properties/listfile_core.cpp", + "src/mod_fs/properties/lseek_core.cpp", + "src/mod_fs/properties/lstat_core.cpp", "src/mod_fs/properties/mkdir_core.cpp", + "src/mod_fs/properties/mkdtemp_core.cpp", "src/mod_fs/properties/move_core.cpp", + "src/mod_fs/properties/movedir_core.cpp", "src/mod_fs/properties/open_core.cpp", "src/mod_fs/properties/read_core.cpp", + "src/mod_fs/properties/read_lines_core.cpp", "src/mod_fs/properties/read_text_core.cpp", + "src/mod_fs/properties/rename_core.cpp", "src/mod_fs/properties/rmdir_core.cpp", "src/mod_fs/properties/stat_core.cpp", + "src/mod_fs/properties/symlink_core.cpp", "src/mod_fs/properties/truncate_core.cpp", "src/mod_fs/properties/unlink_core.cpp", + "src/mod_fs/properties/utimes_core.cpp", + "src/mod_fs/properties/watcher_core.cpp", "src/mod_fs/properties/write_core.cpp", + "src/mod_fs/properties/xattr_core.cpp", ] deps = [ ":ohos_file_fs_abc_etc", @@ -724,7 +807,7 @@ ohos_shared_library("ani_file_fs") { external_deps = [ "ability_runtime:ability_manager", "app_file_service:fileuri_native", - "bounds_checking_function:libsec_static", + "bounds_checking_function:libsec_shared", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", @@ -777,6 +860,8 @@ ohos_shared_library("ani_file_hash") { include_dirs = [ "src/mod_hash", "src/mod_hash/ani", + "src/mod_hash/class_hashstream", + "src/mod_hash/class_hashstream/ani", ] sources = [ "src/common/ani_helper/ani_signature.cpp", @@ -787,6 +872,8 @@ ohos_shared_library("ani_file_hash") { "src/mod_fs/fs_utils.cpp", "src/mod_hash/ani/bind_function_class.cpp", "src/mod_hash/ani/hash_ani.cpp", + "src/mod_hash/class_hashstream/ani/hashstream_ani.cpp", + "src/mod_hash/class_hashstream/hs_hashstream.cpp", "src/mod_hash/hash_core.cpp", ] @@ -797,7 +884,7 @@ ohos_shared_library("ani_file_hash") { "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", ] external_deps = [ - "bounds_checking_function:libsec_static", + "bounds_checking_function:libsec_shared", "eventhandler:libeventhandler", "hilog:libhilog", "ipc:ipc_core", @@ -862,7 +949,7 @@ ohos_shared_library("ani_file_securitylabel") { "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", ] external_deps = [ - "bounds_checking_function:libsec_static", + "bounds_checking_function:libsec_shared", "eventhandler:libeventhandler", "hilog:libhilog", "ipc:ipc_core", @@ -901,3 +988,133 @@ ohos_prebuilt_etc("ohos_file_securityLabel_abc_etc") { part_name = "file_api" deps = [ ":ohos_file_securityLabel_abc" ] } + +ohos_shared_library("ani_file_environment") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_environment/ani", + "src/mod_environment", + ] + sources = [ + "src/common/ani_helper/ani_signature.cpp", + "src/common/ani_helper/error_handler.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_environment/ani/bind_function_class.cpp", + "src/mod_environment/ani/environment_ani.cpp", + "src/mod_environment/environment_core.cpp", + "src/mod_fs/fs_utils.cpp", + ] + deps = [ + ":ohos_file_environment_abc_etc", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bounds_checking_function:libsec_shared", + "hilog:libhilog", + "init:libbegetutil", + "ipc:ipc_core", + "libuv:uv", + "openssl:libcrypto_shared", + "os_account:os_account_innerkits", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + ] + use_exceptions = true + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} +generate_static_abc("ohos_file_environment_abc") { + base_url = "./src/mod_environment/ani/ets" + files = [ "./src/mod_environment/ani/ets/@ohos.file.environment.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_environment_abc.abc" +} +ohos_prebuilt_etc("ohos_file_environment_abc_etc") { + source = "$target_out_dir/ohos_file_environment_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_environment_abc" ] +} +ohos_shared_library("ani_file_statvfs") { + public_configs = [ ":ani_config" ] + include_dirs = [ + "src/mod_statvfs/ani", + "src/mod_statvfs", + ] + sources = [ + "src/common/ani_helper/ani_signature.cpp", + "src/common/ani_helper/error_handler.cpp", + "src/common/ani_helper/type_converter.cpp", + "src/common/file_helper/fd_guard.cpp", + "src/mod_fs/fs_utils.cpp", + "src/mod_statvfs/ani/bind_function_class.cpp", + "src/mod_statvfs/ani/statvfs_ani.cpp", + "src/mod_statvfs/statvfs_core.cpp", + ] + deps = [ + ":ohos_file_statvfs_abc_etc", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "hilog:libhilog", + "libuv:uv", + "runtime_core:ani", + "runtime_core:ani_helpers", + "runtime_core:libarkruntime", + ] + use_exceptions = true + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + output_extension = "so" + subsystem_name = "filemanagement" + part_name = "file_api" +} +generate_static_abc("ohos_file_statvfs_abc") { + base_url = "./src/mod_statvfs/ani/ets" + files = [ "./src/mod_statvfs/ani/ets/@ohos.file.statvfs.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/ohos_file_statvfs_abc.abc" +} +ohos_prebuilt_etc("ohos_file_statvfs_abc_etc") { + source = "$target_out_dir/ohos_file_statvfs_abc.abc" + module_install_dir = "framework" + subsystem_name = "filemanagement" + part_name = "file_api" + deps = [ ":ohos_file_statvfs_abc" ] +} diff --git a/interfaces/kits/js/src/common/ani_helper/ani_helper.h b/interfaces/kits/js/src/common/ani_helper/ani_helper.h index f19c8f041..f600a41df 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_helper.h +++ b/interfaces/kits/js/src/common/ani_helper/ani_helper.h @@ -116,7 +116,7 @@ public: static const string longValueSig = Builder::BuildSignatureDescriptor({}, BasicTypes::longType); ani_long value; status = env->Object_CallMethodByName_Long( - static_cast(property), "longValue", longValueSig.c_str(), &value); + static_cast(property), "toLong", longValueSig.c_str(), &value); if (status != ANI_OK) { return { false, nullopt }; } diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp index 4a683a783..f8a2a92de 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.cpp @@ -60,6 +60,7 @@ const string BuiltInTypes::Array::objectSetterSig = // BuiltInTypes::ArrayBuffer const Type BuiltInTypes::ArrayBuffer::classType = Builder::BuildClass("escompat.ArrayBuffer"); const string BuiltInTypes::ArrayBuffer::classDesc = BuiltInTypes::ArrayBuffer::classType.Descriptor(); +const string BuiltInTypes::ArrayBuffer::ctorSig = Builder::BuildSignatureDescriptor({ BasicTypes::intType }); // BuiltInTypes::BigInt const Type BuiltInTypes::BigInt::classType = Builder::BuildClass("escompat.BigInt"); const string BuiltInTypes::BigInt::classDesc = BuiltInTypes::BigInt::classType.Descriptor(); @@ -115,6 +116,18 @@ const Type FS::WatchEventInner::classType = Builder::BuildClass("@ohos.file.fs.W const string FS::WatchEventInner::classDesc = FS::WatchEventInner::classType.Descriptor(); const string FS::WatchEventInner::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType, BasicTypes::doubleType, BasicTypes::doubleType }); +// FS::ReadStream +const Type FS::ReadStream::classType = Builder::BuildClass("@ohos.file.fs.fileIo.ReadStream"); +const string FS::ReadStream::classDesc = FS::ReadStream::classType.Descriptor(); +const string FS::ReadStream::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); +// FS::WriteStream +const Type FS::WriteStream::classType = Builder::BuildClass("@ohos.file.fs.fileIo.WriteStream"); +const string FS::WriteStream::classDesc = FS::WriteStream::classType.Descriptor(); +const string FS::WriteStream::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); +// FS::AtomicFile +const Type FS::AtomicFile::classType = Builder::BuildClass("@ohos.file.fs.fileIo.AtomicFile"); +const string FS::AtomicFile::classDesc = FS::AtomicFile::classType.Descriptor(); +const string FS::AtomicFile::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); // FS::LocationType const Type FS::LocationType::classType = Builder::BuildClass("@ohos.file.fs.fileIo.LocationType"); const string FS::LocationType::classDesc = FS::LocationType::classType.Descriptor(); @@ -133,5 +146,9 @@ const string Impl::SecurityLabelImpl::classDesc = Impl::SecurityLabelImpl::class // Impl::StatvfsImpl const Type Impl::StatvfsImpl::classType = Builder::BuildClass("@ohos.file.statvfs.StatvfsImpl"); const string Impl::StatvfsImpl::classDesc = Impl::StatvfsImpl::classType.Descriptor(); +// HASH::HashStreamImpl +const Type HASH::HashStreamImpl::classType = Builder::BuildClass("@ohos.file.hash.HashStreamImpl"); +const string HASH::HashStreamImpl::classDesc = HASH::HashStreamImpl::classType.Descriptor(); +const string HASH::HashStreamImpl::ctorSig = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); } // namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/ani_signature.h b/interfaces/kits/js/src/common/ani_helper/ani_signature.h index 8b7e43281..3938f3fb8 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_signature.h +++ b/interfaces/kits/js/src/common/ani_helper/ani_signature.h @@ -93,6 +93,7 @@ struct Array : public BaseType { struct ArrayBuffer : public BaseType { static const Type classType; static const string classDesc; + static const string ctorSig; }; struct BigInt : public BaseType { @@ -181,6 +182,24 @@ struct LocationType : public BaseType { static const string classDesc; }; +struct ReadStream : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct WriteStream : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +struct AtomicFile : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + } // namespace FS namespace Impl { @@ -212,6 +231,16 @@ struct StatvfsImpl : public BaseType { } // namespace Impl +namespace HASH { + +struct HashStreamImpl : public BaseType { + static const Type classType; + static const string classDesc; + static const string ctorSig; +}; + +} // namespace HASH + } // namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature #endif // INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_SIGNATURE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.cpp b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp index d794b727d..7b5f4ac1c 100644 --- a/interfaces/kits/js/src/common/ani_helper/type_converter.cpp +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp @@ -59,7 +59,7 @@ std::tuple> TypeConverter::ToOptionalInt32(ani_env } ani_int intValue; - if (ANI_OK == env->Object_CallMethodByName_Int(value, "intValue", nullptr, &intValue)) { + if (ANI_OK == env->Object_CallMethodByName_Int(value, "toInt", nullptr, &intValue)) { return { true, std::make_optional(intValue) }; } @@ -79,7 +79,7 @@ std::tuple> TypeConverter::ToOptionalInt64(ani_env } ani_long longValue; - if (ANI_OK == env->Object_CallMethodByName_Long(value, "longValue", nullptr, &longValue)) { + if (ANI_OK == env->Object_CallMethodByName_Long(value, "toLong", nullptr, &longValue)) { return { true, std::make_optional(longValue) }; } @@ -145,14 +145,13 @@ std::tuple> TypeConverter::EnumToInt32(ani_env *env static std::tuple ParseFd(ani_env *env, const ani_object &pathOrFd) { ani_boolean isFd = false; - - auto classDesc = BoxedTypes::Double::classDesc.c_str(); - ani_class cls; - env->FindClass(classDesc, &cls); - env->Object_InstanceOf(pathOrFd, cls, &isFd); + auto intClassDesc = BoxedTypes::Int::classDesc.c_str(); + ani_class intClass; + env->FindClass(intClassDesc, &intClass); + env->Object_InstanceOf(pathOrFd, intClass, &isFd); if (isFd) { ani_int fd; - if (ANI_OK != env->Object_CallMethodByName_Int(pathOrFd, "intValue", nullptr, &fd)) { + if (ANI_OK != env->Object_CallMethodByName_Int(pathOrFd, "toInt", nullptr, &fd)) { HILOGE("Parse file path failed"); return { false, 0 }; } @@ -225,16 +224,18 @@ std::tuple TypeConverter::ToAniArrayBuffer(ani_env *env, return { false, nullptr }; } - static const char *className = "Lescompat/ArrayBuffer;"; + auto classDesc = BuiltInTypes::ArrayBuffer::classDesc.c_str(); ani_status ret; ani_class cls; - if ((ret = env->FindClass(className, &cls)) != ANI_OK) { - HILOGE("Not found %{private}s, err: %{public}d", className, ret); + if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { + HILOGE("Not found %{private}s, err: %{public}d", classDesc, ret); return { false, nullptr }; } + auto ctorDesc = BuiltInTypes::ArrayBuffer::ctorDesc.c_str(); + auto ctorSig = BuiltInTypes::ArrayBuffer::ctorSig.c_str(); ani_method ctor; - if ((ret = env->Class_FindMethod(cls, "", "I:V", &ctor)) != ANI_OK) { + if ((ret = env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) != ANI_OK) { HILOGE("Not found ctor, err: %{public}d", ret); return { false, nullptr }; } @@ -265,20 +266,15 @@ std::tuple TypeConverter::ToAniArrayBuffer(ani_env *env, return { true, static_cast(obj) }; } -std::tuple TypeConverter::ToAniStringList( +std::tuple TypeConverter::ToAniStringList( ani_env *env, const std::string strList[], const uint32_t length) { if (env == nullptr) { return { false, nullptr }; } - auto classDesc = BuiltInTypes::String::classDesc.c_str(); - ani_array_ref result = nullptr; - ani_class cls = nullptr; - if (env->FindClass(classDesc, &cls) != ANI_OK) { - return { false, result }; - } - if (env->Array_New_Ref(cls, length, nullptr, &result) != ANI_OK) { + ani_array result = nullptr; + if (env->Array_New(length, nullptr, &result) != ANI_OK) { return { false, result }; } for (uint32_t i = 0; i < length; i++) { @@ -287,11 +283,11 @@ std::tuple TypeConverter::ToAniStringList( return { false, nullptr }; } - if (env->Array_Set_Ref(result, i, item) != ANI_OK) { + if (env->Array_Set(result, i, item) != ANI_OK) { return { false, nullptr }; } } return { true, result }; } -} // namespace OHOS::FileManagement::ModuleFileIO::ANI \ No newline at end of file +} // namespace OHOS::FileManagement::ModuleFileIO::ANI diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.h b/interfaces/kits/js/src/common/ani_helper/type_converter.h index c5bf1fea1..793ad367f 100644 --- a/interfaces/kits/js/src/common/ani_helper/type_converter.h +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.h @@ -39,10 +39,10 @@ public: static std::tuple> EnumToInt32(ani_env *env, const ani_enum_item &enumOp); static std::tuple ToFileInfo(ani_env *env, const ani_object &pathOrFd); static std::tuple ToArrayBuffer(ani_env *env, ani_arraybuffer &buffer); - static std::tuple ToAniStringList( + static std::tuple ToAniStringList( ani_env *env, const std::string strList[], const uint32_t length); }; } // namespace OHOS::FileManagement::ModuleFileIO::ANI -#endif // INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_TYPE_CONVERTER_H \ No newline at end of file +#endif // INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_TYPE_CONVERTER_H diff --git a/interfaces/kits/js/src/common/fs_filefiter.h b/interfaces/kits/js/src/common/fs_filefiter.h new file mode 100644 index 000000000..f16c17821 --- /dev/null +++ b/interfaces/kits/js/src/common/fs_filefiter.h @@ -0,0 +1,117 @@ +/* + * 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 FS_FILE_FILTER_H +#define FS_FILE_FILTER_H + +#include +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class FsFileFilter { +public: + FsFileFilter() = default; + ~FsFileFilter() = default; + + FsFileFilter(const FsFileFilter &filter) = default; + FsFileFilter &operator=(const FsFileFilter &filter) = default; + + void SetSuffix(const std::optional> &suffix) + { + suffix_ = std::move(suffix); + } + + const std::optional> &GetSuffix() const + { + return suffix_; + } + + void SetDisplayName(const std::optional> &displayName) + { + displayName_ = std::move(displayName); + } + + const std::optional> &GetDisplayName() const + { + return displayName_; + } + + void SetMimeType(const std::optional> &mimeType) + { + mimeType_ = std::move(mimeType); + } + + const std::optional> &GetMimeType() const + { + return mimeType_; + } + + void SetFileSizeOver(const std::optional &fileSizeOver) + { + fileSizeOver_ = std::move(fileSizeOver); + } + + const std::optional &GetFileSizeOver() const + { + return fileSizeOver_; + } + + void SetLastModifiedAfter(const std::optional &lastModifiedAfter) + { + lastModifiedAfter_ = std::move(lastModifiedAfter); + } + + const std::optional &GetLastModifiedAfter() const + { + return lastModifiedAfter_; + } + + void SetExcludeMedia(const bool &excludeMedia) + { + excludeMedia_ = excludeMedia; + } + + bool GetExcludeMedia() const + { + return excludeMedia_; + } + + void SetHasFilter(const bool &hasFilter) + { + hasFilter_ = hasFilter; + } + + bool GetHasFilter() const + { + return hasFilter_; + } + +private: + std::optional> suffix_ = std::nullopt; + std::optional> displayName_ = std::nullopt; + std::optional> mimeType_ = std::nullopt; + std::optional fileSizeOver_ = std::nullopt; + std::optional lastModifiedAfter_ = std::nullopt; + bool excludeMedia_ = false; + bool hasFilter_ = false; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // FS_FILE_FILTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_environment/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_environment/ani/bind_function_class.cpp new file mode 100644 index 000000000..dfda60113 --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/ani/bind_function_class.cpp @@ -0,0 +1,73 @@ +/* + * 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 "ani_signature.h" +#include "bind_function.h" +#include "environment_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static ani_status BindStaticMethods(ani_env *env) +{ + auto classDesc = Impl::EnvironmentImpl::classDesc.c_str(); + std::array methods = { + ani_native_function { + "getStorageDataDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetStorageDataDirSync) }, + ani_native_function { + "getUserDataDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetUserDataDirSync) }, + ani_native_function { + "getUserDownloadDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetUserDownloadDirSync) }, + ani_native_function { + "getUserDesktopDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetUserDesktopDirSync) }, + ani_native_function { + "getUserDocumentDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetUserDocumentDirSync) }, + ani_native_function { + "getExternalStorageDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetExternalStorageDirSync) }, + ani_native_function { + "getUserHomeDirSync", nullptr, reinterpret_cast(EnvironmentAni::GetUserHomeDirSync) }, + }; + return BindClass(env, classDesc, methods); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + HILOGE("Invalid parameter vm"); + return ANI_INVALID_ARGS; + } + + if (result == nullptr) { + HILOGE("Invalid parameter result"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("Invalid ani version!"); + return ANI_INVALID_VERSION; + } + + status = BindStaticMethods(env); + if (status != ANI_OK) { + HILOGE("Cannot bind native static methods for environment!"); + return status; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/interfaces/kits/js/src/mod_environment/ani/environment_ani.cpp b/interfaces/kits/js/src/mod_environment/ani/environment_ani.cpp new file mode 100644 index 000000000..da95c9a2a --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/ani/environment_ani.cpp @@ -0,0 +1,175 @@ +/* + * 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 "environment_ani.h" + +#include "environment_core.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleEnvironment; + +ani_string EnvironmentAni::GetStorageDataDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetStorageDataDir(); + if (!ret.IsSuccess()) { + HILOGE("Get storage data dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetUserDataDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetUserDataDir(); + if (!ret.IsSuccess()) { + HILOGE("Get user data dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetUserDownloadDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetUserDownloadDir(); + if (!ret.IsSuccess()) { + HILOGE("Get user download dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetUserDesktopDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetUserDesktopDir(); + if (!ret.IsSuccess()) { + HILOGE("Get user desktop dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetUserDocumentDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetUserDocumentDir(); + if (!ret.IsSuccess()) { + HILOGE("Get user document dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetExternalStorageDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetExternalStorageDir(); + if (!ret.IsSuccess()) { + HILOGE("Get external storage dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_string EnvironmentAni::GetUserHomeDirSync(ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto ret = DoGetUserHomeDir(); + if (!ret.IsSuccess()) { + HILOGE("Get user home dir failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + string res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_environment/ani/environment_ani.h b/interfaces/kits/js/src/mod_environment/ani/environment_ani.h new file mode 100644 index 000000000..d14a78c69 --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/ani/environment_ani.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ANI_ENVIRONMENT_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ANI_ENVIRONMENT_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class EnvironmentAni final { +public: + static ani_string GetStorageDataDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetUserDataDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetUserDownloadDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetUserDesktopDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetUserDocumentDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetExternalStorageDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); + static ani_string GetUserHomeDirSync(ani_env *env, [[maybe_unused]] ani_class clazz); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ANI_ENVIRONMENT_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_environment/ani/ets/@ohos.file.environment.ets b/interfaces/kits/js/src/mod_environment/ani/ets/@ohos.file.environment.ets new file mode 100644 index 000000000..71b8e1c2d --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/ani/ets/@ohos.file.environment.ets @@ -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. + */ + +import { BusinessError, AsyncCallback } from '@ohos.base'; + +namespace Environment { + export function getStorageDataDir(): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute(EnvironmentImpl.getStorageDataDirSync); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: Error): void => { + reject(e as BusinessError); + }); + }); + } + + export function getStorageDataDir(callback: AsyncCallback): void { + let promise = taskpool.execute(EnvironmentImpl.getStorageDataDirSync); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as string; + callback(e, result); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); + }); + } + + export function getUserDataDir(): Promise { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute(EnvironmentImpl.getUserDataDirSync); + promise.then((ret: NullishType): void => { + let result = ret as string; + resolve(result); + }).catch((e: Error): void => { + reject(e as BusinessError); + }); + }); + } + export function getUserDataDir(callback: AsyncCallback): void { + let promise = taskpool.execute(EnvironmentImpl.getUserDataDirSync); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as string; + callback(e, result); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); + }); + } + + export function getUserDownloadDir(): string { + return EnvironmentImpl.getUserDownloadDirSync(); + } + + export function getUserDesktopDir(): string { + return EnvironmentImpl.getUserDesktopDirSync(); + } + + export function getUserDocumentDir(): string { + return EnvironmentImpl.getUserDocumentDirSync(); + } + + export function getExternalStorageDir(): string { + return EnvironmentImpl.getExternalStorageDirSync(); + } + + export function getUserHomeDir(): string { + return EnvironmentImpl.getUserHomeDirSync(); + } + +} + +export default Environment; + +class EnvironmentImpl { + + static { + loadLibrary("ani_file_environment"); + } + + static native getStorageDataDirSync(): string; + static native getUserDataDirSync(): string; + static native getUserDownloadDirSync(): string; + static native getUserDesktopDirSync(): string; + static native getUserDocumentDirSync(): string; + static native getExternalStorageDirSync(): string; + static native getUserHomeDirSync(): string; +} diff --git a/interfaces/kits/js/src/mod_environment/environment_core.cpp b/interfaces/kits/js/src/mod_environment/environment_core.cpp new file mode 100644 index 000000000..5be54fe32 --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/environment_core.cpp @@ -0,0 +1,204 @@ +/* + * 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 "environment_core.h" + +#include +#include + +#include "accesstoken_kit.h" +#include "account_error_no.h" +#include "filemgmt_libhilog.h" +#include "ipc_skeleton.h" +#include "os_account_manager.h" +#include "parameter.h" +#include "tokenid_kit.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleEnvironment { +namespace { +const std::string STORAGE_DATA_PATH = "/data"; +const std::string PC_STORAGE_PATH = "/storage/Users/"; +const std::string EXTERNAL_STORAGE_PATH = "/storage/External"; +const std::string USER_APP_DATA_PATH = "/appdata"; +const std::string READ_WRITE_DOWNLOAD_PERMISSION = "ohos.permission.READ_WRITE_DOWNLOAD_DIRECTORY"; +const std::string READ_WRITE_DESKTOP_PERMISSION = "ohos.permission.READ_WRITE_DESKTOP_DIRECTORY"; +const std::string READ_WRITE_DOCUMENTS_PERMISSION = "ohos.permission.READ_WRITE_DOCUMENTS_DIRECTORY"; +const std::string FILE_ACCESS_MANAGER_PERMISSION = "ohos.permission.FILE_ACCESS_MANAGER"; +const std::string DOWNLOAD_PATH = "/Download"; +const std::string DESKTOP_PATH = "/Desktop"; +const std::string DOCUMENTS_PATH = "/Documents"; +const std::string DEFAULT_USERNAME = "currentUser"; +const char *FILE_MANAGER_FULL_MOUNT_ENABLE_PARAMETER = "const.filemanager.full_mount.enable"; +static bool IsSystemApp() +{ + uint64_t fullTokenId = OHOS::IPCSkeleton::GetCallingFullTokenID(); + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); +} + +static bool CheckCallingPermission(const std::string &permission) +{ + Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID(); + int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permission); + if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + HILOGE("ModuleUserDirectory::CheckCallingPermission have no fileAccess permission"); + return false; + } + return true; +} + +static std::string GetUserName() +{ + std::string userName; + ErrCode errCode = OHOS::AccountSA::OsAccountManager::GetOsAccountShortName(userName); + if (errCode != ERR_OK || userName.empty()) { + HILOGE("Get userName Failed"); + } + userName = DEFAULT_USERNAME; + return userName; +} + +static std::string GetPublicPath(const std::string &directoryName) +{ + return PC_STORAGE_PATH + GetUserName() + directoryName; +} + +static bool CheckFileManagerFullMountEnable() +{ + char value[] = "false"; + int retSystem = GetParameter(FILE_MANAGER_FULL_MOUNT_ENABLE_PARAMETER, "false", value, sizeof(value)); + if (retSystem > 0 && !std::strcmp(value, "true")) { + return true; + } + HILOGE("Not supporting all mounts"); + return false; +} + +static int CheckInvalidAccess(const std::string &permission) +{ + if (!CheckFileManagerFullMountEnable()) { + HILOGE("Capability not supported"); + return E_DEVICENOTSUPPORT; + } + if (permission == FILE_ACCESS_MANAGER_PERMISSION) { + if (!IsSystemApp()) { + return E_PERMISSION_SYS; + } + } + if (!CheckCallingPermission(permission)) { + HILOGE("No Permission"); + return E_PERMISSION; + } + return ERRNO_NOERR; +} +} + +FsResult DoGetStorageDataDir() +{ + if (!IsSystemApp()) { + return FsResult::Error(E_PERMISSION_SYS); + } + return FsResult::Success(std::move(STORAGE_DATA_PATH)); +} + +int GetUserId() +{ + return 0; +} + +FsResult DoGetUserDataDir() +{ + if (!IsSystemApp()) { + return FsResult::Error(E_PERMISSION_SYS); + } + + auto userDataPath = std::make_shared(); + (*userDataPath).append("/storage/media/").append(std::to_string(GetUserId())).append("/local"); + return FsResult::Success(std::move(*userDataPath)); +} + +FsResult DoGetUserDownloadDir() +{ + if (!CheckFileManagerFullMountEnable()) { + HILOGE("Capability not supported"); + return FsResult::Error(E_DEVICENOTSUPPORT); + } + + static std::string downloadPath = GetPublicPath(DOWNLOAD_PATH); + if (downloadPath.empty()) { + HILOGE("Unknown error"); + return FsResult::Error(E_UNKNOWN_ERROR); + } + return FsResult::Success(std::move(downloadPath)); +} + +FsResult DoGetUserDesktopDir() +{ + if (!CheckFileManagerFullMountEnable()) { + HILOGE("Capability not supported"); + return FsResult::Error(E_DEVICENOTSUPPORT); + } + + static std::string desktopPath = GetPublicPath(DESKTOP_PATH); + if (desktopPath.empty()) { + HILOGE("Unknown error"); + return FsResult::Error(E_UNKNOWN_ERROR); + } + return FsResult::Success(std::move(desktopPath)); +} + +FsResult DoGetUserDocumentDir() +{ + if (!CheckFileManagerFullMountEnable()) { + HILOGE("Capability not supported"); + return FsResult::Error(E_DEVICENOTSUPPORT); + } + + static std::string documentsPath = GetPublicPath(DOCUMENTS_PATH); + if (documentsPath.empty()) { + HILOGE("Unknown error"); + return FsResult::Error(E_UNKNOWN_ERROR); + } + return FsResult::Success(std::move(documentsPath)); +} + +FsResult DoGetExternalStorageDir() +{ + auto res = CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION); + if (res) { + return FsResult::Error(res); + } + return FsResult::Success(std::move(EXTERNAL_STORAGE_PATH)); +} + +FsResult DoGetUserHomeDir() +{ + auto res = CheckInvalidAccess(FILE_ACCESS_MANAGER_PERMISSION); + if (res) { + return FsResult::Error(res); + } + + static std::string userName = GetUserName(); + if (userName.empty()) { + HILOGE("Unknown error"); + return FsResult::Error(E_UNKNOWN_ERROR); + } + std::string result = PC_STORAGE_PATH + userName; + return FsResult::Success(std::move(result)); +} +} // namespace ModuleEnvironment +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_environment/environment_core.h b/interfaces/kits/js/src/mod_environment/environment_core.h new file mode 100644 index 000000000..0962c1f4a --- /dev/null +++ b/interfaces/kits/js/src/mod_environment/environment_core.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ENVIRONMENT_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ENVIRONMENT_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleEnvironment { +using namespace ModuleFileIO; +FsResult DoGetStorageDataDir(); +FsResult DoGetUserDataDir(); +FsResult DoGetUserDownloadDir(); +FsResult DoGetUserDesktopDir(); +FsResult DoGetUserDocumentDir(); +FsResult DoGetExternalStorageDir(); +FsResult DoGetUserHomeDir(); +} // namespace ModuleEnvironment +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_ENVIRONMENT_ENVIRONMENT_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp index f8da76c82..cec91441f 100644 --- a/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp +++ b/interfaces/kits/js/src/mod_fs/ani/bind_function_class.cpp @@ -19,25 +19,82 @@ #include "access_ani.h" #include "ani_signature.h" +#include "atomicfile_ani.h" #include "bind_function.h" #include "close_ani.h" +#include "connectdfs_ani.h" +#include "copy_ani.h" +#include "copy_dir_ani.h" #include "copy_file_ani.h" +#include "create_randomaccessfile_ani.h" +#include "create_stream_ani.h" +#include "disconnectdfs_ani.h" +#include "dup_ani.h" +#include "fdatasync_ani.h" +#include "fdopen_stream_ani.h" #include "file_ani.h" +#include "filemgmt_libhilog.h" +#include "fsync_ani.h" +#include "fs_watcher_ani.h" #include "listfile_ani.h" +#include "lseek_ani.h" +#include "lstat_ani.h" #include "mkdir_ani.h" +#include "mkdtemp_ani.h" #include "move_ani.h" -#include "read_ani.h" -#include "rmdir_ani.h" +#include "movedir_ani.h" #include "open_ani.h" +#include "randomaccessfile_ani.h" +#include "read_ani.h" +#include "read_lines_ani.h" #include "read_text_ani.h" +#include "reader_iterator_ani.h" +#include "rename_ani.h" +#include "rmdir_ani.h" #include "stat_ani.h" +#include "stream_ani.h" +#include "symlink_ani.h" +#include "task_signal_ani.h" #include "truncate_ani.h" #include "unlink_ani.h" +#include "utimes_ani.h" +#include "watcher_ani.h" #include "write_ani.h" +#include "xattr_ani.h" using namespace OHOS::FileManagement::ModuleFileIO::ANI; using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; +static ani_status BindRafFileMethods(ani_env *env) +{ + auto classDesc = FS::RandomAccessFileInner::classDesc.c_str(); + + std::array methods = { + ani_native_function { + "setFilePointer0", nullptr, reinterpret_cast(RandomAccessFileAni::SetFilePointer) }, + ani_native_function { "close", nullptr, reinterpret_cast(RandomAccessFileAni::Close) }, + ani_native_function { "writeSync0", nullptr, reinterpret_cast(RandomAccessFileAni::WriteSync) }, + ani_native_function { "readSync0", nullptr, reinterpret_cast(RandomAccessFileAni::ReadSync) }, + ani_native_function { "getReadStream", nullptr, reinterpret_cast(RandomAccessFileAni::GetReadStream) }, + ani_native_function { + "getWriteStream", nullptr, reinterpret_cast(RandomAccessFileAni::GetWriteStream) }, + }; + + return BindClass(env, classDesc, methods); +} + +static ani_status BindWatcherClassMethods(ani_env *env) +{ + auto classDesc = FS::WatcherInner::classDesc.c_str(); + + std::array methods = { + ani_native_function { "start", nullptr, reinterpret_cast(FsWatcherAni::Start) }, + ani_native_function { "stop", nullptr, reinterpret_cast(FsWatcherAni::Stop) }, + }; + + return BindClass(env, classDesc, methods); +} + static ani_status BindFileMethods(ani_env *env) { auto classDesc = FS::FileInner::classDesc.c_str(); @@ -52,6 +109,17 @@ static ani_status BindFileMethods(ani_env *env) return BindClass(env, classDesc, methods); } +static ani_status BindReaderIteratorMethods(ani_env *env) +{ + auto classDesc = FS::ReaderIteratorInner::classDesc.c_str(); + + std::array methods = { + ani_native_function { "next", nullptr, reinterpret_cast(ReaderIteratorAni::Next) }, + }; + + return BindClass(env, classDesc, methods); +} + static ani_status BindStatClassMethods(ani_env *env) { auto classDesc = FS::StatInner::classDesc.c_str(); @@ -69,6 +137,53 @@ static ani_status BindStatClassMethods(ani_env *env) return BindClass(env, classDesc, methods); } +static ani_status BindStreamMethods(ani_env *env) +{ + auto classDesc = FS::StreamInner::classDesc.c_str(); + + std::array methods = { + ani_native_function { "closeSync", nullptr, reinterpret_cast(StreamAni::Close) }, + ani_native_function { "flushSync", nullptr, reinterpret_cast(StreamAni::Flush) }, + ani_native_function { "readSync", nullptr, reinterpret_cast(StreamAni::Read) }, + ani_native_function { "writeSync", nullptr, reinterpret_cast(StreamAni::Write) }, + ani_native_function { "seek", nullptr, reinterpret_cast(StreamAni::Seek) }, + }; + + return BindClass(env, classDesc, methods); +} + +static ani_status BindTaskSignalClassMethods(ani_env *env) +{ + auto classDesc = FS::TaskSignal::classDesc.c_str(); + + std::array methods = { + ani_native_function { "cancel", nullptr, reinterpret_cast(TaskSignalAni::Cancel) }, + ani_native_function { "onCancelNative", nullptr, reinterpret_cast(TaskSignalAni::OnCancel) }, + }; + + return BindClass(env, classDesc, methods); +} + +static ani_status BindAtomicFileMethods(ani_env *env) +{ + auto classDesc = FS::AtomicFile::classDesc.c_str(); + auto ctorDesc = FS::AtomicFile::ctorDesc.c_str(); + auto ctorSig = FS::AtomicFile::ctorSig.c_str(); + + std::array methods = { + ani_native_function { "getPath", nullptr, reinterpret_cast(AtomicFileAni::GetPath) }, + ani_native_function { "getBaseFile", nullptr, reinterpret_cast(AtomicFileAni::GetBaseFile) }, + ani_native_function { "readFully", nullptr, reinterpret_cast(AtomicFileAni::ReadFully) }, + ani_native_function { "nativeStartWrite", nullptr, reinterpret_cast(AtomicFileAni::StartWrite) }, + ani_native_function { "nativeFinishWrite", nullptr, reinterpret_cast(AtomicFileAni::FinishWrite) }, + ani_native_function { "nativeFailWrite", nullptr, reinterpret_cast(AtomicFileAni::FailWrite) }, + ani_native_function { "delete", nullptr, reinterpret_cast(AtomicFileAni::Delete) }, + ani_native_function { ctorDesc, ctorSig, reinterpret_cast(AtomicFileAni::Constructor) }, + ani_native_function { "openRead", nullptr, reinterpret_cast(AtomicFileAni::OpenRead) }, + }; + + return BindClass(env, classDesc, methods); +} const static string mkdirCtorSig0 = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType }); const static string mkdirCtorSig1 = Builder::BuildSignatureDescriptor({ BuiltInTypes::stringType, BasicTypes::booleanType }); @@ -79,19 +194,43 @@ static ani_status BindStaticMethods(ani_env *env) std::array methods = { ani_native_function { "closeSync", nullptr, reinterpret_cast(CloseAni::CloseSync) }, + ani_native_function { "connectDfs", nullptr, reinterpret_cast(ConnectDfsAni::ConnectDfsSync) }, + ani_native_function { "copyDirSync", nullptr, reinterpret_cast(CopyDirAni::CopyDirSync) }, ani_native_function { "copyFileSync", nullptr, reinterpret_cast(CopyFileAni::CopyFileSync) }, + ani_native_function { "copySync", nullptr, reinterpret_cast(CopyAni::CopySync) }, + ani_native_function { "createRandomAccessFileSync", nullptr, + reinterpret_cast(CreateRandomAccessFileAni::CreateRandomAccessFileSync) }, + ani_native_function { + "createStreamSync", nullptr, reinterpret_cast(CreateStreamAni::CreateStreamSync) }, + ani_native_function { "createWatcherSync", nullptr, reinterpret_cast(WatcherAni::CreateWatcherSync) }, + ani_native_function { "disConnectDfs", nullptr, reinterpret_cast(DisConnectDfsAni::DisConnectDfsSync) }, ani_native_function { "doAccessSync", nullptr, reinterpret_cast(AccessAni::AccessSync3) }, + ani_native_function { "dup", nullptr, reinterpret_cast(DupAni::Dup) }, + ani_native_function { "fdatasyncSync", nullptr, reinterpret_cast(FDataSyncAni::FDataSyncSync) }, + ani_native_function { + "fdopenStreamSync", nullptr, reinterpret_cast(FdopenStreamAni::FdopenStreamSync) }, + ani_native_function { "fsyncSync", nullptr, reinterpret_cast(FsyncAni::FsyncSync) }, + ani_native_function { "getxattrSync", nullptr, reinterpret_cast(XattrAni::GetXattrSync) }, ani_native_function { "listFileSync", nullptr, reinterpret_cast(ListFileAni::ListFileSync) }, + ani_native_function { "lseekSync", nullptr, reinterpret_cast(LseekAni::LseekSync) }, + ani_native_function { "lstatSync", nullptr, reinterpret_cast(LstatAni::LstatSync) }, ani_native_function { "mkdirSync", mkdirCtorSig0.c_str(), reinterpret_cast(MkdirkAni::MkdirSync0) }, ani_native_function { "mkdirSync", mkdirCtorSig1.c_str(), reinterpret_cast(MkdirkAni::MkdirSync1) }, + ani_native_function { "mkdtempSync", nullptr, reinterpret_cast(MkdtempAni::MkdtempSync) }, + ani_native_function { "movedirSync", nullptr, reinterpret_cast(MoveDirAni::MoveDirSync) }, ani_native_function { "moveFileSync", nullptr, reinterpret_cast(MoveAni::MoveFileSync) }, ani_native_function { "openSync", nullptr, reinterpret_cast(OpenAni::OpenSync) }, + ani_native_function { "readlinesSync", nullptr, reinterpret_cast(ReadLinesAni::ReadLinesSync) }, ani_native_function { "readSync", nullptr, reinterpret_cast(ReadAni::ReadSync) }, ani_native_function { "readTextSync", nullptr, reinterpret_cast(ReadTextAni::ReadTextSync) }, + ani_native_function { "renameSync", nullptr, reinterpret_cast(RenameAni::RenameSync) }, ani_native_function { "rmdirSync", nullptr, reinterpret_cast(RmdirAni::RmdirSync) }, + ani_native_function { "setxattrSync", nullptr, reinterpret_cast(XattrAni::SetXattrSync) }, ani_native_function { "statSync", nullptr, reinterpret_cast(StatAni::StatSync) }, + ani_native_function { "symlinkSync", nullptr, reinterpret_cast(SymlinkAni::SymlinkSync) }, ani_native_function { "truncateSync", nullptr, reinterpret_cast(TruncateAni::TruncateSync) }, ani_native_function { "unlinkSync", nullptr, reinterpret_cast(UnlinkAni::UnlinkSync) }, + ani_native_function { "utimes", nullptr, reinterpret_cast(UtimesAni::Utimes) }, ani_native_function { "writeSync", nullptr, reinterpret_cast(WriteAni::WriteSync) }, }; return BindClass(env, classDesc, methods); @@ -110,11 +249,41 @@ static ani_status DoBindMethods(ani_env *env) return status; }; + if ((status = BindReaderIteratorMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for ReaderIterator Class"); + return status; + }; + if ((status = BindStatClassMethods(env)) != ANI_OK) { HILOGE("Cannot bind native methods for Stat Class!"); return status; }; + if ((status = BindRafFileMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for RafFile Class"); + return status; + }; + + if ((status = BindStreamMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for Stream Class!"); + return status; + }; + + if ((status = BindTaskSignalClassMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for TaskSignal Class!"); + return status; + }; + + if ((status = BindWatcherClassMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for Watcher Class"); + return status; + }; + + if ((status = BindAtomicFileMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native methods for AtomicFile Class!"); + return status; + }; + return ANI_OK; } diff --git a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets index 5de05d13c..610c1094f 100644 --- a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -13,7 +13,7 @@ * limitations under the License. */ import { BusinessError, AsyncCallback } from '@ohos.base'; -// import stream from '@ohos.util.stream'; +import stream from '@ohos.util.stream'; const UNKNOWN_ERR: number = 13900042 const UNKNOWN_MSG: string = "Unknown error" @@ -47,8 +47,8 @@ function access(path: string, mode?: AccessModeType): Promise { promise.then((ret: NullishType): void => { let result = ret as boolean; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -62,8 +62,8 @@ function access(path: string, callback: AsyncCallback): void { e.code = 0; let result = ret as boolean; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, false); + }).catch((e: Error): void => { + callback(e as BusinessError, false); }); } @@ -75,8 +75,8 @@ function access(path: string, mode: AccessModeType, flag: AccessFlagType): Promi promise.then((ret: NullishType): void => { let result = ret as boolean; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }) } @@ -94,8 +94,8 @@ function close(file: number | File): Promise { let promise = taskpool.execute((file: number | File): undefined => FileIoImpl.closeSync(file), file); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -106,8 +106,8 @@ function close(file: number | File, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -121,8 +121,8 @@ function connectDfs(networkId: string, listeners: DfsListeners): Promise { FileIoImpl.connectDfs(networkId, listeners), networkId, listeners); promise.then((): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -132,8 +132,8 @@ function disconnectDfs(networkId: string): Promise { let promise = taskpool.execute((networkId: string): void => FileIoImpl.disConnectDfs(networkId), networkId); promise.then((): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -150,8 +150,8 @@ function getxattr(path: string, key: string): Promise { promise.then((ret: NullishType): void => { let result = ret as string; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -171,8 +171,8 @@ function copyDir(src: string, dest: string, mode?: number): Promise { FileIoImpl.copyDirSync(src, dest, mode), src, dest, mode); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError>): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError>); }); }); } @@ -185,8 +185,8 @@ function copyDir(src: string, dest: string, callback: AsyncCallback(0); callback(e, undefined); - }).catch((e: BusinessError>): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError>, undefined); }); } @@ -198,8 +198,8 @@ function copyDir(src: string, dest: string, mode: number, callback: AsyncCallbac e.code = 0; e.data = new Array(0); callback(e, undefined); - }).catch((e: BusinessError>): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError>, undefined); }); } @@ -237,7 +237,7 @@ function fdatasync(fd: number): Promise { let promise = taskpool.execute((fd: number): undefined => FileIoImpl.fdatasyncSync(fd), fd); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { reject(e as BusinessError); }); }); @@ -249,8 +249,8 @@ function fdatasync(fd: number, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -273,7 +273,7 @@ function mkdir(path: string): Promise { let promise = taskpool.execute((path: string): undefined => mkdirSync1(path), path); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { reject(e as BusinessError); }); }); @@ -285,8 +285,8 @@ function mkdir(path: string, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -309,8 +309,8 @@ function mkdir(path: string, recursion: boolean, callback: AsyncCallback): let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -326,8 +326,8 @@ function moveDir(src: string, dest: string, mode?: number): Promise { }, src, dest, mode); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError>): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError>); }); }) } @@ -341,8 +341,8 @@ function moveDir(src: string, dest: string, callback: AsyncCallback(0); callback(e, undefined); - }).catch((e: BusinessError>): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError>, undefined); }); } @@ -355,8 +355,8 @@ function moveDir(src: string, dest: string, mode: number, callback: AsyncCallbac e.code = 0; e.data = new Array(0); callback(e, undefined); - }).catch((e: BusinessError>): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError>, undefined); }); } @@ -393,8 +393,8 @@ function mkdtemp(prefix: string): Promise { promise.then((ret: NullishType): void => { let result = ret as string; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -408,8 +408,8 @@ function mkdtemp(prefix: string, callback: AsyncCallback): void { e.code = 0; let result = ret as string; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, ""); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); }); } @@ -424,8 +424,8 @@ function moveFile(src: string, dest: string, mode?: number): Promise { }, src, dest, mode); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -438,8 +438,8 @@ function moveFile(src: string, dest: string, mode: number, callback: AsyncCallba let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -451,8 +451,8 @@ function moveFile(src: string, dest: string, callback: AsyncCallback): voi let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -468,8 +468,8 @@ function open(path: String, mode?: number): Promise { promise.then((ret: NullishType): void => { let file = ret as File; resolve(file); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -483,9 +483,9 @@ function open(path: String, mode: number, callback: AsyncCallback): e.code = 0; let file = ret as File; callback(e, file); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { let f: File = new FileInner(0); - callback(e, f); + callback(e as BusinessError, f); }); } @@ -498,9 +498,9 @@ function open(path: String, callback: AsyncCallback): void { e.code = 0; let file = ret as File; callback(e, file); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { let f: File = new FileInner(0); - callback(e, f); + callback(e as BusinessError, f); }); } @@ -516,8 +516,8 @@ function write(fd: number, buffer: string | ArrayBuffer, options?: WriteOptions) promise.then((ret: NullishType): void => { let result = ret as number resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -532,8 +532,8 @@ function write(fd: number, buffer: string | ArrayBuffer, options: WriteOptions, e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -546,8 +546,8 @@ function write(fd: number, buffer: string | ArrayBuffer, callback: AsyncCallback e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -563,8 +563,8 @@ function read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise { let result = ret as number; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -578,8 +578,8 @@ function read(fd: number, buffer: ArrayBuffer, callback: AsyncCallback { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -592,8 +592,8 @@ function read(fd: number, buffer: ArrayBuffer, options: ReadOptions, callback: A e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -610,8 +610,8 @@ function readLines(filePath: string, options?: Options): Promise promise.then((ret: NullishType): void => { let it = ret as ReaderIterator; resolve(it); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -625,9 +625,9 @@ function readLines(filePath: string, callback: AsyncCallback): v e.code = 0; let it = ret as ReaderIterator; callback(e, it); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { let r: ReaderIterator = new ReaderIteratorInner(0); - callback(e, r); + callback(e as BusinessError, r); }); } @@ -640,9 +640,9 @@ function readLines(filePath: string, options: Options, callback: AsyncCallback { + }).catch((e: Error): void => { let r: ReaderIterator = new ReaderIteratorInner(0); - callback(e, r); + callback(e as BusinessError, r); }); } @@ -656,8 +656,8 @@ function rmdir(path: string): Promise { let promise = taskpool.execute((path: string): void => FileIoImpl.rmdirSync(path), path); promise.then((ret: NullishType) => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -668,8 +668,8 @@ function rmdir(path: string, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -684,8 +684,8 @@ function truncate(file: string | number, len?: number): Promise { }, file, len); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }) } @@ -698,8 +698,8 @@ function truncate(file: string | number, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -711,8 +711,8 @@ function truncate(file: string | number, len: number, callback: AsyncCallback(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -726,8 +726,8 @@ function unlink(path: string): Promise { let promise = taskpool.execute((path: string): undefined => unlinkSync(path), path); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -738,8 +738,8 @@ function unlink(path: string, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -751,9 +751,9 @@ function readText(filePath: string, options?: ReadTextOptions): Promise promise.then((ret: NullishType): void => { let r = ret as string; resolve(r); - }).catch((e: BusinessError): void => { - reject(e); - }); + }).catch((e: Error): void => { + reject(e as BusinessError); + }); }); } @@ -766,8 +766,8 @@ function readText(filePath: string, callback: AsyncCallback): void { e.code = 0; let r = ret as string; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, ""); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); }); } @@ -780,8 +780,8 @@ function readText(filePath: string, options: ReadTextOptions, callback: AsyncCal e.code = 0; let r = ret as string; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, ""); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); }); } @@ -797,8 +797,8 @@ function listFile(path: string, options?: ListFileOptions): Promise { promise.then((ret: NullishType): void => { let r = ret as string[]; resolve(r); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -812,8 +812,8 @@ function listFile(path: string, callback: AsyncCallback): void { e.code = 0; let r = ret as string[]; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, []); + }).catch((e: Error): void => { + callback(e as BusinessError, []); }); } @@ -826,8 +826,8 @@ function listFile(path: string, options: ListFileOptions, callback: AsyncCallbac e.code = 0; let r = ret as string[]; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, []); + }).catch((e: Error): void => { + callback(e as BusinessError, []); }); } @@ -851,8 +851,8 @@ function stat(file: string | number): Promise { promise.then((ret: NullishType): void => { let r = ret as Stat; resolve(r); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -866,8 +866,8 @@ function stat(file: string | number, callback: AsyncCallback): void e.code = 0; let r = ret as Stat; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, new StatInner(0)); + }).catch((e: Error): void => { + callback(e as BusinessError, new StatInner(0)); }); } @@ -882,8 +882,8 @@ function fsync(fd: number): Promise { }, fd); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -896,8 +896,8 @@ function fsync(fd: number, callback: AsyncCallback): void { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -913,8 +913,8 @@ function symlink(target: string, srcPath: string): Promise { }, target, srcPath); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -929,8 +929,8 @@ function rename(oldPath: string, newPath: string): Promise { }, oldPath, newPath); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -943,8 +943,8 @@ function rename(oldPath: string, newPath: string, callback: AsyncCallback) let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -964,8 +964,8 @@ function createRandomAccessFile(file: string | File, mode?: number, promise.then((ret: NullishType): void => { let raffile = ret as RandomAccessFileInner; resolve(raffile); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -978,8 +978,8 @@ function fdopenStream(fd: number, mode: string): Promise { promise.then((ret: NullishType): void => { let stream = ret as Stream; resolve(stream); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -994,7 +994,7 @@ function setxattr(path: string, key: string, value: string): Promise { FileIoImpl.setxattrSync(path, key, value), path, key, value); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { reject(e as BusinessError); }); }); @@ -1009,9 +1009,9 @@ function createRandomAccessFile(file: string | File, callback: AsyncCallback { + }).catch((e: Error): void => { let f: RandomAccessFile = new RandomAccessFileInner(0); - callback(e, f); + callback(e as BusinessError, f); }); } @@ -1025,9 +1025,9 @@ function createRandomAccessFile(file: string | File, mode: number, e.code = 0; let raffile = ret as RandomAccessFile; callback(e, raffile); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { let f: RandomAccessFile = new RandomAccessFileInner(0); - callback(e, f); + callback(e as BusinessError, f); }); } @@ -1040,9 +1040,9 @@ function fdopenStream(fd: number, mode: string, callback: AsyncCallback) e.code = 0; let stream = ret as Stream; callback(e, stream); - }).catch((e: BusinessError): void => { + }).catch((e: Error): void => { let r: Stream = new StreamInner(0); - callback(e, r); + callback(e as BusinessError, r); }); } @@ -1058,8 +1058,8 @@ function createStream(path: string, mode: string): Promise { promise.then((ret: NullishType): void => { let stream = ret as Stream; resolve(stream); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1073,9 +1073,9 @@ function createStream(path: string, mode: string, callback: AsyncCallback { + }).catch((e: Error): void => { let r: Stream = new StreamInner(0); - callback(e, r); + callback(e as BusinessError, r); }); } @@ -1083,13 +1083,13 @@ function createStreamSync(path: string, mode: string): Stream { return FileIoImpl.createStreamSync(path, mode); } -// function createReadStream(path: string, options?: ReadStreamOptions): ReadStream { -// return new ReadStream(path, options) -// } +function createReadStream(path: string, options?: ReadStreamOptions): ReadStream { + return new ReadStream(path, options) +} -// function createWriteStream(path: string, options?: WriteStreamOptions): WriteStream { -// return new WriteStream(path, options); -// } +function createWriteStream(path: string, options?: WriteStreamOptions): WriteStream { + return new WriteStream(path, options); +} function createWatcher(path: string, events: number, listener: WatchEventListener): Watcher { return FileIoImpl.createWatcherSync(path, events, listener); @@ -1103,8 +1103,8 @@ function symlink(target: string, srcPath: string, callback: AsyncCallback) let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1130,8 +1130,8 @@ function lstat(path: string): Promise { let r = ret as Stat; resolve(r); } - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1151,8 +1151,8 @@ function lstat(path: string, callback: AsyncCallback): void { let r = ret as Stat; callback(e, r); } - }).catch((e: BusinessError): void => { - callback(e, new StatInner(0)); + }).catch((e: Error): void => { + callback(e as BusinessError, new StatInner(0)); }); } function copyFile(src: string | number, dest: string | number, mode?: number): Promise { @@ -1161,8 +1161,8 @@ function copyFile(src: string | number, dest: string | number, mode?: number): P FileIoImpl.copyFileSync(src, dest, mode), src, dest, mode); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1173,8 +1173,8 @@ function copy(srcUri: string, destUri: string, options?: CopyOptions): Promise { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1186,8 +1186,8 @@ function copyFile(src: string | number, dest: string | number, mode: number, cal let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1198,8 +1198,8 @@ function copy(srcUri: string, destUri: string, options: CopyOptions, callback: A let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1210,8 +1210,8 @@ function copyFile(src: string | number, dest: string | number, callback: AsyncCa let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1222,8 +1222,8 @@ function copy(srcUri: string, destUri: string, callback: AsyncCallback): v let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1263,20 +1263,31 @@ export type ProgressListener = (progress: Progress) => void; export class TaskSignal { private nativeTaskSignal: long = 0; + private native onCancelNative(): void; + private onCancelResolve: (path: string) => void = (path: string): void => {}; private onCancelCallback(path: string): void { if (this.onCancelResolve) { this.onCancelResolve(path); } } + native cancel(): void; + onCancel(): Promise { - return new Promise((resolve: (path: string) => void, reject: (e: BusinessError) => void): void => { + return new Promise((resolve: (result: string) => void, reject: (e: BusinessError) => void): void => { this.onCancelResolve = resolve; - this.onCancelNative(); + try { + this.onCancelNative(); + } catch (e: BusinessError) { + reject(e); + } catch (e: Error) { + reject(e as BusinessError); + } }); } + } export interface CopyOptions { @@ -1309,8 +1320,8 @@ export interface RandomAccessFile { read(buffer: ArrayBuffer, callback: AsyncCallback): void; read(buffer: ArrayBuffer, options: ReadOptions, callback: AsyncCallback): void; readSync(buffer: ArrayBuffer, options?: ReadOptions): number; - // getReadStream(): ReadStream; - // getWriteStream(): WriteStream; + getReadStream(): ReadStream; + getWriteStream(): WriteStream; } export class RandomAccessFileInner implements RandomAccessFile { @@ -1331,7 +1342,7 @@ export class RandomAccessFileInner implements RandomAccessFile { } native setFilePointer0(filePointer: number): void; - + native close(): void; writeSync(buffer: ArrayBuffer | string, options?: WriteOptions): number { @@ -1350,8 +1361,8 @@ export class RandomAccessFileInner implements RandomAccessFile { promise.then((ret: NullishType): void => { let result = ret as number resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1365,8 +1376,8 @@ export class RandomAccessFileInner implements RandomAccessFile { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1379,8 +1390,8 @@ export class RandomAccessFileInner implements RandomAccessFile { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1400,8 +1411,8 @@ export class RandomAccessFileInner implements RandomAccessFile { promise.then((ret: NullishType): void => { let result = ret as number; resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1415,8 +1426,8 @@ export class RandomAccessFileInner implements RandomAccessFile { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1429,13 +1440,13 @@ export class RandomAccessFileInner implements RandomAccessFile { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } - // native getReadStream(): ReadStream; - // native getWriteStream(): WriteStream; + native getReadStream(): ReadStream; + native getWriteStream(): WriteStream; } export interface File { @@ -1474,8 +1485,8 @@ export class FileInner implements File { }, exclusive); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1488,8 +1499,8 @@ export class FileInner implements File { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1501,8 +1512,8 @@ export class FileInner implements File { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1590,7 +1601,7 @@ export class StatInner implements Stat { this.nativeStat = stat; } } - + native isBlockDevice(): boolean; native isCharacterDevice(): boolean; native isDirectory(): boolean; @@ -1632,8 +1643,8 @@ export class StreamInner implements Stream { let promise = taskpool.execute((): undefined => this.closeSync()); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1644,8 +1655,8 @@ export class StreamInner implements Stream { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1656,8 +1667,8 @@ export class StreamInner implements Stream { let promise = taskpool.execute((): undefined => this.flushSync()); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1668,8 +1679,8 @@ export class StreamInner implements Stream { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -1683,8 +1694,8 @@ export class StreamInner implements Stream { promise.then((ret: NullishType): void => { let result = ret as number resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1698,8 +1709,8 @@ export class StreamInner implements Stream { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1712,8 +1723,8 @@ export class StreamInner implements Stream { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1727,8 +1738,8 @@ export class StreamInner implements Stream { promise.then((ret: NullishType): void => { let result = ret as number resolve(result); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -1742,8 +1753,8 @@ export class StreamInner implements Stream { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } @@ -1756,162 +1767,162 @@ export class StreamInner implements Stream { e.code = 0; let result = ret as number; callback(e, result); - }).catch((e: BusinessError): void => { - callback(e, 0); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); }); } - + native readSync(buffer: ArrayBuffer, options?: ReadOptions): number; native seek(offset: number, whence?: number): number; } -// export class ReadStream extends stream.Readable { -// path: string; -// bytesRead: number; -// private offset: number; -// private start?: number; -// private end?: number; -// private stream?: Stream; - -// constructor(path: string, options?: ReadStreamOptions) { -// super(); -// this.path = path; -// this.bytesRead = 0; -// this.start = options?.start; -// this.end = options?.end; -// this.stream = createStreamSync(this.path, 'r'); -// this.offset = this.start ?? 0; -// } - -// seek(offset: number, whence?: WhenceType): number { -// if (whence === undefined) { -// let off = this.stream?.seek(offset); -// if (off !== undefined) { -// this.offset = off -// } -// } else { -// let off = this.stream?.seek(offset, whence); -// if (off !== undefined) { -// this.offset = off -// } -// } -// return this.offset; -// } - -// close(): void { -// this.stream?.close(); -// } - -// doInitialize(callback: () => void): void { -// callback(); -// } - -// doRead(size: number): void { -// let readSize = size; -// let end = this.end -// if (end !== undefined) { -// if (this.offset > end) { -// this.push(null); -// return; -// } -// if (this.offset + readSize > end) { -// readSize = end - this.offset; -// } -// } -// let buffer = new ArrayBuffer(readSize); -// const off = this.offset; -// this.offset += readSize; -// this.stream?.read(buffer, { offset: off, length: readSize }) -// .then((readOut: number) => { -// if (readOut > 0) { -// this.bytesRead += readOut; -// this.push(new Uint8Array(buffer.slice(0, readOut))); -// } -// if (readOut !== readSize || readOut < size) { -// this.offset = this.offset - readSize + readOut; -// this.push(null); -// } -// }); -// } -// } - -// export class WriteStream extends stream.Writable { -// path: string; -// bytesWritten: number; -// private offset: number; -// private mode: string; -// private start?: number; -// private stream?: Stream; - -// constructor(path: string, options?: WriteStreamOptions) { -// super(); -// this.path = path; -// this.bytesWritten = 0; -// this.start = options?.start; -// this.mode = this.convertOpenMode(options?.mode); -// this.stream = createStreamSync(this.path, this.mode); -// this.offset = this.start ?? 0; -// } - -// seek(offset: number, whence?: WhenceType): number { -// if (whence === undefined) { -// let off = this.stream?.seek(offset); -// if (off !== undefined) { -// this.offset = off -// } -// } else { -// let off = this.stream?.seek(offset, whence); -// if (off !== undefined) { -// this.offset = off -// } -// } -// return this.offset; -// } - -// close(): void { -// this.stream?.close(); -// } - -// closeSync(): void { -// this.stream?.closeSync(); -// } - -// doInitialize(callback: () => void): void { -// callback(); -// } - -// doWrite(chunk: string | ArrayBuffer, encoding: string, callback: () => void): void { -// this.stream?.write(chunk, { offset: this.offset }) -// .then((writeIn: number) => { -// this.offset += writeIn; -// this.bytesWritten += writeIn; -// callback(); -// }) -// .finally(() => { -// this.stream?.flush(); -// }); -// } - -// convertOpenMode(mode?: number): string { -// let modeStr = 'w'; -// if (mode === undefined) { -// return modeStr; -// } -// if ((mode as number) & fileIo.OpenMode.WRITE_ONLY) { -// modeStr = 'w'; -// } -// if ((mode as number) & fileIo.OpenMode.READ_WRITE) { -// modeStr = 'w+'; -// } -// if (((mode as number) & fileIo.OpenMode.WRITE_ONLY) && ((mode as number) & fileIo.OpenMode.APPEND)) { -// modeStr = 'a'; -// } -// if (((mode as number) & fileIo.OpenMode.READ_WRITE) && ((mode as number) & fileIo.OpenMode.APPEND)) { -// modeStr = 'a+'; -// } -// return modeStr; -// } -// } +export class ReadStream extends stream.Readable { + path: string; + bytesRead: number; + private offset: number; + private start?: number; + private end?: number; + private stream?: Stream; + + constructor(path: string, options?: ReadStreamOptions) { + super(); + this.path = path; + this.bytesRead = 0; + this.start = options?.start; + this.end = options?.end; + this.stream = createStreamSync(this.path, 'r'); + this.offset = this.start ?? 0; + } + + seek(offset: number, whence?: WhenceType): number { + if (whence === undefined) { + let off = this.stream?.seek(offset); + if (off !== undefined) { + this.offset = off + } + } else { + let off = this.stream?.seek(offset, whence); + if (off !== undefined) { + this.offset = off + } + } + return this.offset; + } + + close(): void { + this.stream?.close(); + } + + doInitialize(callback: () => void): void { + callback(); + } + + doRead(size: number): void { + let readSize = size; + let end = this.end + if (end !== undefined) { + if (this.offset > end) { + this.push(null); + return; + } + if (this.offset + readSize > end) { + readSize = end - this.offset; + } + } + let buffer = new ArrayBuffer(readSize); + const off = this.offset; + this.offset += readSize; + this.stream?.read(buffer, { offset: off, length: readSize }) + .then((readOut: number) => { + if (readOut > 0) { + this.bytesRead += readOut; + this.push(new Uint8Array(buffer.slice(0, readOut))); + } + if (readOut !== readSize || readOut < size) { + this.offset = this.offset - readSize + readOut; + this.push(null); + } + }); + } +} + +export class WriteStream extends stream.Writable { + path: string; + bytesWritten: number; + private offset: number; + private mode: string; + private start?: number; + private stream?: Stream; + + constructor(path: string, options?: WriteStreamOptions) { + super(); + this.path = path; + this.bytesWritten = 0; + this.start = options?.start; + this.mode = this.convertOpenMode(options?.mode); + this.stream = createStreamSync(this.path, this.mode); + this.offset = this.start ?? 0; + } + + seek(offset: number, whence?: WhenceType): number { + if (whence === undefined) { + let off = this.stream?.seek(offset); + if (off !== undefined) { + this.offset = off + } + } else { + let off = this.stream?.seek(offset, whence); + if (off !== undefined) { + this.offset = off + } + } + return this.offset; + } + + close(): void { + this.stream?.close(); + } + + closeSync(): void { + this.stream?.closeSync(); + } + + doInitialize(callback: () => void): void { + callback(); + } + + doWrite(chunk: string | ArrayBuffer, encoding: string, callback: () => void): void { + this.stream?.write(chunk, { offset: this.offset }) + .then((writeIn: number) => { + this.offset += writeIn; + this.bytesWritten += writeIn; + callback(); + }) + .finally(() => { + this.stream?.flush(); + }); + } + + convertOpenMode(mode?: number): string { + let modeStr = 'w'; + if (mode === undefined) { + return modeStr; + } + if ((mode as number) & fileIo.OpenMode.WRITE_ONLY) { + modeStr = 'w'; + } + if ((mode as number) & fileIo.OpenMode.READ_WRITE) { + modeStr = 'w+'; + } + if (((mode as number) & fileIo.OpenMode.WRITE_ONLY) && ((mode as number) & fileIo.OpenMode.APPEND)) { + modeStr = 'a'; + } + if (((mode as number) & fileIo.OpenMode.READ_WRITE) && ((mode as number) & fileIo.OpenMode.APPEND)) { + modeStr = 'a+'; + } + return modeStr; + } +} export class AtomicFile { static { @@ -1920,42 +1931,42 @@ export class AtomicFile { private nativePtr: long = 0; private native getPath(): string; - // private writeStream: WriteStream | null = null; + private writeStream: WriteStream | null = null; native constructor(path: string); native getBaseFile(): File; - // native openRead(): ReadStream; + native openRead(): ReadStream; native readFully(): ArrayBuffer; - // native nativeStartWrite(): WriteStream; - // startWrite(): WriteStream { - // let ws = this.nativeStartWrite(); - // this.writeStream = ws; - // return ws; - // } - - // native nativeFinishWrite(): void; - // finishWrite(): void { - // if (!this.writeStream) { - // throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); - // } - // this.writeStream?.close(); - // this.nativeFinishWrite(); - // this.writeStream = null; - // }; - - // native nativeFailWrite(): void; - // failWrite(): void { - // if (!this.writeStream) { - // throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); - // } - // this.writeStream?.close(); - // this.nativeFailWrite(); - // this.writeStream = null; - // }; + native nativeStartWrite(): WriteStream; + startWrite(): WriteStream { + let ws = this.nativeStartWrite(); + this.writeStream = ws; + return ws; + } + + native nativeFinishWrite(): void; + finishWrite(): void { + if (!this.writeStream) { + throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + } + this.writeStream?.close(); + this.nativeFinishWrite(); + this.writeStream = null; + }; + + native nativeFailWrite(): void; + failWrite(): void { + if (!this.writeStream) { + throw createBusinessError(UNKNOWN_ERR, UNKNOWN_MSG); + } + this.writeStream?.close(); + this.nativeFailWrite(); + this.writeStream = null; + }; native delete(): void; } @@ -2119,15 +2130,15 @@ export class FileIoImpl { static native createStreamSync(path: string, mode: string): fileIo.Stream; static native createWatcherSync(path: string, events: number, listener: WatchEventListener): fileIo.Watcher; - + static native fdopenStreamSync(fd: number, mode: string): fileIo.Stream; - + static native dup(fd: number): fileIo.File; static native listFileSync(path: string, options?: ListFileOptions): string[]; static native lstatSync(path: string): fileIo.Stat; - + static native lseekSync(fd: number, offset: number, whence?: fileIo.WhenceType): number; static native mkdirSync(path: string): void; @@ -2143,7 +2154,7 @@ export class FileIoImpl { static native openSync(path: String, mode?: number): fileIo.File; static native readlinesSync(filePath: string, options?: Options): fileIo.ReaderIterator; - + static native readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number; static native readTextSync(filePath: string, options?: ReadTextOptions): string; diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp new file mode 100644 index 000000000..71666f6ea --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.cpp @@ -0,0 +1,367 @@ +/* + * 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_ani.h" + +#include + +#include "ani_signature.h" +#include "error_handler.h" +#include "file_wrapper.h" +#include "filemgmt_libhilog.h" +#include "fs_atomicfile.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +namespace fs = std::filesystem; +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +const std::string READ_STREAM_CLASS = "ReadStream"; +const std::string WRITE_STREAM_CLASS = "WriteStream"; +const std::string TEMP_FILE_SUFFIX = "_XXXXXX"; + +void AtomicFileAni::Constructor(ani_env *env, ani_object obj, ani_string pathObj) +{ + auto [succ, filePath] = TypeConverter::ToUTF8String(env, pathObj); + if (!succ) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + + auto ret = FsAtomicFile::Constructor(filePath); + if (!ret.IsSuccess()) { + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } + + if (ANI_OK != + env->Object_SetFieldByName_Long(obj, "nativePtr", + static_cast(reinterpret_cast(ret.GetData().value())))) { + HILOGE("Failed to wrap entity for obj AtomicFile"); + ErrorHandler::Throw(env, EIO); + return; + } +} + +static FsAtomicFile *Unwrap(ani_env *env, ani_object object) +{ + ani_long file; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &file); + if (ret != ANI_OK) { + HILOGE("Unwrap file err: %{private}d", ret); + return nullptr; + } + + return reinterpret_cast(file); +} + +ani_string AtomicFileAni::GetPath(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto file = Unwrap(env, object); + if (file == nullptr) { + ErrorHandler::Throw(env, E_PARAMS); + return nullptr; + } + + string path = file->GetPath(); + auto [succ, result] = TypeConverter::ToAniString(env, path); + if (!succ) { + HILOGE("ToAniString failed"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + return result; +} + +ani_object AtomicFileAni::GetBaseFile(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto ret = atomicFile->GetBaseFile(); + if (!ret.IsSuccess()) { + HILOGE("Failed to GetBaseFile"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const FsFile *fsFile = ret.GetData().value(); + auto result = FileWrapper::Wrap(env, move(fsFile)); + if (result == nullptr) { + HILOGE("Failed to wrap"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + return result; +} + +static ani_object CreateReadStream(ani_env *env, ani_string filePath) +{ + auto classDesc = FS::ReadStream::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + + auto ctorDesc = FS::ReadStream::ctorDesc.c_str(); + auto ctorSig = FS::ReadStream::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath)) { + HILOGE("New %s obj Failed", classDesc); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateWriteStream(ani_env *env, ani_string filePath) +{ + auto classDesc = FS::WriteStream::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + + auto ctorDesc = FS::WriteStream::ctorDesc.c_str(); + auto ctorSig = FS::WriteStream::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath)) { + HILOGE("New %s obj Failed", classDesc); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateStream( + ani_env *env, [[maybe_unused]] ani_object object, const std::string &streamName, const std::string &fileName) +{ + auto [succ, filePath] = TypeConverter::ToAniString(env, fileName); + if (!succ) { + HILOGE("Failed to ani_string"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + if (streamName == READ_STREAM_CLASS) { + auto stream = CreateReadStream(env, filePath); + if (stream == nullptr) { + HILOGE("Failed to create read stream"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return move(stream); + } + if (streamName == WRITE_STREAM_CLASS) { + auto stream = CreateWriteStream(env, filePath); + if (stream == nullptr) { + HILOGE("Failed to create write stream"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return move(stream); + } + + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; +} + +ani_object AtomicFileAni::OpenRead(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = atomicFile->GetEntity(); + if (entity == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + return CreateStream(env, object, READ_STREAM_CLASS, entity->baseFileName); +} + +ani_arraybuffer AtomicFileAni::ReadFully(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto ret = atomicFile->ReadFully(); + if (!ret.IsSuccess()) { + HILOGE("Failed to read fully"); + ErrorHandler::Throw(env, ret.GetError()); + return nullptr; + } + + auto &bufferData = ret.GetData().value(); + uint8_t *buffer = bufferData->buffer; + size_t length = bufferData->length; + auto [succ, obj] = TypeConverter::ToAniArrayBuffer(env, buffer, length); + if (!succ) { + HILOGE("Failed to ani_arrayBuffer"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + return obj; +} + +ani_object AtomicFileAni::StartWrite(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = atomicFile->GetEntity(); + if (entity == nullptr) { + HILOGE("Failed to get atomicFile entity"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + fs::path filePath = entity->newFileName; + fs::path parentPath = filePath.parent_path(); + if (access(parentPath.c_str(), F_OK) != 0) { + HILOGE("Parent directory does not exist, err:%{public}d", errno); + ErrorHandler::Throw(env, ENOENT); + return nullptr; + } + + char *tmpfile = const_cast(entity->newFileName.c_str()); + if (mkstemp(tmpfile) == -1) { + HILOGE("Fail to create tmp file err:%{public}d!", errno); + ErrorHandler::Throw(env, ENOENT); + return nullptr; + } + + ani_object writeStream = CreateStream(env, object, WRITE_STREAM_CLASS, entity->newFileName); + if (writeStream == nullptr) { + HILOGE("Failed to create write stream"); + return nullptr; + } + + return writeStream; +} + +void AtomicFileAni::FinishWrite(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + + auto entity = atomicFile->GetEntity(); + if (entity == nullptr) { + HILOGE("Failed to get atomicFile entity"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + + auto ret = atomicFile->FinishWrite(); + if (!ret.IsSuccess()) { + HILOGE("Failed to finish write"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + } + return; +} + +void AtomicFileAni::FailWrite(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + + auto entity = atomicFile->GetEntity(); + if (entity == nullptr) { + HILOGE("Failed to get atomicFile entity"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + + auto ret = atomicFile->FailWrite(); + if (!ret.IsSuccess()) { + HILOGE("Failed to fail write"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + } + return; +} + +void AtomicFileAni::Delete(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto atomicFile = Unwrap(env, object); + if (atomicFile == nullptr) { + HILOGE("Failed to get atomicFile"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + + auto ret = atomicFile->Delete(); + if (!ret.IsSuccess()) { + HILOGE("Failed to delete"); + ErrorHandler::Throw(env, ret.GetError()); + return; + } + + return; +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.h b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.h new file mode 100644 index 000000000..08898f125 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/ani/atomicfile_ani.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_ATOMICFILE_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_ATOMICFILE_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class AtomicFileAni final { +public: + static void Constructor(ani_env *env, ani_object obj, ani_string pathObj); + static ani_string GetPath(ani_env *env, [[maybe_unused]] ani_object object); + static ani_object GetBaseFile(ani_env *env, [[maybe_unused]] ani_object object); + static ani_object OpenRead(ani_env *env, [[maybe_unused]] ani_object object); + static ani_arraybuffer ReadFully(ani_env *env, [[maybe_unused]] ani_object object); + static ani_object StartWrite(ani_env *env, [[maybe_unused]] ani_object object); + static void FinishWrite(ani_env *env, [[maybe_unused]] ani_object object); + static void FailWrite(ani_env *env, [[maybe_unused]] ani_object object); + static void Delete(ani_env *env, [[maybe_unused]] ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_ATOMICFILE_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.cpp b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.cpp new file mode 100644 index 000000000..2caa33889 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.cpp @@ -0,0 +1,235 @@ +/* + * 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 "fs_atomicfile.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "fs_atomicfile_entity.h" +#include "filemgmt_libfs.h" +#include "file_instantiator.h" +#include "file_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace fs = std::filesystem; + +const std::string READ_STREAM_CLASS = "ReadStream"; +const std::string WRITE_STREAM_CLASS = "WriteStream"; +const std::string TEMP_FILE_SUFFIX = "_XXXXXX"; + +FsAtomicFileEntity *FsAtomicFile::GetEntity() +{ + if (!entity) { + return nullptr; + } + return entity.get(); +} + +void FsAtomicFile::FinalizeCallback(void *finalizeData, [[maybe_unused]] void *finalizeHint) +{ + BufferData *bufferData = static_cast(finalizeData); + delete bufferData; +} + +string FsAtomicFile::GetPath() +{ + return entity->baseFileName; +} + +FsResult FsAtomicFile::GetBaseFile() +{ + if (entity == nullptr) { + HILOGE("Failed to get atomicFileEntity"); + return FsResult::Error(UNKNOWN_ERR); + } + + if (entity->baseFileName.size() >= PATH_MAX) { + HILOGE("Base file name is too long"); + return FsResult::Error(UNKNOWN_ERR); + } + + auto absolutePath = std::make_unique(PATH_MAX); + char *result = realpath(entity->baseFileName.c_str(), absolutePath.get()); + if (result == nullptr) { + HILOGE("Failed to resolve real path, err:%{public}d", errno); + return FsResult::Error(errno); + } + + int fd = open(result, O_RDONLY); + if (fd < 0) { + HILOGE("Failed to open file, err:%{public}d", errno); + return FsResult::Error(errno); + } + + return FileInstantiator::InstantiateFile(fd, entity->baseFileName, false); +} + +static std::tuple, int32_t> ReadFileToBuffer(FILE *fp) +{ + int fd = fileno(fp); + if (fd < 0) { + HILOGE("Failed to get file descriptor, err:%{public}d", errno); + return { nullptr, UNKNOWN_ERR }; + } + + struct stat fileStat {}; + if (fstat(fd, &fileStat) < 0) { + HILOGE("Failed to get file stats, err:%{public}d", errno); + return { nullptr, errno }; + } + + long fileSize = fileStat.st_size; + if (fileSize <= 0) { + HILOGE("Invalid file size"); + return { nullptr, EIO }; + } + + auto bufferData = std::make_unique(); + bufferData->buffer = new (std::nothrow) uint8_t[fileSize]; + if (bufferData->buffer == nullptr) { + HILOGE("Failed to allocate memory"); + return { nullptr, ENOMEM }; + } + bufferData->length = fread(bufferData->buffer, sizeof(uint8_t), fileSize, fp); + if ((bufferData->length != static_cast(fileSize) && !feof(fp)) || ferror(fp)) { + HILOGE("Failed to read file, actual length is:%zu, fileSize:%ld", bufferData->length, fileSize); + delete[] bufferData->buffer; + bufferData->buffer = nullptr; + bufferData->length = 0; + return { nullptr, EIO }; + } + return { std::move(bufferData), ERRNO_NOERR }; +} + +FsResult> FsAtomicFile::ReadFully() +{ + if (entity == nullptr) { + HILOGE("Failed to get atomicFileEntity"); + return FsResult>::Error(UNKNOWN_ERR); + } + + auto absolutePath = std::make_unique(PATH_MAX); + char *result = realpath(entity->baseFileName.c_str(), absolutePath.get()); + if (result == nullptr) { + HILOGE("Failed to resolve file real path, err:%{public}d", errno); + return FsResult>::Error(errno); + } + + auto file = std::unique_ptr(std::fopen(result, "rb"), &std::fclose); + if (!file) { + HILOGE("Failed to open file, err:%{public}d", errno); + return FsResult>::Error(errno); + } + + auto [bufferData, errCode] = ReadFileToBuffer(file.get()); + if (errCode != ERRNO_NOERR) { + return FsResult>::Error(errCode); + } + return FsResult>::Success(move(bufferData)); +} + +FsResult FsAtomicFile::StartWrite() +{ + fs::path filePath = entity->newFileName; + fs::path parentPath = filePath.parent_path(); + if (access(parentPath.c_str(), F_OK) != 0) { + HILOGE("Parent directory does not exist, err:%{public}d", errno); + return FsResult::Error(ENOENT); + } + + char *tmpfile = const_cast(entity->newFileName.c_str()); + if (mkstemp(tmpfile) == -1) { + HILOGE("Fail to create tmp file err:%{public}d!", errno); + return FsResult::Error(ENOENT); + } + + return FsResult::Success(entity->newFileName); +} + +FsResult FsAtomicFile::FinishWrite() +{ + if (std::rename(entity->newFileName.c_str(), entity->baseFileName.c_str()) != 0) { + HILOGE("rename failed"); + return FsResult::Error(errno); + } + std::string tmpNewFileName = entity->baseFileName; + entity->newFileName = tmpNewFileName.append(TEMP_FILE_SUFFIX); + + return FsResult::Success(); +} + +FsResult FsAtomicFile::FailWrite() +{ + if (!fs::remove(entity->newFileName)) { + HILOGW("Failed to remove file"); + return FsResult::Error(errno); + } + std::string tmpNewFileName = entity->baseFileName; + entity->newFileName = tmpNewFileName.append(TEMP_FILE_SUFFIX); + + return FsResult::Success(); +} + +FsResult FsAtomicFile::Delete() +{ + auto rafentity = GetEntity(); + if (rafentity == nullptr) { + HILOGE("Failed to get atomicFileEntity"); + return FsResult::Error(UNKNOWN_ERR); + } + + bool errFlag = false; + std::error_code fsErrcode; + if (fs::exists(rafentity->newFileName, fsErrcode) && !fs::remove(rafentity->newFileName, fsErrcode)) { + errFlag = true; + } + if (fs::exists(rafentity->baseFileName, fsErrcode) && !fs::remove(rafentity->baseFileName, fsErrcode)) { + errFlag = true; + } + if (errFlag) { + HILOGE("Failed to remove file, err:%{public}s", fsErrcode.message().c_str()); + return FsResult::Error(fsErrcode.value()); + } + + rafentity->newFileName.clear(); + rafentity->baseFileName.clear(); + return FsResult::Success(); +} + +FsResult FsAtomicFile::Constructor(string path) +{ + auto atomicFileEntity = CreateUniquePtr(); + if (atomicFileEntity == nullptr) { + HILOGE("Failed to request heap memory"); + return FsResult::Error(ENOMEM); + } + atomicFileEntity->baseFileName = path; + atomicFileEntity->newFileName = path.append(TEMP_FILE_SUFFIX); + + auto file = new FsAtomicFile(move(atomicFileEntity)); + + return FsResult::Success(file); +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.h b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.h new file mode 100644 index 000000000..80996b1c7 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_H + +#include "fs_atomicfile_entity.h" +#include "fs_file.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct BufferData { + uint8_t *buffer = nullptr; + size_t length = 0; + + ~BufferData() + { + delete[] buffer; + } +}; + +class FsAtomicFile final { +public: + FsAtomicFileEntity *GetEntity(); + static FsResult Constructor(string path); + string GetPath(); + FsResult GetBaseFile(); + FsResult> ReadFully(); + FsResult StartWrite(); + FsResult FinishWrite(); + FsResult FailWrite(); + FsResult Delete(); + static void FinalizeCallback(void *finalizeData, [[maybe_unused]] void *finalizeHint); + +private: + unique_ptr entity; + explicit FsAtomicFile(unique_ptr entity) : entity(move(entity)) {} +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile_entity.h b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile_entity.h new file mode 100644 index 000000000..71bcb9ee1 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_atomicfile/fs_atomicfile_entity.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_ENTITY_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +struct FsAtomicFileEntity { + std::string baseFileName = ""; + std::string newFileName = ""; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_ATOMICFILE_FS_ATOMICFILE_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp new file mode 100644 index 000000000..604835791 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.cpp @@ -0,0 +1,488 @@ +/* + * 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 "randomaccessfile_ani.h" + +#include "ani_helper.h" +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fs_randomaccessfile.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +const int BUF_SIZE = 1024; +const string READ_STREAM_CLASS = "ReadStream"; +const string WRITE_STREAM_CLASS = "WriteStream"; + +static FsRandomAccessFile *Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap FsRandomAccessFile err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsRandomAccessFile *rafFile = reinterpret_cast(ptrValue); + return rafFile; +} + +static tuple> ToReadOptions(ani_env *env, ani_object obj) +{ + ReadOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + return { true, make_optional(move(options)) }; +} + +static tuple> ToWriteOptions(ani_env *env, ani_object obj) +{ + WriteOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + + auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj); + if (!succEncoding) { + HILOGE("Illegal option.encoding parameter"); + return { false, nullopt }; + } + options.encoding = encoding; + return { true, make_optional(move(options)) }; +} + +static tuple ParseStringBuffer(ani_env *env, const ani_object &buf) +{ + ani_class cls; + auto classDesc = BuiltInTypes::String::classDesc.c_str(); + env->FindClass(classDesc, &cls); + + ani_boolean isString; + env->Object_InstanceOf(buf, cls, &isString); + if (!isString) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, move(result) }; +} + +static tuple ParseArrayBuffer(ani_env *env, const ani_object &buf) +{ + ani_class cls; + auto classDesc = BuiltInTypes::ArrayBuffer::classDesc.c_str(); + env->FindClass(classDesc, &cls); + + ani_boolean isArrayBuffer; + env->Object_InstanceOf(buf, cls, &isArrayBuffer); + if (!isArrayBuffer) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, move(result) }; +} + +void RandomAccessFileAni::SetFilePointer(ani_env *env, [[maybe_unused]] ani_object object, ani_double fp) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + auto ret = rafFile->SetFilePointerSync(static_cast(fp)); + if (!ret.IsSuccess()) { + HILOGE("SetFilePointerSync failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +void RandomAccessFileAni::Close(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + auto ret = rafFile->CloseSync(); + if (!ret.IsSuccess()) { + HILOGE("close rafFile failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +ani_double RandomAccessFileAni::WriteSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return -1; + } + + auto [succOp, op] = ToWriteOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [isString, stringBuffer] = ParseStringBuffer(env, buf); + if (isString) { + auto [succBuf, buffer] = TypeConverter::ToUTF8String(env, stringBuffer); + if (!succBuf) { + HILOGE("Failed to resolve stringBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = rafFile->WriteSync(buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + ErrorHandler::Throw(env, ret.GetError()); + return -1; + } + return static_cast(ret.GetData().value()); + } + + auto [isArrayBuffer, arrayBuffer] = ParseArrayBuffer(env, buf); + if (isArrayBuffer) { + auto [succBuf, buffer] = TypeConverter::ToArrayBuffer(env, arrayBuffer); + if (!succBuf) { + HILOGE("Failed to resolve arrayBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = rafFile->WriteSync(buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + ErrorHandler::Throw(env, ret.GetError()); + return -1; + } + return static_cast(ret.GetData().value()); + } + HILOGE("Unsupported buffer type!"); + ErrorHandler::Throw(env, EINVAL); + return -1; +} + +ani_double RandomAccessFileAni::ReadSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buf, ani_object options) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return -1; + } + + auto [succBuf, arrayBuffer] = TypeConverter::ToArrayBuffer(env, buf); + if (!succBuf) { + HILOGE("Failed to resolve arrayBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [succOp, op] = ToReadOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto ret = rafFile->ReadSync(arrayBuffer, op); + if (!ret.IsSuccess()) { + HILOGE("Read file content failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); +} + +static ani_string GetFilePath(ani_env *env, const int fd) +{ + auto dstFd = dup(fd); + if (dstFd < 0) { + HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno), fd); + return nullptr; + } + + string path = "/proc/self/fd/" + to_string(dstFd); + auto buf = CreateUniquePtr(BUF_SIZE); + int readLinkRes = readlink(path.c_str(), buf.get(), BUF_SIZE); + if (readLinkRes < 0) { + close(dstFd); + return nullptr; + } + + close(dstFd); + auto [succ, filePath] = TypeConverter::ToAniString(env, string(buf.get())); + if (!succ) { + return nullptr; + } + return move(filePath); +} + +static ani_object CreateReadStreamOptions(ani_env *env, int64_t start, int64_t end) +{ + static const char *className = "L@ohos/file/fs/ReadStreamOptionsInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + ani_field startField = nullptr; + ani_field endField = nullptr; + if (ANI_OK != env->Class_FindField(cls, "start", &startField)) { + HILOGE("Cannot find start in class %s", className); + return nullptr; + } + if (ANI_OK != env->Class_FindField(cls, "end", &endField)) { + HILOGE("Cannot find end in class %s", className); + return nullptr; + } + + if (start >= 0) { + env->Object_SetField_Int(obj, startField, start); + } + if (end >= 0) { + env->Object_SetField_Int(obj, endField, end); + } + if (obj == nullptr) { + HILOGE("CreateReadStreamOptions is nullptr"); + } + + return move(obj); +} + +static ani_object CreateWriteStreamOptions(ani_env *env, int64_t start, int flags) +{ + static const char *className = "L@ohos/file/fs/WriteStreamOptionsInner;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + ani_field modeField = nullptr; + ani_field startField = nullptr; + if (ANI_OK != env->Class_FindField(cls, "mode", &modeField)) { + HILOGE("Cannot find mode in class %s", className); + return nullptr; + } + if (ANI_OK != env->Class_FindField(cls, "start", &startField)) { + HILOGE("Cannot find start in class %s", className); + return nullptr; + } + + env->Object_SetField_Int(obj, modeField, flags); + if (start >= 0) { + env->Object_SetField_Int(obj, startField, start); + } + + return move(obj); +} + +static ani_object CreateReadStream(ani_env *env, ani_string filePath, ani_object options) +{ + static const char *className = "L@ohos/file/fs/fileIo/ReadStream;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;L@ohos/file/fs/ReadStreamOptions;:V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath, options)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateWriteStream(ani_env *env, ani_string filePath, ani_object options) +{ + static const char *className = "L@ohos/file/fs/fileIo/WriteStream;"; + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + HILOGE("Cannot find class %s", className); + return nullptr; + } + ani_method ctor; + if (ANI_OK != + env->Class_FindMethod(cls, "", "Lstd/core/String;L@ohos/file/fs/WriteStreamOptions;:V", &ctor)) { + HILOGE("Cannot find constructor method for class %s", className); + return nullptr; + } + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, filePath, options)) { + HILOGE("New %s obj Failed", className); + return nullptr; + } + + return move(obj); +} + +static ani_object CreateStream(ani_env *env, const string &streamName, RandomAccessFileEntity *rafEntity, int flags) +{ + ani_string filePath = GetFilePath(env, rafEntity->fd.get()->GetFD()); + if (!filePath) { + HILOGE("Get file path failed, errno=%{public}d", errno); + ErrorHandler::Throw(env, errno); + return nullptr; + } + + if (streamName == READ_STREAM_CLASS) { + ani_object obj = CreateReadStreamOptions(env, rafEntity->start, rafEntity->end); + return CreateReadStream(env, filePath, obj); + } + if (streamName == WRITE_STREAM_CLASS) { + ani_object obj = CreateWriteStreamOptions(env, rafEntity->start, flags); + return CreateWriteStream(env, filePath, obj); + } + + return nullptr; +} + +ani_object RandomAccessFileAni::GetReadStream(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = rafFile->GetRAFEntity(); + if (!entity) { + HILOGE("Get RandomAccessFileEntity failed!"); + ErrorHandler::Throw(env, EIO); + return nullptr; + } + + int flags = fcntl(entity->fd.get()->GetFD(), F_GETFL); + unsigned int uflags = static_cast(flags); + if (((uflags & O_ACCMODE) != O_RDONLY) && ((uflags & O_ACCMODE) != O_RDWR)) { + HILOGE("Failed to check Permission"); + ErrorHandler::Throw(env, EACCES); + return nullptr; + } + + return CreateStream(env, READ_STREAM_CLASS, entity, flags); +} + +ani_object RandomAccessFileAni::GetWriteStream(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto rafFile = Unwrap(env, object); + if (rafFile == nullptr) { + HILOGE("Cannot unwrap rafFile!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto entity = rafFile->GetRAFEntity(); + if (!entity) { + HILOGE("Get RandomAccessFileEntity failed!"); + ErrorHandler::Throw(env, EIO); + return nullptr; + } + + int flags = fcntl(entity->fd.get()->GetFD(), F_GETFL); + unsigned int uflags = static_cast(flags); + if (((uflags & O_ACCMODE) != O_WRONLY) && ((uflags & O_ACCMODE) != O_RDWR)) { + HILOGE("Failed to check Permission"); + ErrorHandler::Throw(env, EACCES); + return nullptr; + } + + return CreateStream(env, WRITE_STREAM_CLASS, entity, flags); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h new file mode 100644 index 000000000..d1a29d8ec --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/ani/randomaccessfile_ani.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_ANI_RANDOMACCESSFILE_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_ANI_RANDOMACCESSFILE_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class RandomAccessFileAni final { +public: + static void SetFilePointer(ani_env *env, [[maybe_unused]] ani_object object, ani_double fp); + static void Close(ani_env *env, [[maybe_unused]] ani_object object); + static ani_double WriteSync(ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options); + static ani_double ReadSync( + ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buf, ani_object options); + static ani_object GetReadStream(ani_env *env, [[maybe_unused]] ani_object object); + static ani_object GetWriteStream(ani_env *env, [[maybe_unused]] ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_ANI_RANDOMACCESSFILE_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.cpp b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.cpp new file mode 100644 index 000000000..8d8b149f6 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.cpp @@ -0,0 +1,287 @@ +/* +* 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 "fs_randomaccessfile.h" + +#include + +#include "file_uri.h" +#include "file_utils.h" +#include "filemgmt_libfs.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int DoReadRAF(void* buf, size_t len, int fd, int64_t offset) +{ + unique_ptr readReq = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (readReq == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + uv_buf_t iov = uv_buf_init(static_cast(buf), len); + int ret = uv_fs_read(nullptr, readReq.get(), fd, &iov, 1, offset, nullptr); + return ret; +} + +static int DoWriteRAF(void* buf, size_t len, int fd, int64_t offset) +{ + unique_ptr writeReq = { + new (nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (writeReq == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + uv_buf_t iov = uv_buf_init(static_cast(buf), len); + int ret = uv_fs_write(nullptr, writeReq.get(), fd, &iov, 1, offset, nullptr); + return ret; +} + +FsResult FsRandomAccessFile::GetFD() const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + return FsResult::Success(rafEntity->fd.get()->GetFD()); +} + +FsResult FsRandomAccessFile::GetFPointer() const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + return FsResult::Success(rafEntity->filePointer); +} + +FsResult FsRandomAccessFile::SetFilePointerSync(const int64_t &fp) const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + rafEntity->filePointer = fp; + return FsResult::Success(); +} + +static int64_t CalculateOffset(int64_t offset, int64_t fPointer) +{ + if (offset < 0) { + HILOGD("No specified offset provided"); + offset = fPointer; + } else { + offset += fPointer; + } + return offset; +} + +tuple ValidReadArg(ArrayBuffer &buffer, const optional &options) +{ + size_t retLen = 0; + int64_t offset = -1; + bool succ = false; + void *buf = buffer.buf; + size_t bufLen = buffer.length; + + if (bufLen > UINT_MAX) { + HILOGE("Invalid arraybuffer"); + return { false, nullptr, retLen, offset }; + } + optional lengthOp = nullopt; + optional offsetOp = nullopt; + if (options.has_value()) { + ReadOptions op = options.value(); + lengthOp = op.length; + offsetOp = op.offset; + } + tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp); + if (!succ) { + HILOGE("Failed to get actual length"); + return { false, nullptr, retLen, offset }; + } + if (offsetOp.has_value()) { + offset = offsetOp.value(); + if (offset < 0) { + HILOGE("option.offset shall be positive number"); + return { false, nullptr, retLen, offset }; + } + } + return { true, buf, retLen, offset }; +} + +FsResult FsRandomAccessFile::ReadSync(ArrayBuffer &buffer, const optional &options) const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + auto [succ, buf, len, offset] = ValidReadArg(buffer, options); + if (!succ) { + HILOGE("Invalid buffer/options"); + return FsResult::Error(EINVAL); + } + offset = CalculateOffset(offset, rafEntity->filePointer); + int actLen = DoReadRAF(buf, len, rafEntity->fd.get()->GetFD(), offset); + if (actLen < 0) { + HILOGE("Failed to read file for %{private}d", actLen); + return FsResult::Error(actLen); + } + rafEntity->filePointer = offset + actLen; + return FsResult::Success(static_cast(actLen)); +} + +tuple ValidWriteArg( + void *buffer, const size_t bufLen, const optional &options) +{ + size_t retLen = 0; + int64_t offset = -1; + bool succ = false; + + if (bufLen > UINT_MAX) { + HILOGE("The Size of buffer is too large"); + return { false, nullptr, 0, offset }; + } + + optional lengthOp = nullopt; + optional offsetOp = nullopt; + if (options.has_value()) { + WriteOptions op = options.value(); + lengthOp = op.length; + offsetOp = op.offset; + } + + tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp); + if (!succ) { + HILOGE("Failed to get actual length"); + return { false, nullptr, 0, offset }; + } + + if (offsetOp.has_value()) { + offset = offsetOp.value(); + if (offset < 0) { + HILOGE("option.offset shall be positive number"); + return { false, nullptr, 0, offset }; + } + } + return { true, buffer, retLen, offset }; +} + +FsResult FsRandomAccessFile::WriteSync(const string &buffer, const optional &options) const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + + bool succ = false; + size_t len = 0; + int64_t offset = -1; + void *buf = nullptr; + size_t bufLen = static_cast(buffer.length()); + + tie(succ, buf, len, offset) = ValidWriteArg(const_cast(static_cast(buffer.c_str())), + bufLen, options); + if (!succ) { + HILOGE("Invalid buffer/options"); + return FsResult::Error(EINVAL); + } + offset = CalculateOffset(offset, rafEntity->filePointer); + int writeLen = DoWriteRAF(buf, len, rafEntity->fd.get()->GetFD(), offset); + if (writeLen < 0) { + return FsResult::Error(writeLen); + } + rafEntity->filePointer = offset + writeLen; + return FsResult::Success(static_cast(writeLen)); +} + +FsResult FsRandomAccessFile::WriteSync(const ArrayBuffer &buffer, const optional &options) const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + + bool succ = false; + size_t len = 0; + int64_t offset = -1; + void *buf = nullptr; + + tie(succ, buf, len, offset) = ValidWriteArg(buffer.buf, buffer.length, options); + if (!succ) { + HILOGE("Invalid buffer/options"); + return FsResult::Error(EINVAL); + } + offset = CalculateOffset(offset, rafEntity->filePointer); + int writeLen = DoWriteRAF(buf, len, rafEntity->fd.get()->GetFD(), offset); + if (writeLen < 0) { + return FsResult::Error(writeLen); + } + rafEntity->filePointer = offset + writeLen; + return FsResult::Success(static_cast(writeLen)); +} + +static int CloseFd(int fd) +{ + unique_ptr closeReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!closeReq) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int ret = uv_fs_close(nullptr, closeReq.get(), fd, nullptr); + if (ret < 0) { + HILOGE("Failed to close file with ret: %{private}d", ret); + return ret; + } + return ERRNO_NOERR; +} + +FsResult FsRandomAccessFile::CloseSync() const +{ + if (!rafEntity) { + HILOGE("Failed to get entity of RandomAccessFile"); + return FsResult::Error(EIO); + } + auto err = CloseFd(rafEntity->fd.get()->GetFD()); + if (err) { + return FsResult::Error(err); + } + return FsResult::Success(); +} + +FsResult FsRandomAccessFile::Constructor() +{ + auto rafEntity = CreateUniquePtr(); + if (rafEntity == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + FsRandomAccessFile *randomAccessFilePtr = new FsRandomAccessFile(move(rafEntity)); + if (randomAccessFilePtr == nullptr) { + HILOGE("INNER BUG. Failed to wrap entity for obj RandomAccessFile"); + return FsResult::Error(EIO); + } + return FsResult::Success(move(randomAccessFilePtr)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h new file mode 100644 index 000000000..8756a9e33 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/fs_randomaccessfile.h @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_FS_RANDOMACCESSFILE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_FS_RANDOMACCESSFILE_H + +#include "randomaccessfile_entity.h" +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct WriteOptions { + optional length = nullopt; + optional offset = nullopt; + optional encoding = nullopt; +}; + +struct ReadOptions { + optional offset = nullopt; + optional length = nullopt; +}; + +class FsRandomAccessFile { +public: + inline static const string className_ = "RandomAccessFile"; + + RandomAccessFileEntity *GetRAFEntity() const + { + return rafEntity.get(); + } + + FsRandomAccessFile(const FsRandomAccessFile &other) = delete; + FsRandomAccessFile &operator=(const FsRandomAccessFile &other) = delete; + + FsRandomAccessFile(FsRandomAccessFile &&other) noexcept : rafEntity(move(other.rafEntity)) + { + other.rafEntity = nullptr; + } + + FsRandomAccessFile &operator=(FsRandomAccessFile &&other) noexcept + { + if (this != &other) { + rafEntity = move(other.rafEntity); + other.rafEntity = nullptr; + } + return *this; + } + + ~FsRandomAccessFile() = default; + + FsResult SetFilePointerSync(const int64_t &fp) const; + FsResult WriteSync(const string &buffer, const optional &options = nullopt) const; + FsResult WriteSync(const ArrayBuffer &buffer, const optional &options = nullopt) const; + FsResult ReadSync(ArrayBuffer &buffer, const optional &options = nullopt) const; + FsResult CloseSync() const; + + FsResult GetFD() const; + FsResult GetFPointer() const; + + static FsResult Constructor(); + +private: + unique_ptr rafEntity; + explicit FsRandomAccessFile(unique_ptr entity) : rafEntity(move(entity)) {} +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif //INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_FS_RANDOMACCESSFILE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h index 3f5b12a7f..cc0f26609 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h @@ -34,4 +34,4 @@ struct RandomAccessFileEntity { } // namespace ModuleFileIO } // namespace FileManagement } // namespace OHOS -#endif \ No newline at end of file +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_RANDOMACCESSFILE_RANDOMACCESSFILE_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.cpp b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.cpp new file mode 100644 index 000000000..eb3f82c0e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.cpp @@ -0,0 +1,104 @@ +/* + * 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 "reader_iterator_ani.h" + +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "reader_iterator_result_ani.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +ani_object ReaderIteratorAni::Wrap(ani_env *env, const FsReaderIterator *it) +{ + if (it == nullptr) { + HILOGE("FsReaderIterator pointer is null!"); + return nullptr; + } + + auto classDesc = FS::ReaderIteratorInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + + auto ctorDesc = FS::ReaderIteratorInner::ctorDesc.c_str(); + auto ctorSig = FS::ReaderIteratorInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + ani_long ptr = static_cast(reinterpret_cast(it)); + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, ptr)) { + HILOGE("New %s obj Failed!", classDesc); + return nullptr; + } + + return obj; +} + +FsReaderIterator *ReaderIteratorAni::Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap fsReaderIterator err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsReaderIterator *readeriterator = reinterpret_cast(ptrValue); + return readeriterator; +} + +ani_object ReaderIteratorAni::Next(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsReaderIterator = Unwrap(env, object); + if (fsReaderIterator == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + + auto ret = fsReaderIterator->Next(); + if (!ret.IsSuccess()) { + HILOGE("Cannot get readeriterator next!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + auto nextRet = ret.GetData().value(); + auto result = ReaderIteratorResultAni::Wrap(env, &nextRet); + if (result == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.h b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.h new file mode 100644 index 000000000..31d70abc2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_ani.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_ANI_H + +#include + +#include "fs_reader_iterator.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class ReaderIteratorAni final { +public: + static ani_object Wrap(ani_env *env, const FsReaderIterator *it); + static FsReaderIterator *Unwrap(ani_env *env, ani_object object); + static ani_object Next(ani_env *env, [[maybe_unused]] ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.cpp b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.cpp new file mode 100644 index 000000000..b8efe806e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.cpp @@ -0,0 +1,78 @@ +/* + * 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 "reader_iterator_result_ani.h" + +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +ani_object ReaderIteratorResultAni::Wrap(ani_env *env, const ReaderIteratorResult *result) +{ + if (result == nullptr) { + HILOGE("ReaderIteratorResult pointer is null!"); + return nullptr; + } + + auto classDesc = FS::ReaderIteratorResultInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + + auto ctorDesc = FS::ReaderIteratorResultInner::ctorDesc.c_str(); + auto ctorSig = FS::ReaderIteratorResultInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + ani_long ptr = static_cast(reinterpret_cast(result)); + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, ptr)) { + HILOGE("New %s obj Failed!", classDesc); + return nullptr; + } + + const auto &done = result->done; + if (ANI_OK != AniHelper::SetPropertyValue(env, cls, obj, "done", static_cast(done))) { + HILOGE("Set 'done' field value failed!"); + return nullptr; + } + + const auto &value = result->value; + if (ANI_OK != AniHelper::SetPropertyValue(env, cls, obj, "value", value)) { + HILOGE("Set 'value' field value failed!"); + return nullptr; + } + + return obj; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.h b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.h new file mode 100644 index 000000000..0f6837846 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/ani/reader_iterator_result_ani.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_RESULT_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_RESULT_ANI_H + +#include + +#include "fs_reader_iterator.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class ReaderIteratorResultAni final { +public: + static ani_object Wrap(ani_env *env, const ReaderIteratorResult *result); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_READER_ITERATOR_RESULT_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.cpp b/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.cpp new file mode 100644 index 000000000..80321d51f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.cpp @@ -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. + */ + +#include "fs_reader_iterator.h" + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "rust_file.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +FsResult FsReaderIterator::Constructor() +{ + auto entity = CreateUniquePtr(); + if (entity == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + FsReaderIterator *it = new FsReaderIterator(move(entity)); + + if (it == nullptr) { + HILOGE("Failed to create FsReaderIterator object on heap."); + return FsResult::Error(ENOMEM); + } + return FsResult::Success(move(it)); +} + +FsResult FsReaderIterator::Next() +{ + if (entity == nullptr) { + HILOGE("Failed to get reader iterator entity"); + return FsResult::Error(UNKNOWN_ERR); + } + + Str *str = NextLine(entity->iterator); + if (str == nullptr && entity->offset != 0) { + HILOGE("Failed to get next line, error:%{public}d", errno); + return FsResult::Error(errno); + } + + ReaderIteratorResult result; + bool done = entity->offset == 0; + result.done = done; + if (str != nullptr) { + std::string value(str->str, str->len); + result.value = value; + entity->offset -= static_cast(str->len); + } else { + result.value = ""; + } + StrFree(str); + + return FsResult::Success(move(result)); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.h b/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.h new file mode 100644 index 000000000..bc534da09 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/fs_reader_iterator.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_FS_READERITERATOR_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_FS_READERITERATOR_H + +#include "filemgmt_libfs.h" +#include "readeriterator_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +struct ReaderIteratorResult { + bool done; + std::string value; +}; + +class FsReaderIterator final { +public: + static FsResult Constructor(); + + ReaderIteratorEntity *GetReaderIteratorEntity() const + { + return entity.get(); + } + + FsResult Next(); + +private: + unique_ptr entity; + explicit FsReaderIterator(unique_ptr entity) : entity(move(entity)) {}; +}; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_FS_READERITERATOR_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.cpp b/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.cpp new file mode 100644 index 000000000..deb3052c5 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.cpp @@ -0,0 +1,66 @@ +/* + * 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 "lstat_ani.h" + +#include +#include + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "lstat_core.h" +#include "stat_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object LstatAni::LstatSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succPath, filePath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("The first argument requires filepath"); + ErrorHandler::Throw(env, EINVAL); + return {}; + } + + auto ret = LstatCore::DoLstat(filePath); + if (!ret.IsSuccess()) { + HILOGE("DoStat failed!"); + const FsError &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return {}; + } + + auto fsStat = ret.GetData().value(); + auto statObject = StatWrapper::Wrap(env, fsStat); + if (statObject == nullptr) { + delete fsStat; + fsStat = nullptr; + HILOGE("Wrap stat object failed!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return {}; + } + + return statObject; +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.h b/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.h new file mode 100644 index 000000000..140d92807 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stat/ani/lstat_ani.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSTAT_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSTAT_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class LstatAni final { +public: + static ani_object LstatSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSTAT_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stat/ani/stat_wrapper.cpp b/interfaces/kits/js/src/mod_fs/class_stat/ani/stat_wrapper.cpp index 73e0a235c..94aae30c1 100644 --- a/interfaces/kits/js/src/mod_fs/class_stat/ani/stat_wrapper.cpp +++ b/interfaces/kits/js/src/mod_fs/class_stat/ani/stat_wrapper.cpp @@ -185,15 +185,14 @@ static ani_status SetProperties(ani_env *env, const ani_class &cls, ani_object & ani_object StatWrapper::Wrap(ani_env *env, FsStat *fsStat) { - auto classDesc = FS::StatInner::classDesc.c_str(); - ani_object statObject = {}; - ani_class cls; - ani_status ret; - if (fsStat == nullptr) { HILOGE("FsStat pointer is null!"); return nullptr; } + auto classDesc = FS::StatInner::classDesc.c_str(); + ani_object statObject = {}; + ani_class cls; + ani_status ret; if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { HILOGE("Not found %{private}s, err: %{private}d", classDesc, ret); diff --git a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp new file mode 100644 index 000000000..a1d694187 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp @@ -0,0 +1,290 @@ +/* + * 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 "stream_ani.h" + +#include +#include + +#include "ani_helper.h" +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fs_stream.h" +#include "fs_utils.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static tuple> ToReadOptions(ani_env *env, ani_object obj) +{ + ReadOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + return { true, make_optional(move(options)) }; +} + +static tuple> ToWriteOptions(ani_env *env, ani_object obj) +{ + WriteOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset"); + if (!succOffset) { + HILOGE("Illegal option.offset parameter"); + return { false, nullopt }; + } + options.offset = offset; + + auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length"); + if (!succLength) { + HILOGE("Illegal option.length parameter"); + return { false, nullopt }; + } + options.length = length; + + auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj); + if (!succEncoding) { + HILOGE("Illegal option.encoding parameter"); + return { false, nullopt }; + } + options.encoding = encoding; + return { true, make_optional(move(options)) }; +} + +static std::tuple ParseStringBuffer(ani_env *env, const ani_object &buf) +{ + auto classDesc = BuiltInTypes::String::classDesc.c_str(); + ani_class cls; + env->FindClass(classDesc, &cls); + + ani_boolean isString; + env->Object_InstanceOf(buf, cls, &isString); + if (!isString) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, std::move(result) }; +} + +static std::tuple ParseArrayBuffer(ani_env *env, const ani_object &buf) +{ + auto classDesc = BuiltInTypes::ArrayBuffer::classDesc.c_str(); + ani_class cls; + env->FindClass(classDesc, &cls); + + ani_boolean isArrayBuffer; + env->Object_InstanceOf(buf, cls, &isArrayBuffer); + if (!isArrayBuffer) { + return { false, {} }; + } + auto result = static_cast(buf); + return { true, std::move(result) }; +} + +static FsStream *Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap fsFile err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsStream *stream = reinterpret_cast(ptrValue); + return stream; +} + +void StreamAni::Close(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStream = Unwrap(env, object); + if (fsStream == nullptr) { + HILOGE("Cannot unwrap fsStream!"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = fsStream->Close(); + if (!ret.IsSuccess()) { + HILOGE("Cannot close fsStream!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +void StreamAni::Flush(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto fsStream = Unwrap(env, object); + if (fsStream == nullptr) { + HILOGE("Cannot unwrap fsStream!"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = fsStream->Flush(); + if (!ret.IsSuccess()) { + HILOGE("Cannot flush fsStream!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +ani_double StreamAni::Write(ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options) +{ + auto fsStream = Unwrap(env, object); + if (fsStream == nullptr) { + HILOGE("Cannot unwrap fsStream!"); + return -1; + } + + auto [succOp, op] = ToWriteOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + return -1; + } + + auto [isString, stringBuffer] = ParseStringBuffer(env, buf); + if (isString) { + auto [succBuf, buffer] = TypeConverter::ToUTF8String(env, stringBuffer); + if (!succBuf) { + HILOGE("Failed to resolve stringBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = fsStream->Write(buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write string failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return ret.GetData().value(); + } + + auto [isArrayBuffer, arrayBuffer] = ParseArrayBuffer(env, buf); + if (isArrayBuffer) { + auto [succBuf, buffer] = TypeConverter::ToArrayBuffer(env, arrayBuffer); + if (!succBuf) { + HILOGE("Failed to resolve arrayBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto ret = fsStream->Write(buffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); + } + + HILOGE("Unsupported buffer type!"); + ErrorHandler::Throw(env, EINVAL); + return -1; +} + +ani_double StreamAni::Read(ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buffer, ani_object options) +{ + auto fsStream = Unwrap(env, object); + if (fsStream == nullptr) { + HILOGE("Cannot unwrap fsStream!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [succBuf, arrayBuffer] = TypeConverter::ToArrayBuffer(env, buffer); + if (!succBuf) { + HILOGE("Failed to resolve arrayBuffer!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [succOp, op] = ToReadOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto ret = fsStream->Read(arrayBuffer, op); + if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); +} + +ani_double StreamAni::Seek(ani_env *env, [[maybe_unused]] ani_object object, ani_double offset, ani_object whence) +{ + auto fsStream = Unwrap(env, object); + if (fsStream == nullptr) { + HILOGE("Cannot unwrap fsStream!"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto [succ, typeOpt] = TypeConverter::ToOptionalInt32(env, whence); + if (!succ) { + HILOGE("Invalied whence type"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + + auto ret = fsStream->Seek(static_cast(offset), typeOpt); + if (!ret.IsSuccess()) { + HILOGE("seek failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + return static_cast(ret.GetData().value()); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.h b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.h new file mode 100644 index 000000000..91fdb9852 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class StreamAni final { +public: + static void Close(ani_env *env, [[maybe_unused]] ani_object object); + static void Flush(ani_env *env, [[maybe_unused]] ani_object object); + static ani_double Write(ani_env *env, [[maybe_unused]] ani_object object, ani_object buf, ani_object options); + static ani_double Read( + ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buffer, ani_object options); + static ani_double Seek(ani_env *env, [[maybe_unused]] ani_object object, ani_double offset, ani_object whence); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.cpp b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.cpp new file mode 100644 index 000000000..c882f9dda --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.cpp @@ -0,0 +1,78 @@ +/* + * 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 "stream_wrapper.h" + +#include + +#include "ani_helper.h" +#include "ani_signature.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +FsStream *StreamWrapper::Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap fsFile err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsStream *stream = reinterpret_cast(ptrValue); + return stream; +} + +ani_object StreamWrapper::Wrap(ani_env *env, const FsStream *stream) +{ + if (stream == nullptr) { + HILOGE("FsStream pointer is null!"); + return nullptr; + } + auto classDesc = FS::StreamInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + auto ctorDesc = FS::StreamInner::ctorDesc.c_str(); + auto ctorSig = FS::StreamInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + ani_long ptr = static_cast(reinterpret_cast(stream)); + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, ptr)) { + HILOGE("New %s obj Failed!", classDesc); + return nullptr; + } + + return obj; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.h b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.h new file mode 100644 index 000000000..a99f6d4ad --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_wrapper.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_WRAPPER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_WRAPPER_H + +#include +#include "fs_stream.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class StreamWrapper final { +public: + static FsStream *Unwrap(ani_env *env, ani_object object); + static ani_object Wrap(ani_env *env, const FsStream *stream); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_STREAM_WRAPPER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.cpp b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.cpp new file mode 100644 index 000000000..00a493ed2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.cpp @@ -0,0 +1,292 @@ +/* + * 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 "fs_stream.h" + +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +std::shared_ptr FsStream::GetFilePtr() +{ + std::lock_guard lock(mtx); + if (!streamEntity) { + return nullptr; + } + return streamEntity->fp; +} + +static tuple ValidWriteArg(const size_t bufLen, const optional &options) +{ + size_t retLen = 0; + int64_t offset = -1; + bool succ = false; + + if (bufLen > UINT_MAX) { + HILOGE("The Size of buffer is too large"); + return { false, 0, offset }; + } + + optional lengthOp = nullopt; + optional offsetOp = nullopt; + optional encodingOp = nullopt; + if (options.has_value()) { + WriteOptions op = options.value(); + lengthOp = op.length; + offsetOp = op.offset; + encodingOp = op.encoding; + } + + tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp); + if (!succ) { + HILOGE("Failed to get actual length"); + return { false, 0, offset }; + } + + if (offsetOp.has_value()) { + offset = offsetOp.value(); + if (offset < 0) { + HILOGE("option.offset shall be positive number"); + return { false, 0, offset }; + } + } + + if (encodingOp.has_value()) { + if (encodingOp.value() != "utf-8") { + HILOGE("option.encoding shall be utf-8"); + return { false, 0, offset }; + } + } + return { true, retLen, offset }; +} + +static tuple ValidReadArg(const size_t bufLen, const optional &options) +{ + size_t retLen = 0; + int64_t offset = -1; + bool succ = false; + + if (bufLen > UINT_MAX) { + HILOGE("The Size of buffer is too large"); + return { false, 0, offset }; + } + + optional lengthOp = nullopt; + optional offsetOp = nullopt; + if (options.has_value()) { + ReadOptions op = options.value(); + lengthOp = op.length; + offsetOp = op.offset; + } + + tie(succ, retLen) = FsUtils::GetActualLen(bufLen, 0, lengthOp); + if (!succ) { + HILOGE("Failed to get actual length"); + return { false, 0, offset }; + } + + if (offsetOp.has_value()) { + offset = offsetOp.value(); + if (offset < 0) { + HILOGE("option.offset shall be positive number"); + return { false, 0, offset }; + } + } + return { true, retLen, offset }; +} + +FsResult FsStream::Write(const ArrayBuffer &buf, const optional &options) +{ + auto fp = GetFilePtr(); + if (!fp) { + HILOGE("Failed to get file ptr"); + return FsResult::Error(EIO); + } + + auto [succ, retLen, offset] = ValidWriteArg(buf.length, options); + if (!succ) { + HILOGE("Invalid options"); + return FsResult::Error(EINVAL); + } + + if (offset >= 0) { + int ret = fseek(fp.get(), static_cast(offset), SEEK_SET); + if (ret < 0) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return FsResult::Error(errno); + } + } + + size_t writeLen = fwrite(buf.buf, 1, retLen, fp.get()); + if ((writeLen == 0) && (writeLen != retLen)) { + HILOGE("Failed to fwrite stream"); + return FsResult::Error(EIO); + } + return FsResult::Success(writeLen); +} + +FsResult FsStream::Write(const string &buf, const optional &options) +{ + auto fp = GetFilePtr(); + if (!fp) { + HILOGE("Failed to get file ptr"); + return FsResult::Error(EIO); + } + + size_t bufLen = static_cast(buf.length()); + + auto [succ, retLen, offset] = ValidWriteArg(bufLen, options); + if (!succ) { + HILOGE("Invalid options"); + return FsResult::Error(EINVAL); + } + + if (offset >= 0) { + int ret = fseek(fp.get(), static_cast(offset), SEEK_SET); + if (ret < 0) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return FsResult::Error(errno); + } + } + + size_t writeLen = fwrite(buf.c_str(), 1, retLen, fp.get()); + if ((writeLen == 0) && (writeLen != retLen)) { + HILOGE("Failed to fwrite stream"); + return FsResult::Error(EIO); + } + return FsResult::Success(writeLen); +} + +FsResult FsStream::Read(ArrayBuffer &buf, const optional &options) +{ + auto fp = GetFilePtr(); + if (!fp) { + HILOGE("Failed to get file ptr"); + return FsResult::Error(EIO); + } + + auto [succ, retLen, offset] = ValidReadArg(buf.length, options); + if (!succ) { + HILOGE("Invalid options"); + return FsResult::Error(EINVAL); + } + + if (offset >= 0) { + int ret = fseek(fp.get(), static_cast(offset), SEEK_SET); + if (ret < 0) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return FsResult::Error(errno); + } + } + + size_t actLen = fread(buf.buf, 1, retLen, fp.get()); + if ((actLen != static_cast(retLen) && !feof(fp.get())) || ferror(fp.get())) { + HILOGE("Invalid buffer size or pointer, actlen: %{public}zu", actLen); + return FsResult::Error(EIO); + } + + return FsResult::Success(actLen); +} + +FsResult FsStream::Flush() +{ + auto fp = GetFilePtr(); + if (fp == nullptr) { + HILOGE("Failed to get entity of Stream"); + return FsResult::Error(EIO); + } + + int ret = fflush(fp.get()); + if (ret < 0) { + HILOGE("Failed to fflush file in the stream, ret: %{public}d", ret); + return FsResult::Error(errno); + } + + return FsResult::Success(); +} + +FsResult FsStream::Close() +{ + if (!streamEntity) { + HILOGE("Failed to get entity of Stream, may closed twice"); + return FsResult::Error(EIO); + } + streamEntity = nullptr; + return FsResult::Success(); +} + +FsResult FsStream::Seek(const int64_t &offset, const optional &typeOpt) +{ + int whence = SEEK_SET; + + auto fp = GetFilePtr(); + if (fp == nullptr) { + HILOGE("Failed to get file ptr"); + return FsResult::Error(ENOENT); + } + + if (typeOpt.has_value()) { + int pos = typeOpt.value(); + if (pos < SEEK_SET || pos > SEEK_END) { + HILOGE("Invalid whence"); + return FsResult::Error(EINVAL); + } + whence = pos; + } + + if (offset >= 0) { + int ret = fseek(fp.get(), static_cast(offset), whence); + if (ret < 0) { + HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); + return FsResult::Error(errno); + } + } + + int64_t res = ftell(fp.get()); + if (res < 0) { + HILOGE("Failed to tell, error:%{public}d", errno); + return FsResult::Error(errno); + } + + return FsResult::Success(res); +} + +FsResult FsStream::Constructor() +{ + auto rafEntity = CreateUniquePtr(); + if (rafEntity == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + FsStream *fsStreamPtr = new FsStream(move(rafEntity)); + + if (fsStreamPtr == nullptr) { + HILOGE("Failed to create FsStream object on heap."); + return FsResult::Error(ENOMEM); + } + + return FsResult::Success(move(fsStreamPtr)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h new file mode 100644 index 000000000..a6b9661e0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/fs_stream.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_FS_STREAM_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_FS_STREAM_H + +#include "stream_entity.h" + +#include +#include +#include + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct WriteOptions { + optional length = nullopt; + optional offset = nullopt; + optional encoding = nullopt; +}; + +struct ReadOptions { + optional length = nullopt; + optional offset = nullopt; +}; + +class FsStream final { +public: + StreamEntity *GetStreamEntity() const + { + return streamEntity.get(); + } + + FsStream(const FsStream &) = delete; + FsStream &operator=(const FsStream &) = delete; + + std::shared_ptr GetFilePtr(); + FsResult Write(const ArrayBuffer &buf, const optional &options = nullopt); + FsResult Write(const string &buf, const optional &options = nullopt); + FsResult Read(ArrayBuffer &buf, const optional &options = nullopt); + FsResult Close(); + FsResult Flush(); + FsResult Seek(const int64_t &offset, const optional &typeOpt = nullopt); + + ~FsStream() = default; + static FsResult Constructor(); + +private: + std::mutex mtx; + unique_ptr streamEntity; + explicit FsStream(unique_ptr entity) : streamEntity(move(entity)) {} +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_FS_STREAM_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.cpp b/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.cpp new file mode 100644 index 000000000..e28dfa77c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.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 "stream_instantiator.h" + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "stream_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult StreamInstantiator::InstantiateStream(FILE *file) +{ + FsResult result = FsStream::Constructor(); + if (!result.IsSuccess()) { + HILOGE("Failed to instantiate class"); + int ret = fclose(file); + if (ret < 0) { + HILOGE("Failed to close file"); + } + return FsResult::Error(EIO); + } + + const FsStream *objStream = result.GetData().value(); + if (!objStream) { + HILOGE("Failed to get FsStream"); + int ret = fclose(file); + if (ret < 0) { + HILOGE("Failed to close file"); + } + return FsResult::Error(EIO); + } + + auto *streamEntity = objStream->GetStreamEntity(); + if (!streamEntity) { + HILOGE("Failed to get streamEntity"); + int ret = fclose(file); + if (ret < 0) { + HILOGE("Failed to close file"); + } + delete objStream; + objStream = nullptr; + return FsResult::Error(EIO); + } + + auto fp = std::shared_ptr(file, fclose); + if (fp == nullptr) { + HILOGE("Failed to request heap memory."); + int ret = fclose(file); + if (ret < 0) { + HILOGE("Failed to close file"); + } + delete objStream; + objStream = nullptr; + return FsResult::Error(ENOMEM); + } + + streamEntity->fp.swap(fp); + return result; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.h b/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.h new file mode 100644 index 000000000..bf98d7b53 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_instantiator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_INSTANTIATOR_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_INSTANTIATOR_H + +#include "filemgmt_libfs.h" +#include "fs_stream.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +class StreamInstantiator { +public: + static FsResult InstantiateStream(FILE *file); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_STREAM_INSTANTIATOR_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.cpp b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.cpp new file mode 100644 index 000000000..2b1229a69 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.cpp @@ -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. + */ + +#include "task_signal_ani.h" + +#include "ani_helper.h" +#include "copy_core.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fs_task_signal.h" +#include "task_signal_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +void TaskSignalAni::Cancel(ani_env *env, [[maybe_unused]] ani_object object) +{ + FsTaskSignal *copySignal = TaskSignalWrapper::Unwrap(env, object); + if (copySignal == nullptr) { + HILOGE("Cannot unwrap copySignal!"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = copySignal->Cancel(); + if (!ret.IsSuccess()) { + HILOGE("Cannot Cancel!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +void TaskSignalAni::OnCancel(ani_env *env, [[maybe_unused]] ani_object object) +{ + FsTaskSignal *copySignal = TaskSignalWrapper::Unwrap(env, object); + if (copySignal == nullptr) { + HILOGE("Cannot unwrap copySignal!"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = copySignal->OnCancel(); + if (!ret.IsSuccess()) { + HILOGE("Cannot Cancel!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.h b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.h new file mode 100644 index 000000000..d27e52538 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class TaskSignalAni final { +public: + static void Cancel(ani_env *env, [[maybe_unused]] ani_object object); + static void OnCancel(ani_env *env, [[maybe_unused]] ani_object object); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.cpp b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.cpp new file mode 100644 index 000000000..8f533889c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.cpp @@ -0,0 +1,63 @@ +/* + * 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 "task_signal_listener_ani.h" + +#include +#include "ani_helper.h" +#include "ani_signature.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +void TaskSignalListenerAni::OnCancel() +{ + auto filepath = taskSignal->filePath_; + auto task = [this, filepath]() { SendCancelEvent(filepath); }; + AniHelper::SendEventToMainThread(task); +} + +void TaskSignalListenerAni::SendCancelEvent(const string &filepath) const +{ + if (vm == nullptr) { + HILOGE("Cannot send cancel event because the vm is null."); + return; + } + if (signalObj == nullptr) { + HILOGE("Cannot send cancel event because the signalObj is null."); + return; + } + ani_env *env = AniHelper::GetThreadEnv(vm); + if (env == nullptr) { + HILOGE("Cannot send cancel event because the env is null."); + return; + } + auto [succ, aniPath] = TypeConverter::ToAniString(env, filepath); + if (!succ) { + HILOGE("Cannot convert filepath to ani string!"); + return; + } + auto ret = env->Object_CallMethodByName_Void(signalObj, "onCancelCallback", nullptr, aniPath); + if (ret != ANI_OK) { + HILOGE("Call onCancelCallback failed, err: %{public}d", ret); + return; + } +} + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.h b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.h new file mode 100644 index 000000000..ae02a941e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_listener_ani.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_LISTENER_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_LISTENER_ANI_H + +#include +#include "task_signal_listener.h" +#include "task_signal.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace DistributedFS::ModuleTaskSignal; + +class TaskSignalListenerAni : public TaskSignalListener { +public: + TaskSignalListenerAni(ani_vm *vm, const ani_object &signalObj, std::shared_ptr taskSignal) + : vm(vm), signalObj(signalObj), taskSignal(taskSignal) {} + void OnCancel() override; + +public: + TaskSignalListenerAni() = default; + ~TaskSignalListenerAni() = default; + +private: + void SendCancelEvent(const std::string &filepath) const; + +private: + ani_vm *vm; + ani_object signalObj; + std::shared_ptr taskSignal; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_LISTENER_ANI_H diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.cpp b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.cpp new file mode 100644 index 000000000..79be64231 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.cpp @@ -0,0 +1,71 @@ +/* + * 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 "task_signal_wrapper.h" + +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fs_task_signal.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +FsTaskSignal *TaskSignalWrapper::Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto status = env->Object_GetFieldByName_Long(object, "nativeTaskSignal", &nativePtr); + if (status != ANI_OK) { + HILOGE("Unwrap taskSignal obj failed! status: %{public}d", status); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsTaskSignal *copySignal = reinterpret_cast(ptrValue); + return copySignal; +} + +bool TaskSignalWrapper::Wrap(ani_env *env, ani_object object, const FsTaskSignal *signal) +{ + if (object == nullptr) { + HILOGE("TaskSignal obj is null!"); + return false; + } + + if (signal == nullptr) { + HILOGE("FsTaskSignal pointer is null!"); + return false; + } + + ani_long ptr = static_cast(reinterpret_cast(signal)); + + auto status = env->Object_SetFieldByName_Long(object, "nativeTaskSignal", ptr); + if (status != ANI_OK) { + HILOGE("Wrap taskSignal obj failed! status: %{public}d", status); + return false; + } + + return true; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.h b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.h new file mode 100644 index 000000000..4fe9fb143 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/ani/task_signal_wrapper.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_WRAPPER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_WRAPPER_H + +#include +#include "fs_task_signal.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class TaskSignalWrapper final { +public: + static FsTaskSignal *Unwrap(ani_env *env, ani_object object); + static bool Wrap(ani_env *env, ani_object object, const FsTaskSignal *signal); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_ANI_TASK_SIGNAL_WRAPPER_H diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.cpp b/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.cpp new file mode 100644 index 000000000..d9b4b6ffe --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.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 "fs_task_signal.h" + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult> FsTaskSignal::Constructor( + shared_ptr taskSignal, shared_ptr signalListener) +{ + if (!taskSignal) { + HILOGE("Invalid taskSignal"); + return FsResult>::Error(EINVAL); + } + if (!signalListener) { + HILOGE("Invalid signalListener"); + return FsResult>::Error(EINVAL); + } + auto copySignal = CreateSharedPtr(); + if (copySignal == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult>::Error(ENOMEM); + } + copySignal->taskSignal_ = move(taskSignal); + copySignal->signalListener_ = move(signalListener); + return FsResult>::Success(copySignal); +} + +FsResult FsTaskSignal::Cancel() +{ + if (taskSignal_ == nullptr) { + HILOGE("Failed to get taskSignal"); + return FsResult::Error(EINVAL); + } + auto ret = taskSignal_->Cancel(); + if (ret != ERRNO_NOERR) { + HILOGE("Failed to cancel the task."); + return FsResult::Error(CANCEL_ERR); + } + return FsResult::Success(); +} + +FsResult FsTaskSignal::OnCancel() +{ + if (taskSignal_ == nullptr) { + HILOGE("Failed to get taskSignal"); + return FsResult::Error(EINVAL); + } + taskSignal_->SetTaskSignalListener(signalListener_.get()); + return FsResult::Success(); +} + +shared_ptr FsTaskSignal::GetTaskSignal() const +{ + return taskSignal_; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.h b/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.h new file mode 100644 index 000000000..33161108c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/fs_task_signal.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_FS_TASK_SIGNAL_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_FS_TASK_SIGNAL_H + +#include "filemgmt_libfs.h" +#include "task_signal.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace DistributedFS::ModuleTaskSignal; + +class FsTaskSignal { +public: + static FsResult> Constructor( + shared_ptr taskSignal, shared_ptr signalListener); + FsResult Cancel(); + FsResult OnCancel(); + shared_ptr GetTaskSignal() const; + +public: + FsTaskSignal() = default; + ~FsTaskSignal() = default; + FsTaskSignal(const FsTaskSignal &other) = delete; + FsTaskSignal &operator=(const FsTaskSignal &other) = delete; + +private: + shared_ptr taskSignal_ = nullptr; + shared_ptr signalListener_ = nullptr; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_TASKSIGNAL_FS_TASK_SIGNAL_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.cpp new file mode 100644 index 000000000..39d11f496 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.cpp @@ -0,0 +1,68 @@ +/* + * 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 "fs_watcher_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fs_watcher.h" +#include "fs_watcher_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace std; + +void FsWatcherAni::Start(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto watcher = FsWatcherWrapper::Unwrap(env, object); + if (watcher == nullptr) { + HILOGE("Cannot unwrap watcher!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + auto ret = watcher->Start(); + if (!ret.IsSuccess()) { + HILOGE("Cannot start watcher!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +void FsWatcherAni::Stop(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto watcher = FsWatcherWrapper::Unwrap(env, object); + if (watcher == nullptr) { + HILOGE("Cannot unwrap watcher!"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + auto ret = watcher->Stop(); + if (!ret.IsSuccess()) { + HILOGE("Cannot stop watcher!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.h b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.h new file mode 100644 index 000000000..e6badfc7b --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class FsWatcherAni final { +public: + static void Start(ani_env *env, [[maybe_unused]] ani_object object); + static void Stop(ani_env *env, [[maybe_unused]] ani_object object); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.cpp new file mode 100644 index 000000000..79d6fb1dc --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.cpp @@ -0,0 +1,73 @@ +/* + * 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 "fs_watcher_wrapper.h" + +#include "ani_signature.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +FsWatcher *FsWatcherWrapper::Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap fsWatcher err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + FsWatcher *watcher = reinterpret_cast(ptrValue); + return watcher; +} + +ani_object FsWatcherWrapper::Wrap(ani_env *env, const FsWatcher *watcher) +{ + if (watcher == nullptr) { + HILOGE("FsWatcher pointer is null!"); + return nullptr; + } + auto classDesc = FS::WatcherInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + auto ctorDesc = FS::WatcherInner::ctorDesc.c_str(); + auto ctorSig = FS::WatcherInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + ani_long ptr = static_cast(reinterpret_cast(watcher)); + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, ptr)) { + HILOGE("New %s obj Failed!", classDesc); + return nullptr; + } + return obj; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.h b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.h new file mode 100644 index 000000000..15d24f94e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/fs_watcher_wrapper.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_WRAPPER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_WRAPPER_H + +#include +#include "fs_watcher.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class FsWatcherWrapper final { +public: + static FsWatcher *Unwrap(ani_env *env, ani_object object); + static ani_object Wrap(ani_env *env, const FsWatcher *watcher); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_FS_WATCHER_WRAPPER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp new file mode 100644 index 000000000..36ac7517d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp @@ -0,0 +1,114 @@ +/* + * 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 "watch_event_listener.h" + +#include +#include "ani_helper.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "watch_event_wrapper.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace std; + +bool WatchEventListener::IsStrictEquals(const shared_ptr &other) const +{ + if (other->GetClassName() != className_) { + return false; + } + + const auto otherListener = static_pointer_cast(other); + if (!otherListener) { + HILOGE("Cannot convert IWatcherCallback to WatchEventListener"); + return false; + } + + ani_env *env = AniHelper::GetThreadEnv(vm); + if (!env) { + HILOGE("Current object's env is null"); + return false; + } + + ani_boolean isSame = false; + ani_status status = env->Reference_StrictEquals(callback, otherListener->callback, &isSame); + if (status != ANI_OK) { + HILOGE("Compare ref for strict equality failed. status = %{public}d", static_cast(status)); + return false; + } + return isSame; +} + +void WatchEventListener::InvokeCallback(const string &fileName, uint32_t event, uint32_t cookie) const +{ + auto watchEvent = CreateSharedPtr(); + if (watchEvent == nullptr) { + HILOGE("Failed to request heap memory."); + return; + } + + watchEvent->fileName = fileName; + watchEvent->event = event; + watchEvent->cookie = cookie; + auto task = [this, watchEvent]() { SendWatchEvent(*watchEvent); }; + AniHelper::SendEventToMainThread(task); +} + +inline static const int32_t ANI_SCOPE_SIZE = 16; + +void WatchEventListener::SendWatchEvent(const WatchEvent &watchEvent) const +{ + if (vm == nullptr) { + HILOGE("Cannot send WatchEvent because the vm is null."); + return; + } + if (callback == nullptr) { + HILOGE("Cannot send WatchEvent because the callback is null."); + return; + } + ani_size scopeSize = ANI_SCOPE_SIZE; + ani_env *env = AniHelper::GetThreadEnv(vm); + if (env == nullptr) { + HILOGE("Cannot send WatchEvent because the env is null."); + return; + } + ani_status status = env->CreateLocalScope(scopeSize); + if (status != ANI_OK) { + HILOGE("Failed to creat local scope, status: %{public}d", static_cast(status)); + return; + } + auto evtObj = WatchEventWrapper::Wrap(env, watchEvent); + if (evtObj == nullptr) { + HILOGE("Create WatchEvent obj failed!"); + return; + } + vector args = { static_cast(evtObj) }; + auto argc = args.size(); + ani_ref result; + auto cbObj = static_cast(callback); + status = env->FunctionalObject_Call(cbObj, argc, args.data(), &result); + if (status != ANI_OK) { + HILOGE("Failed to call FunctionalObject_Call, status: %{public}d", static_cast(status)); + // continue execution and not exit. + } + status = env->DestroyLocalScope(); + if (status != ANI_OK) { + HILOGE("Failed to destroy local scope, status: %{public}d", static_cast(status)); + return; + } +} + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.h b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.h new file mode 100644 index 000000000..919739228 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_LISTENER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_LISTENER_H + +#include + +#include + +#include "fs_watch_entity.h" +#include "i_watcher_callback.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { + +class WatchEventListener final : public IWatcherCallback { +public: + WatchEventListener(ani_vm *vm, const ani_ref &callback) : vm(vm), callback(callback) {} + bool IsStrictEquals(const std::shared_ptr &other) const override; + void InvokeCallback(const std::string &fileName, uint32_t event, uint32_t cookie) const override; + + std::string GetClassName() const override + { + return className_; + } + +private: + inline static const std::string className_ = "WatchEventListener"; + void SendWatchEvent(const WatchEvent &watchEvent) const; + + ani_vm *vm; + ani_ref callback; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_LISTENER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp new file mode 100644 index 000000000..1712f7f1f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.cpp @@ -0,0 +1,66 @@ +/* + * 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 "watch_event_wrapper.h" + +#include "ani_signature.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +ani_object WatchEventWrapper::Wrap(ani_env *env, const WatchEvent &evt) +{ + auto classDesc = FS::WatchEventInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + auto ctorDesc = FS::WatchEventInner::ctorDesc.c_str(); + auto ctorSig = FS::WatchEventInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + auto [succ, fileName] = TypeConverter::ToAniString(env, evt.fileName); + if (!succ) { + HILOGE("Convert fileName to ani string failed!"); + return nullptr; + } + + auto event = static_cast(evt.event); + auto cookie = static_cast(evt.cookie); + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, fileName, event, cookie)) { + HILOGE("Create %s obj failed!", classDesc); + return nullptr; + } + return obj; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.h b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.h new file mode 100644 index 000000000..8e2ca980c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_wrapper.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_WRAPPER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_WRAPPER_H + +#include +#include +#include "fs_watch_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class WatchEventWrapper final { +public: + static ani_object Wrap(ani_env *env, const WatchEvent &evt); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_ANI_WATCH_EVENT_WRAPPER_H \ No newline at end of file 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 new file mode 100644 index 000000000..9f77d49df --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp @@ -0,0 +1,348 @@ +/* + * 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 "fs_file_watcher.h" + +#include +#include +#include +#include +#include + +#include + +#include "filemgmt_libhilog.h" +#include "uv.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +int32_t FsFileWatcher::GetNotifyId() +{ + return notifyFd_; +} + +bool FsFileWatcher::InitNotify() +{ + notifyFd_ = inotify_init(); + if (notifyFd_ < 0) { + HILOGE("Failed to init notify errCode:%{public}d", errno); + return false; + } + eventFd_ = eventfd(0, EFD_CLOEXEC); + if (eventFd_ < 0) { + HILOGE("Failed to init eventfd errCode:%{public}d", errno); + return false; + } + return true; +} + +int32_t FsFileWatcher::StartNotify(shared_ptr info) +{ + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; + } + + if (notifyFd_ < 0) { + HILOGE("Failed to start notify notifyFd_:%{public}d", notifyFd_); + return EIO; + } + + auto [isWatched, wd] = dataCache_.FindWatchedWd(info->fileName, info->events); + if (isWatched && wd > 0) { + info->wd = wd; + return ERRNO_NOERR; + } + + uint32_t watchEvents = 0; + if (wd != -1) { + watchEvents = dataCache_.GetFileEvents(info->fileName) | info->events; + } else { + watchEvents = info->events; + } + + int32_t newWd = inotify_add_watch(notifyFd_, info->fileName.c_str(), watchEvents); + if (newWd < 0) { + HILOGE("Failed to start notify errCode:%{public}d", errno); + return errno; + } + + info->wd = newWd; + dataCache_.UpdateWatchedEvents(info->fileName, newWd, watchEvents); + return ERRNO_NOERR; +} + +int32_t FsFileWatcher::NotifyToWatchNewEvents(const string &fileName, int32_t wd, uint32_t watchEvents) +{ + int32_t newWd = inotify_add_watch(notifyFd_, fileName.c_str(), watchEvents); + if (newWd < 0) { + HILOGE("Failed to start new notify errCode:%{public}d", errno); + return errno; + } + + if (newWd != wd) { + HILOGE("New notify wd is error"); + return EIO; + } + + dataCache_.UpdateWatchedEvents(fileName, wd, watchEvents); + return ERRNO_NOERR; +} + +int32_t FsFileWatcher::CloseNotifyFd() +{ + int32_t closeRet = ERRNO_NOERR; + + if (!dataCache_.HasWatcherInfo()) { + run_ = false; + closeRet = close(notifyFd_); + if (closeRet != 0) { + HILOGE("Failed to stop notify close fd errCode:%{public}d", errno); + } + notifyFd_ = -1; + + closeRet = close(eventFd_); + if (closeRet != 0) { + HILOGE("Failed to close eventfd errCode:%{public}d", errno); + } + eventFd_ = -1; + DestroyTaskThead(); + } + + closed_ = false; + return closeRet; +} + +int32_t FsFileWatcher::CloseNotifyFdLocked() +{ + { + lock_guard lock(readMutex_); + closed_ = true; + if (reading_) { + HILOGE("close while reading"); + return ERRNO_NOERR; + } + } + return CloseNotifyFd(); +} + +int32_t FsFileWatcher::StopNotify(shared_ptr info) +{ + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; + } + + if (notifyFd_ < 0) { + HILOGE("Failed to stop notify notifyFd_:%{public}d", notifyFd_); + return EIO; + } + + 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); + } + HILOGE("The Watched file does not exist, and the remaining monitored events will be invalid."); + 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_); + if (!(closed_ && reading_)) { + oldWd = inotify_rm_watch(notifyFd_, info->wd); + } else { + HILOGE("rm watch fail"); + } + } + + if (oldWd == -1) { + 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); + CloseNotifyFdLocked(); + return rmErr; + } + } + + dataCache_.RemoveFileWatcher(info->fileName); + return CloseNotifyFdLocked(); +} + +void FsFileWatcher::ReadNotifyEvent() +{ + int32_t len = 0; + int32_t index = 0; + char buf[BUF_SIZE] = { 0 }; + struct inotify_event *event = nullptr; + + do { + len = read(notifyFd_, &buf, sizeof(buf)); + if (len < 0 && errno != EINTR) { + HILOGE("Read notify event failed! ret: %d", errno); + break; + } + } while (len < 0); + + while (index < len) { + event = reinterpret_cast(buf + index); + NotifyEvent(event); + index += sizeof(struct inotify_event) + static_cast(event->len); + } +} + +void FsFileWatcher::ReadNotifyEventLocked() +{ + { + lock_guard lock(readMutex_); + if (closed_) { + HILOGE("read after close"); + return; + } + reading_ = true; + } + + ReadNotifyEvent(); + + { + lock_guard lock(readMutex_); + reading_ = false; + if (closed_) { + HILOGE("close after read"); + CloseNotifyFd(); + return; + } + } +} + +void FsFileWatcher::AsyncGetNotifyEvent() +{ + lock_guard lock(taskMutex_); + if (!taskRunning_) { + taskRunning_ = true; + taskThead_ = thread(&FsFileWatcher::GetNotifyEvent, this); + } +} + +void FsFileWatcher::GetNotifyEvent() +{ + if (run_) { + return; + } + + run_ = true; + nfds_t nfds = 2; + struct pollfd fds[2] = { { -1 } }; + fds[0].fd = eventFd_; + fds[0].events = POLLIN; + fds[1].fd = notifyFd_; + fds[1].events = POLLIN; + int32_t ret = 0; + + while (run_) { + ret = poll(fds, nfds, pollTimeoutMs); + if (ret > 0) { + if (static_cast(fds[0].revents) & POLLNVAL) { + run_ = false; + break; + } + if (static_cast(fds[0].revents) & POLLIN) { + run_ = false; + break; + } + if (static_cast(fds[1].revents) & POLLIN) { + ReadNotifyEventLocked(); + } + } else if (ret < 0 && errno != EINTR) { + HILOGE("Failed to poll NotifyFd, errno=%{public}d", errno); + break; + } + // Ignore cases where poll returns 0 (timeout) or EINTR (interrupted system call) + } +} + +bool FsFileWatcher::AddWatcherInfo(shared_ptr info) +{ + if (!info) { + HILOGE("Invalid param: info"); + return false; + } + return dataCache_.AddWatcherInfo(info); +} + +uint32_t FsFileWatcher::RemoveWatcherInfo(shared_ptr info) +{ + if (!info) { + HILOGE("Invalid param: info"); + return EINVAL; + } + return dataCache_.RemoveWatcherInfo(info); +} + +void FsFileWatcher::NotifyEvent(const struct inotify_event *event) +{ + if (!event) { + HILOGE("Invalid inotify event"); + return; + } + + auto [matched, fileName, watcherInfos] = dataCache_.FindWatcherInfos(event->wd, event->mask); + if (!matched) { + HILOGE("Cannot find matched watcherInfos"); + return; + } + + for (const auto &info : watcherInfos) { + if (event->len > 0) { + fileName += "/" + string(event->name); + } + info->TriggerCallback(fileName, event->mask & IN_ALL_EVENTS, event->cookie); + } +} + +bool FsFileWatcher::CheckEventValid(uint32_t event) +{ + if ((event & IN_ALL_EVENTS) == event) { + return true; + } else { + HILOGE("Param event:%{public}x is not valid", event); + return false; + } +} + +void FsFileWatcher::DestroyTaskThead() +{ + if (taskThead_.joinable()) { + if (taskThead_.get_id() != std::this_thread::get_id()) { + taskThead_.join(); + } else { + taskThead_.detach(); + } + } + + { + lock_guard lock(taskMutex_); + if (taskRunning_) { + taskRunning_ = false; + run_ = false; + } + } + dataCache_.ClearCache(); +} +} // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h new file mode 100644 index 000000000..57b83d331 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h @@ -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. + */ +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_FILE_WATCHER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_FILE_WATCHER_H + +#include +#include +#include + +#include + +#include "filemgmt_libfs.h" +#include "fs_watch_entity.h" +#include "singleton.h" +#include "watcher_data_cache.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +constexpr int32_t BUF_SIZE = 1024; + +class FsFileWatcher : public Singleton { +public: + int32_t GetNotifyId(); + bool InitNotify(); + 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); + +public: + FsFileWatcher() = default; + ~FsFileWatcher() = default; + FsFileWatcher(const FsFileWatcher &) = delete; + FsFileWatcher &operator=(const FsFileWatcher &) = delete; + +private: + uint32_t RemoveWatcherInfo(shared_ptr info); + void NotifyEvent(const struct inotify_event *event); + int32_t CloseNotifyFd(); + int32_t CloseNotifyFdLocked(); + int32_t NotifyToWatchNewEvents(const string &fileName, int32_t wd, uint32_t watchEvents); + void ReadNotifyEvent(); + void ReadNotifyEventLocked(); + void DestroyTaskThead(); + +private: + static constexpr int32_t pollTimeoutMs = 500; + + mutex taskMutex_; + mutex readMutex_; + + atomic taskRunning_ = false; + thread taskThead_; + + bool run_ = false; + bool reading_ = false; + bool closed_ = false; + int32_t notifyFd_ = -1; + int32_t eventFd_ = -1; + WatcherDataCache dataCache_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_FILE_WATCHER_H 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 new file mode 100644 index 000000000..88fe92b18 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watch_entity.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCH_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCH_ENTITY_H + +#include +#include +#include +#include "i_watcher_callback.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +struct WatchEvent { + std::string fileName = ""; + uint32_t event = 0; + uint32_t cookie = 0; +}; + +struct WatcherInfo { + std::string fileName = ""; + uint32_t events = 0; + int32_t wd = -1; + std::shared_ptr callback; + + explicit WatcherInfo(std::shared_ptr callback) : callback(std::move(callback)) {} + + void TriggerCallback(const std::string &fileName, uint32_t event, uint32_t cookie) const + { + callback->InvokeCallback(fileName, event, cookie); + } +}; + +struct FsWatchEntity { + std::shared_ptr data_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCH_ENTITY_H 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 new file mode 100644 index 000000000..6be590065 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.cpp @@ -0,0 +1,78 @@ +/* + * 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 "fs_watcher.h" + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" +#include "fs_watch_entity.h" +#include "securec.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +FsResult FsWatcher::Constructor() +{ + auto watchEntity = CreateUniquePtr(); + if (watchEntity == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + FsWatcher *watcherPtr = new FsWatcher(move(watchEntity)); + + if (watcherPtr == nullptr) { + HILOGE("Failed to create FsWatcher object on heap."); + return FsResult::Error(ENOMEM); + } + + return FsResult::Success(move(watcherPtr)); +} + +FsResult FsWatcher::Stop() +{ + if (!watchEntity) { + HILOGE("Failed to get watchEntity when stop."); + return FsResult::Error(EINVAL); + } + int ret = FsFileWatcher::GetInstance().StopNotify(watchEntity->data_); + if (ret != ERRNO_NOERR) { + HILOGE("Failed to stopNotify errno:%{public}d", errno); + return FsResult::Error(ret); + } + return FsResult::Success(); +} + +FsResult FsWatcher::Start() +{ + if (!watchEntity) { + HILOGE("Failed to get watchEntity when start."); + return FsResult::Error(EINVAL); + } + + shared_ptr info = watchEntity->data_; + int ret = FsFileWatcher::GetInstance().StartNotify(info); + if (ret != ERRNO_NOERR) { + HILOGE("Failed to startNotify."); + return FsResult::Error(ret); + } + + FsFileWatcher::GetInstance().AsyncGetNotifyEvent(); + + return FsResult::Success(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.h b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.h new file mode 100644 index 000000000..46a1c5340 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_watcher.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCHER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCHER_H + +#include "filemgmt_libfs.h" +#include "fs_watch_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +class FsWatcher { +public: + static FsResult Constructor(); + FsResult Start(); + FsResult Stop(); + + FsWatchEntity *GetWatchEntity() const + { + return watchEntity.get(); + } + + FsWatcher(const FsWatcher &) = delete; + FsWatcher &operator=(const FsWatcher &) = delete; + + FsWatcher(FsWatcher &&) noexcept = default; + FsWatcher &operator=(FsWatcher &&) noexcept = default; + + ~FsWatcher() = default; + +private: + unique_ptr watchEntity; + explicit FsWatcher(unique_ptr entity) : watchEntity(move(entity)) {} +}; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_FS_WATCHER_H diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/i_watcher_callback.h b/interfaces/kits/js/src/mod_fs/class_watcher/i_watcher_callback.h new file mode 100644 index 000000000..a6baaa782 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/i_watcher_callback.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_I_WATCHER_CALLBACK_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_I_WATCHER_CALLBACK_H + +#include + +namespace OHOS::FileManagement::ModuleFileIO { + +class IWatcherCallback { +public: + virtual ~IWatcherCallback() = default; + virtual bool IsStrictEquals(const std::shared_ptr &other) const = 0; + virtual void InvokeCallback(const std::string &fileName, uint32_t event, uint32_t cookie) const = 0; + virtual std::string GetClassName() const = 0; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_I_WATCHER_CALLBACK_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp new file mode 100644 index 000000000..83b5e2a51 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "watcher_data_cache.h" +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +bool WatcherDataCache::AddWatcherInfo(std::shared_ptr info) +{ + std::lock_guard lock(cacheMutex_); + for (auto &iter : watcherInfoCache_) { + if (iter->fileName == info->fileName && iter->events == info->events) { + bool isSame = iter->callback->IsStrictEquals(info->callback); + if (isSame) { + HILOGE("Failed to add watcher, fileName:%{private}s the callback is same", info->fileName.c_str()); + return false; + } + } + } + watcherInfoCache_.push_back(info); + wdFileNameCache_[info->fileName] = std::make_pair(info->wd, info->events); + return true; +} + +uint32_t WatcherDataCache::RemoveWatcherInfo(std::shared_ptr info) +{ + std::lock_guard lock(cacheMutex_); + auto it = std::find(watcherInfoCache_.begin(), watcherInfoCache_.end(), info); + if (it != watcherInfoCache_.end()) { + watcherInfoCache_.erase(it); + } + + uint32_t remainingEvents = 0; + for (const auto &iter : watcherInfoCache_) { + if (iter->fileName == info->fileName && iter->wd > 0) { + remainingEvents |= iter->events; + } + } + + return remainingEvents; +} + +bool WatcherDataCache::RemoveFileWatcher(const std::string &fileName) +{ + std::lock_guard lock(cacheMutex_); + + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return false; + } + wdFileNameCache_.erase(iter); + + watcherInfoCache_.erase(std::remove_if(watcherInfoCache_.begin(), watcherInfoCache_.end(), + [&fileName](const std::shared_ptr &info) { + return info->fileName == fileName; + }), watcherInfoCache_.end()); + + return true; +} + +std::tuple WatcherDataCache::FindWatchedWd(const std::string &fileName, uint32_t event) +{ + std::lock_guard lock(cacheMutex_); + + int32_t wd = -1; + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return { false, wd }; + } + + wd = iter->second.first; + if ((iter->second.second & event) == event) { + return { true, wd }; + } + + return { false, wd }; +} + +bool WatcherDataCache::UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events) +{ + std::lock_guard lock(cacheMutex_); + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return false; + } + + iter->second = std::make_pair(wd, events); + return true; +} + +static bool CheckIncludeEvent(uint32_t mask, uint32_t event) +{ + return (mask & event) > 0; +} + +std::tuple>> WatcherDataCache::FindWatcherInfos( + int32_t wd, uint32_t eventMask) +{ + std::lock_guard lock(cacheMutex_); + std::string fileName; + bool found = false; + for (const auto &[key, val] : wdFileNameCache_) { + if (val.first == wd) { + fileName = key; + found = true; + break; + } + } + + if (!found) { + return { false, "", {} }; + } + + std::vector> matchedInfos; + for (const auto &info : watcherInfoCache_) { + uint32_t watchEvent = 0; + if ((info->fileName == fileName) && (info->wd > 0)) { + watchEvent = info->events; + } + if (CheckIncludeEvent(eventMask, watchEvent)) { + matchedInfos.push_back(info); + } + } + return { !matchedInfos.empty(), fileName, matchedInfos }; +} + +uint32_t WatcherDataCache::GetFileEvents(const std::string &fileName) +{ + std::lock_guard lock(cacheMutex_); + auto iter = wdFileNameCache_.find(fileName); + if (iter == wdFileNameCache_.end()) { + return 0; + } + return iter->second.second; +} + +bool WatcherDataCache::HasWatcherInfo() const +{ + std::lock_guard lock(cacheMutex_); + return !watcherInfoCache_.empty(); +} + +void WatcherDataCache::ClearCache() +{ + std::lock_guard lock(cacheMutex_); + watcherInfoCache_.clear(); + wdFileNameCache_.clear(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h new file mode 100644 index 000000000..e18d584f1 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_data_cache.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_WATCHER_DATA_CACHE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_WATCHER_DATA_CACHE_H + +#include +#include +#include +#include +#include + +#include "fs_watch_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +class WatcherDataCache { +public: + bool AddWatcherInfo(std::shared_ptr info); + uint32_t RemoveWatcherInfo(std::shared_ptr info); + bool RemoveFileWatcher(const std::string &fileName); + std::tuple FindWatchedWd(const std::string &fileName, uint32_t event); + bool UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events); + std::tuple>> FindWatcherInfos( + int32_t wd, uint32_t eventMask); + uint32_t GetFileEvents(const std::string &fileName); + bool HasWatcherInfo() const; + void ClearCache(); + +public: + WatcherDataCache() = default; + ~WatcherDataCache() = default; + WatcherDataCache(const WatcherDataCache &) = delete; + WatcherDataCache &operator=(const WatcherDataCache &) = delete; + +private: + mutable std::mutex cacheMutex_; + std::vector> watcherInfoCache_; + std::unordered_map> wdFileNameCache_; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_WATCHER_WATCHER_DATA_CACHE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/close_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/close_ani.cpp index ab03c2525..e2f7b9464 100644 --- a/interfaces/kits/js/src/mod_fs/properties/ani/close_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/ani/close_ani.cpp @@ -43,7 +43,7 @@ tuple ParseFdOrFile(ani_env *env, ani_object obj) env->Object_InstanceOf(obj, doubleClass, &isDouble); if (isDouble) { ani_int fd; - if (ANI_OK != env->Object_CallMethodByName_Int(obj, "intValue", nullptr, &fd)) { + if (ANI_OK != env->Object_CallMethodByName_Int(obj, "toInt", nullptr, &fd)) { HILOGE("Get fd value failed"); return { false, result, nullptr }; } diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.cpp new file mode 100644 index 000000000..da3f63b52 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.cpp @@ -0,0 +1,95 @@ +/* + * 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 "connectdfs_ani.h" +#include "connectdfs_core.h" +#include "filemgmt_libhilog.h" +#include "error_handler.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +void ConnectDfsAni::ConnectDfsSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string networkId, + ani_object listener) +{ + //注册 + auto [succNetworkId, networkIdStr] = TypeConverter::ToUTF8String(env, networkId); + if (!succNetworkId) { + HILOGE("Invalid NetworkId"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + sptr anidfslistener_(new(std::nothrow) ANIDfsListener()); + anidfslistener_->SetConnectDfsEnv(env); + ani_ref promiseDeferred = nullptr; + + if (listener != nullptr) { + anidfslistener_->SetConnectDfsCBRef(listener); + HILOGE("Connectdfs set callback success"); + } else { + anidfslistener_->SetConnectDfsPromiseRef(promiseDeferred); + HILOGE("Connectdfs set Promise success"); + } + + auto ret = ConnectDfsCore::ConnectDfsExec(networkIdStr, anidfslistener_); + if (!ret.IsSuccess()) { + HILOGE("ConnectDfsExec failed"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } +} + +void ANIDfsListener::SetConnectDfsEnv(ani_env *env) +{ + env_ = env; +} + +void ANIDfsListener::SetConnectDfsCBRef(ani_ref ref) +{ + onStatusRef_ = ref; +} + +void ANIDfsListener::SetConnectDfsPromiseRef(ani_ref promiseDeferred) +{ + promiseDeferred_ = promiseDeferred; +} + +void ANIDfsListener::OnStatus(const std::string &networkId, int32_t status) +{ + //回调 + ani_string networkId_; + ani_status res = env_->String_NewUTF8(networkId.c_str(), networkId.size(), &networkId_); + if (res != ANI_OK) { + HILOGE("std string to ani string failed. ret = %{public}d", static_cast(res)); + ErrorHandler::Throw(env_, E_PARAMS); + return; + } + ani_double status_ = static_cast(status); + ani_status ret = env_->Object_CallMethodByName_Void(static_cast(objectlistener), "onStatus", nullptr, + networkId_, status_); + if (ret != ANI_OK) { + HILOGE("Object_CallMethodByName_Void failed. ret = %{public}d", static_cast(ret)); + ErrorHandler::Throw(env_, E_PARAMS); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.h new file mode 100644 index 000000000..b215b37aa --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/connectdfs_ani.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CONNECTDFS_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CONNECTDFS_ANI_H + +#include +#include +#include "dfs_listener/file_dfs_listener_stub.h" +#include "distributed_file_daemon_manager.h" +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; + +class ANIDfsListener : public FileDfsListenerStub { +public: + void OnStatus(const std::string &networkId, int32_t status); + void SetConnectDfsEnv(ani_env *env); + void SetConnectDfsCBRef(ani_ref ref); + void SetConnectDfsPromiseRef(ani_ref promiseDeferred); + +private: + ani_env *env_ = nullptr; + ani_ref onStatusRef_ = nullptr; + ani_ref promiseDeferred_ = nullptr; + ani_ref objectlistener = nullptr; +}; +class ConnectDfsAni final { +public: + static void ConnectDfsSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string networkId, + ani_object listener); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CONNECTDFS_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.cpp new file mode 100644 index 000000000..541cd7f6c --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.cpp @@ -0,0 +1,170 @@ +/* + * 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 "copy_ani.h" + +#include "ani_helper.h" +#include "ani_signature.h" +#include "copy_core.h" +#include "error_handler.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_task_signal.h" +#include "progress_listener_ani.h" +#include "task_signal_listener_ani.h" +#include "task_signal_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static bool ParseListenerFromOptionArg(ani_env *env, const ani_object &options, CopyOptions &opts) +{ + ani_ref prog; + if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "progressListener", &prog)) { + HILOGE("Illegal options.progressListener type"); + return false; + } + + ani_boolean isUndefined = true; + env->Reference_IsUndefined(prog, &isUndefined); + if (isUndefined) { + return true; + } + + ani_ref cbRef; + if (ANI_OK != env->GlobalReference_Create(prog, &cbRef)) { + HILOGE("Illegal options.progressListener type"); + return false; + } + + ani_vm *vm = nullptr; + env->GetVM(&vm); + auto listener = CreateSharedPtr(vm, cbRef); + if (listener == nullptr) { + HILOGE("Failed to request heap memory."); + return false; + } + + opts.progressListener = move(listener); + return true; +} + +static bool ParseCopySignalFromOptionArg(ani_env *env, const ani_object &options, CopyOptions &opts) +{ + ani_ref prog; + if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "copySignal", &prog)) { + HILOGE("Illegal options.CopySignal type"); + return false; + } + + ani_boolean isUndefined = true; + env->Reference_IsUndefined(prog, &isUndefined); + if (isUndefined) { + return true; + } + + auto taskSignal = CreateSharedPtr(); + if (taskSignal == nullptr) { + HILOGE("Failed to request heap memory."); + return false; + } + + auto signalObj = static_cast(prog); + ani_vm *vm = nullptr; + env->GetVM(&vm); + auto listener = CreateSharedPtr(vm, signalObj, taskSignal); + if (listener == nullptr) { + HILOGE("Failed to request heap memory."); + return false; + } + + auto result = FsTaskSignal::Constructor(taskSignal, listener); + if (!result.IsSuccess()) { + return false; + } + + auto copySignal = result.GetData().value(); + auto succ = TaskSignalWrapper::Wrap(env, signalObj, copySignal.get()); + if (!succ) { + return false; + } + + opts.copySignal = move(copySignal); + return true; +} + +static tuple> ParseOptions(ani_env *env, ani_object &options) +{ + ani_boolean isUndefined; + env->Reference_IsUndefined(options, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + CopyOptions opts; + auto succ = ParseListenerFromOptionArg(env, options, opts); + if (!succ) { + return { false, nullopt }; + } + + succ = ParseCopySignalFromOptionArg(env, options, opts); + if (!succ) { + return { false, nullopt }; + } + + return { true, make_optional(move(opts)) }; +} + +void CopyAni::CopySync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string srcUri, ani_string destUri, ani_object options) +{ + auto [succSrc, src] = TypeConverter::ToUTF8String(env, srcUri); + auto [succDest, dest] = TypeConverter::ToUTF8String(env, destUri); + auto [succOpts, opts] = ParseOptions(env, options); + + if (!succSrc) { + HILOGE("The first argument requires uri"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + if (!succDest) { + HILOGE("The second argument requires uri"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + if (!succOpts) { + HILOGE("The third argument requires listener function"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + + auto ret = CopyCore::DoCopy(src, dest, opts); + if (!ret.IsSuccess()) { + HILOGE("DoCopy failed!"); + const FsError &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.h new file mode 100644 index 000000000..fbbcf9d08 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_ani.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class CopyAni final { +public: + static void CopySync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string srcUri, ani_string destUri, ani_object options); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.cpp new file mode 100644 index 000000000..13804c8ad --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.cpp @@ -0,0 +1,165 @@ +/* + * 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 "copy_dir_ani.h" + +#include +#include "ani_signature.h" +#include "copy_dir_core.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static tuple ToConflictFiles(ani_env *env, const ConflictFiles &files) +{ + auto classDesc = FS::ConflictFilesInner::classDesc.c_str(); + ani_class cls; + ani_status ret; + if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { + HILOGE("Cannot find class %{private}s, err: %{private}d", classDesc, ret); + return { false, nullptr }; + } + + auto ctorDesc = FS::ConflictFilesInner::ctorDesc.c_str(); + auto ctorSig = FS::ConflictFilesInner::ctorSig.c_str(); + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) != ANI_OK) { + HILOGE("Cannot find class %{private}s constructor method, err: %{private}d", classDesc, ret); + return { false, nullptr }; + } + + auto [succSrc, src] = TypeConverter::ToAniString(env, files.srcFiles); + if (!succSrc) { + HILOGE("Convert ConflictFiles srcFiles to ani string failed!"); + return { false, nullptr }; + } + + auto [succDest, dest] = TypeConverter::ToAniString(env, files.destFiles); + if (!succSrc) { + HILOGE("Convert ConflictFiles destFiles to ani string failed!"); + return { false, nullptr }; + } + + ani_object obj; + if ((ret = env->Object_New(cls, ctor, &obj, src, dest)) != ANI_OK) { + HILOGE("Create ConflictFiles object failed!, err: %{private}d", ret); + return { false, nullptr }; + } + + return { true, obj }; +} + +static tuple> ToConflictFilesArray( + ani_env *env, const optional> &errFiles) +{ + if (!errFiles.has_value()) { + return { true, nullopt }; + } + auto classDesc = BuiltInTypes::Array::classDesc.c_str(); + ani_class cls = nullptr; + ani_status ret; + + if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { + HILOGE("Cannot find class %{private}s, err: %{private}d", classDesc, ret); + return { false, nullopt }; + } + + auto ctorDesc = BuiltInTypes::Array::ctorDesc.c_str(); + auto ctorSig = BuiltInTypes::Array::ctorSig.c_str(); + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) != ANI_OK) { + HILOGE("Cannot find class %{private}s constructor method, err: %{private}d", classDesc, ret); + return { false, nullopt }; + } + + ani_object arr; + auto files = errFiles.value(); + if ((ret = env->Object_New(cls, ctor, &arr, files.size())) != ANI_OK) { + HILOGE("Create Array failed!, err: %{private}d", ret); + return { false, nullopt }; + } + + auto setterDesc = BuiltInTypes::Array::setterDesc.c_str(); + auto setterSig = BuiltInTypes::Array::objectSetterSig.c_str(); + ani_size index = 0; + for (const auto &errFile : files) { + auto [succ, fileObj] = ToConflictFiles(env, errFile); + if (!succ) { + return { false, nullopt }; + } + + if ((ret = env->Object_CallMethodByName_Void(arr, setterDesc, setterSig, index, fileObj)) != ANI_OK) { + HILOGE("Add element to Array failed, err: %{private}d", ret); + return { false, nullopt }; + } + index++; + } + + return { true, make_optional(move(arr)) }; +} + +void CopyDirAni::CopyDirSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string src, ani_string dest, ani_object mode) +{ + error_code errCode; + + auto [succSrc, srcPath] = TypeConverter::ToUTF8String(env, src); + if (!succSrc) { + HILOGE("Invalid src, errCode = %{public}d", errCode.value()); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [succDest, destPath] = TypeConverter::ToUTF8String(env, dest); + if (!succDest) { + HILOGE("Invalid dest, errCode = %{public}d", errCode.value()); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [succMode, optMode] = TypeConverter::ToOptionalInt32(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [fsResult, errFiles] = CopyDirCore::DoCopyDir(srcPath, destPath, optMode); + if (!fsResult.IsSuccess()) { + HILOGE("DoCopyFile failed!"); + auto [succ, errData] = ToConflictFilesArray(env, errFiles); + if (!succ) { + HILOGE("Convert conflict files array failed"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + const FsError &err = fsResult.GetError(); + ErrorHandler::Throw(env, err, errData); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.h new file mode 100644 index 000000000..469b5fe41 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/copy_dir_ani.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_DIR_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_DIR_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class CopyDirAni final { +public: + static void CopyDirSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string src, ani_string dest, ani_object mode); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_COPY_DIR_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.cpp new file mode 100644 index 000000000..17fe296a3 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.cpp @@ -0,0 +1,218 @@ +/* + * 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 "create_randomaccessfile_ani.h" + +#include "ani_helper.h" +#include "ani_signature.h" +#include "create_randomaccessfile_core.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static ani_object Wrap(ani_env *env, const FsRandomAccessFile *rafFile) +{ + if (rafFile == nullptr) { + HILOGE("FsRandomAccessFile pointer is null!"); + return nullptr; + } + + auto classDesc = FS::RandomAccessFileInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %s", classDesc); + return nullptr; + } + + auto ctorDesc = FS::RandomAccessFileInner::ctorDesc.c_str(); + auto ctorSig = FS::RandomAccessFileInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %s", classDesc); + return nullptr; + } + + ani_long ptr = static_cast(reinterpret_cast(rafFile)); + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, ptr)) { + HILOGE("New %s obj Failed!", classDesc); + return nullptr; + } + + const auto &fdRet = rafFile->GetFD(); + if (!fdRet.IsSuccess()) { + HILOGE("GetFD Failed!"); + return nullptr; + } + + const auto &fd = fdRet.GetData().value(); + if (ANI_OK != AniHelper::SetPropertyValue(env, cls, obj, "fd", static_cast(fd))) { + HILOGE("Set fd field value failed!"); + return nullptr; + } + + const auto &fpRet = rafFile->GetFPointer(); + if (!fpRet.IsSuccess()) { + HILOGE("GetFPointer Failed!"); + return nullptr; + } + + const auto &fp = fpRet.GetData().value(); + if (ANI_OK != AniHelper::SetPropertyValue(env, cls, obj, "filePointer", static_cast(fp))) { + HILOGE("Set fp field value failed!"); + return nullptr; + } + return obj; +} + +static tuple JudgeFile(ani_env *env, ani_object obj) +{ + auto stringTypeDesc = BuiltInTypes::String::classDesc.c_str(); + ani_class stringClass; + env->FindClass(stringTypeDesc, &stringClass); + ani_boolean isString = false; + env->Object_InstanceOf(obj, stringClass, &isString); + if (isString) { + return { true, true }; + } + + auto fileClassDesc = FS::FileInner::classDesc.c_str(); + ani_class fileClass; + env->FindClass(fileClassDesc, &fileClass); + ani_boolean isFile = false; + env->Object_InstanceOf(obj, fileClass, &isFile); + if (isFile) { + return { true, false }; + } + HILOGE("Invalid file type"); + return { false, false }; +} + +static tuple> ToRafOptions(ani_env *env, ani_object obj) +{ + RandomAccessFileOptions options; + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succStart, start] = AniHelper::ParseInt64Option(env, obj, "start"); + if (!succStart) { + HILOGE("Illegal option.start parameter"); + return { false, nullopt }; + } + options.start = start; + + auto [succEnd, end] = AniHelper::ParseInt64Option(env, obj, "end"); + if (!succEnd) { + HILOGE("Illegal option.end parameter"); + return { false, nullopt }; + } + options.end = end; + + return { true, make_optional(move(options)) }; +} + +static ani_object CreateRandomAccessFileByString( + ani_env *env, ani_object file, ani_object mode, optional op) +{ + auto [succPath, path] = TypeConverter::ToUTF8String(env, static_cast(file)); + if (!succPath) { + HILOGE("Parse file path failed"); + return nullptr; + } + auto [succMode, modeOp] = TypeConverter::ToOptionalInt32(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + FsResult ret = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, modeOp, op); + if (!ret.IsSuccess()) { + HILOGE("CreateRandomAccessFile failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + const FsRandomAccessFile *refFile = ret.GetData().value(); + auto result = Wrap(env, move(refFile)); + if (result == nullptr) { + delete refFile; + refFile = nullptr; + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +ani_object CreateRandomAccessFileAni::CreateRandomAccessFileSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_object file, ani_object mode, ani_object options) +{ + auto [succOp, op] = ToRafOptions(env, options); + if (!succOp) { + HILOGE("Failed to resolve options!"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succ, isPath] = JudgeFile(env, file); + if (!succ) { + HILOGE("Judge file argument failed"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + if (isPath) { + return CreateRandomAccessFileByString(env, file, mode, op); + } else { + ani_double fdOp; + if (ANI_OK != env->Object_GetPropertyByName_Double(file, "fd", &fdOp)) { + HILOGE("Get fd in class file failed"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + int32_t fd = static_cast(fdOp); + FsResult ret = CreateRandomAccessFileCore::DoCreateRandomAccessFile(fd, op); + if (!ret.IsSuccess()) { + HILOGE("CreateRandomAccessFile failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + const FsRandomAccessFile *refFile = ret.GetData().value(); + auto result = Wrap(env, move(refFile)); + if (result == nullptr) { + delete refFile; + refFile = nullptr; + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.h new file mode 100644 index 000000000..eb7940596 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/create_randomaccessfile_ani.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CREATE_RANDOMACCESSFILE_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CREATE_RANDOMACCESSFILE_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class CreateRandomAccessFileAni final { +public: + static ani_object CreateRandomAccessFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, + ani_object file, ani_object mode, ani_object options); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_CREATE_RANDOMACCESSFILE_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.cpp new file mode 100644 index 000000000..d81983404 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.cpp @@ -0,0 +1,71 @@ +/* + * 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 "create_stream_ani.h" + +#include "create_stream_core.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "stream_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object CreateStreamAni::CreateStreamSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string mode) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succMode, openMode] = TypeConverter::ToUTF8String(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + FsResult ret = CreateStreamCore::DoCreateStream(srcPath, openMode); + if (!ret.IsSuccess()) { + HILOGE("create stream failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const FsStream *stream = ret.GetData().value(); + auto result = StreamWrapper::Wrap(env, move(stream)); + if (result == nullptr) { + delete stream; + stream = nullptr; + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.h new file mode 100644 index 000000000..2052b6b4d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/create_stream_ani.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class CreateStreamAni final { +public: + static ani_object CreateStreamSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string mode); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.cpp new file mode 100644 index 000000000..7beafaeaa --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.cpp @@ -0,0 +1,46 @@ +/* + * 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 "disconnectdfs_ani.h" +#include "disconnectdfs_core.h" +#include "filemgmt_libhilog.h" +#include "error_handler.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +void DisConnectDfsAni::DisConnectDfsSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string networkId) +{ + auto [succNetworkId, networkIdStr] = TypeConverter::ToUTF8String(env, networkId); + if (!succNetworkId) { + HILOGE("Invalid NetworkId"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } + auto ret = DisConnectDfsCore::DisConnectDfsExec(networkIdStr); + if (!ret.IsSuccess()) { + HILOGE("DisConnectDfsExec failed"); + ErrorHandler::Throw(env, E_PARAMS); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.h new file mode 100644 index 000000000..a42dab9cc --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/disconnectdfs_ani.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DISCONNECTDFS_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DISCONNECTDFS_ANI_H + +#include +#include "dfs_listener/file_dfs_listener_stub.h" +#include "distributed_file_daemon_manager.h" +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class DisConnectDfsAni final { +public: + static void DisConnectDfsSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string networkId); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DISCONNECTDFS_ANI_H diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp new file mode 100644 index 000000000..22c002243 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.cpp @@ -0,0 +1,52 @@ +/* + * 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 "dup_ani.h" + +#include "ani_helper.h" +#include "dup_core.h" +#include "error_handler.h" +#include "file_wrapper.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object DupAni::Dup(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd) +{ + FsResult ret = DupCore::DoDup(static_cast(fd)); + if (!ret.IsSuccess()) { + HILOGE("Dup file failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + const FsFile *file = ret.GetData().value(); + auto result = FileWrapper::Wrap(env, move(file)); + if (result == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h new file mode 100644 index 000000000..c0e4a02c7 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/dup_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DUP_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DUP_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class DupAni final { +public: + static ani_object Dup(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_DUP_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.cpp new file mode 100644 index 000000000..7ce4a8bfc --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.cpp @@ -0,0 +1,44 @@ +/* + * 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 "fdatasync_ani.h" + +#include + +#include "error_handler.h" +#include "fdatasync_core.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void FDataSyncAni::FDataSyncSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd) +{ + auto ret = FDataSyncCore::DoFDataSync(static_cast(fd)); + if (!ret.IsSuccess()) { + HILOGE("Fdatasync failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.h new file mode 100644 index 000000000..ce0b83261 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fdatasync_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FDATASYNC_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FDATASYNC_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class FDataSyncAni final { +public: + static void FDataSyncSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FDATASYNC_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.cpp new file mode 100644 index 000000000..bc6e8d274 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.cpp @@ -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. + */ + +#include "fdopen_stream_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fdopen_stream_core.h" +#include "stream_wrapper.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object FdopenStreamAni::FdopenStreamSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_string mode) +{ + auto [succMode, openMode] = TypeConverter::ToUTF8String(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + FsResult ret = FdopenStreamCore::DoFdopenStream(static_cast(fd), openMode); + if (!ret.IsSuccess()) { + HILOGE("fdopen stream failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const FsStream *stream = ret.GetData().value(); + auto result = StreamWrapper::Wrap(env, move(stream)); + if (result == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.h new file mode 100644 index 000000000..81f0fde31 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fdopen_stream_ani.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class FdopenStreamAni final { +public: + static ani_object FdopenStreamSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_string mode); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.cpp new file mode 100644 index 000000000..f2680914f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsync_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "fsync_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +void FsyncAni::FsyncSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd) +{ + auto ret = FsyncCore::DoFsync(static_cast(fd)); + if (!ret.IsSuccess()) { + HILOGE("DoFsync failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.h new file mode 100644 index 000000000..ad9d936fe --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/fsync_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FSYNC_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FSYNC_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class FsyncAni final { +public: + static void FsyncSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_FSYNC_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp index 43527ee47..65e0f545e 100644 --- a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp @@ -65,7 +65,7 @@ tuple ParseIntParam(ani_env *env, ani_object obj, string tag) } ani_int resultRefRes; if (ANI_OK != env->Object_CallMethodByName_Int( - static_cast(resultRef), "intValue", nullptr, &resultRefRes)) { + static_cast(result_ref), "toInt", nullptr, &result_ref_res)) { result = -1; return { false, result }; } @@ -87,7 +87,7 @@ tuple> ParseDoubleParam(ani_env *env, ani_object obj, str ani_double resultRefRes; if (ANI_OK != env->Object_CallMethodByName_Double( - static_cast(resultRef), "doubleValue", nullptr, &resultRefRes)) { + static_cast(result_ref), "toDouble", nullptr, &result_ref_res)) { return { false, nullopt }; } double result = static_cast(resultRefRes); @@ -206,7 +206,7 @@ tuple> ParseArgs(ani_env *env, ani_object obj) return { true, make_optional(result) }; } -ani_array_ref ListFileAni::ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj) +ani_array ListFileAni::ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj) { auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); if (!succPath) { @@ -244,4 +244,4 @@ ani_array_ref ListFileAni::ListFileSync(ani_env *env, [[maybe_unused]] ani_class } // namespace ANI } // namespace ModuleFileIO } // namespace FileManagement -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h index 1c238ab59..ee5dadbe1 100644 --- a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h +++ b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.h @@ -25,7 +25,7 @@ namespace ANI { class ListFileAni final { public: - static ani_array_ref ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj); + static ani_array ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj); }; } // namespace ANI @@ -33,4 +33,4 @@ public: } // namespace FileManagement } // namespace OHOS -#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LISTFILE_ANI_H \ No newline at end of file +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LISTFILE_ANI_H diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.cpp new file mode 100644 index 000000000..1d689c696 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.cpp @@ -0,0 +1,63 @@ +/* + * 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 "lseek_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "lseek_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace std; + +optional ParseSeekPos(const optional &whence) +{ + if (!whence.has_value()) { + return nullopt; + } + + return make_optional(static_cast(move(whence.value()))); +} + +ani_double LseekAni::LseekSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_double offset, ani_enum_item whence) +{ + auto [succWhence, whenceOp] = TypeConverter::EnumToInt32(env, whence); + if (!succWhence) { + HILOGE("Invalid whence"); + ErrorHandler::Throw(env, EINVAL); + return -1; + } + auto pos = ParseSeekPos(whenceOp); + + auto ret = LseekCore::DoLseek(static_cast(fd), static_cast(offset), pos); + if (!ret.IsSuccess()) { + HILOGE("DoLseek failed!"); + const FsError &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return -1; + } + + return ani_double(static_cast(ret.GetData().value())); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.h new file mode 100644 index 000000000..5a7995d79 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/lseek_ani.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSEEK_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSEEK_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +class LseekAni final { +public: + static ani_double LseekSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_double offset, ani_enum_item whence); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_LSEEK_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.cpp new file mode 100644 index 000000000..42b5a7316 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.cpp @@ -0,0 +1,60 @@ +/* + * 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_ani.h" + +#include + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "mkdtemp_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +ani_string MkdtempAni::MkdtempSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string prefix) +{ + auto [succPath, prefixPath] = TypeConverter::ToUTF8String(env, prefix); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = MkdtempCore::DoMkdtemp(prefixPath); + if (!ret.IsSuccess()) { + HILOGE("Mkdtemp faild"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const auto &res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.h new file mode 100644 index 000000000..cda9c8e12 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/mkdtemp_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MKDTEMP_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MKDTEMP_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class MkdtempAni final { +public: + static ani_string MkdtempSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string prefix); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MKDTEMP_ANI_H diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.cpp new file mode 100644 index 000000000..77633e1b5 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.cpp @@ -0,0 +1,155 @@ +/* + * 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 "movedir_ani.h" + +#include +#include "ani_signature.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "movedir_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static tuple ToConflictFiles(ani_env *env, const ErrFiles &files) +{ + auto classDesc = FS::ConflictFilesInner::classDesc.c_str(); + ani_class cls; + ani_status ret; + if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { + HILOGE("Cannot find class %{private}s, err: %{private}d", classDesc, ret); + return { false, nullptr }; + } + + auto ctorDesc = FS::ConflictFilesInner::ctorDesc.c_str(); + auto ctorSig = FS::ConflictFilesInner::ctorSig.c_str(); + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) != ANI_OK) { + HILOGE("Cannot find class %{private}s constructor method, err: %{private}d", classDesc, ret); + return { false, nullptr }; + } + + auto [succSrc, src] = TypeConverter::ToAniString(env, files.srcFiles); + if (!succSrc) { + HILOGE("Convert ConflictFiles srcFiles to ani string failed!"); + return { false, nullptr }; + } + + auto [succDest, dest] = TypeConverter::ToAniString(env, files.destFiles); + if (!succSrc) { + HILOGE("Convert ConflictFiles destFiles to ani string failed!"); + return { false, nullptr }; + } + + ani_object obj; + if ((ret = env->Object_New(cls, ctor, &obj, src, dest)) != ANI_OK) { + HILOGE("Create ConflictFiles object failed!, err: %{private}d", ret); + return { false, nullptr }; + } + + return { true, obj }; +} + +static tuple> ToConflictFilesArray( + ani_env *env, const optional> &errFiles) +{ + if (!errFiles.has_value()) { + return { true, nullopt }; + } + auto classDesc = BuiltInTypes::Array::classDesc.c_str(); + ani_class cls = nullptr; + ani_status ret; + + if ((ret = env->FindClass(classDesc, &cls)) != ANI_OK) { + HILOGE("Cannot find class %{private}s, err: %{private}d", classDesc, ret); + return { false, nullopt }; + } + + auto ctorDesc = BuiltInTypes::Array::ctorDesc.c_str(); + auto ctorSig = BuiltInTypes::Array::ctorSig.c_str(); + ani_method ctor; + if ((ret = env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) != ANI_OK) { + HILOGE("Cannot find class %{private}s constructor method, err: %{private}d", classDesc, ret); + return { false, nullopt }; + } + + ani_object arr; + auto files = errFiles.value(); + if ((ret = env->Object_New(cls, ctor, &arr, files.size())) != ANI_OK) { + HILOGE("Create Array failed!, err: %{private}d", ret); + return { false, nullopt }; + } + + auto setterDesc = BuiltInTypes::Array::setterDesc.c_str(); + auto setterSig = BuiltInTypes::Array::objectSetterSig.c_str(); + ani_size index = 0; + for (const auto &errFile : files) { + auto [succ, fileObj] = ToConflictFiles(env, errFile); + if (!succ) { + return { false, nullopt }; + } + + if ((ret = env->Object_CallMethodByName_Void(arr, setterDesc, setterSig, index, fileObj)) != ANI_OK) { + HILOGE("Add element to Array failed, err: %{private}d", ret); + return { false, nullopt }; + } + index++; + } + + return { true, make_optional(move(arr)) }; +} + +void MoveDirAni::MoveDirSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string src, ani_string dest, ani_object mode) +{ + auto [succSrc, srcPath] = TypeConverter::ToUTF8String(env, src); + auto [succDest, destPath] = TypeConverter::ToUTF8String(env, dest); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires filepath"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [succMode, optMode] = TypeConverter::ToOptionalInt32(env, mode); + if (!succMode) { + HILOGE("Invalid mode"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [fsResult, errFiles] = MoveDirCore::DoMoveDir(srcPath, destPath, optMode); + if (!fsResult.IsSuccess()) { + HILOGE("DoMoveDir failed!"); + auto [succ, errData] = ToConflictFilesArray(env, errFiles); + if (!succ) { + HILOGE("Convert conflict files array failed"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return; + } + const FsError &err = fsResult.GetError(); + ErrorHandler::Throw(env, err, errData); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.h new file mode 100644 index 000000000..bd1750446 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/movedir_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MOVEDIR_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MOVEDIR_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class MoveDirAni final { +public: + static void MoveDirSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string src, ani_string dest, ani_object mode); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_MOVEDIR_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.cpp new file mode 100644 index 000000000..10c3ce394 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.cpp @@ -0,0 +1,88 @@ +/* + * 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_lines_ani.h" + +#include "ani_helper.h" +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "read_lines_core.h" +#include "reader_iterator_ani.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +static tuple> ToReadLinesOptions(ani_env *env, ani_object obj) +{ + Options options; + + ani_boolean isUndefined; + env->Reference_IsUndefined(obj, &isUndefined); + if (isUndefined) { + return { true, nullopt }; + } + + auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj); + if (!succEncoding) { + HILOGE("Illegal option.encoding parameter"); + return { false, nullopt }; + } + options.encoding = encoding.value(); + + return { true, make_optional(move(options)) }; +} + +ani_object ReadLinesAni::ReadLinesSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object options) +{ + auto [succPath, filePath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path from ETS first argument"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [succMode, opt] = ToReadLinesOptions(env, options); + if (!succMode) { + HILOGE("Invalid options"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + FsResult ret = ReadLinesCore::DoReadLines(filePath, opt); + if (!ret.IsSuccess()) { + HILOGE("Readlines failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const FsReaderIterator *readerIterator = ret.GetData().value(); + auto result = ReaderIteratorAni::Wrap(env, move(readerIterator)); + if (result == nullptr) { + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.h new file mode 100644 index 000000000..3f1bfeb72 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/read_lines_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_READ_LINES_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_READ_LINES_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class ReadLinesAni final { +public: + static ani_object ReadLinesSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, + ani_object options); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_READ_LINES_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.cpp new file mode 100644 index 000000000..0b4d762a0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rename_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "rename_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +void RenameAni::RenameSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string oldPath, ani_string newPath) +{ + auto [succSrcPath, srcPath] = TypeConverter::ToUTF8String(env, oldPath); + if (!succSrcPath) { + HILOGE("Invalid src"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto [succDestPath, destPath] = TypeConverter::ToUTF8String(env, newPath); + if (!succDestPath) { + HILOGE("Invalid dest"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = RenameCore::DoRename(srcPath, destPath); + if (!ret.IsSuccess()) { + HILOGE("DoRename failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.h new file mode 100644 index 000000000..f2c39cbb0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/rename_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_RENAME_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_RENAME_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class RenameAni final { +public: + static void RenameSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string oldPath, ani_string newPath); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_RENAME_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.cpp new file mode 100644 index 000000000..4cbac5133 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.cpp @@ -0,0 +1,53 @@ +/* + * 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 "symlink_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "symlink_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void SymlinkAni::SymlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string target, ani_string srcPath) +{ + auto [succTarget, targetPath] = TypeConverter::ToUTF8String(env, target); + if (!succTarget) { + HILOGE("Invalid target"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto [succSrc, src] = TypeConverter::ToUTF8String(env, srcPath); + if (!succSrc) { + HILOGE("Invalid src"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = SymlinkCore::DoSymlink(targetPath, src); + if (!ret.IsSuccess()) { + HILOGE("DoSymlink failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.h new file mode 100644 index 000000000..6ba3abb55 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/symlink_ani.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_SYMLINK_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_SYMLINK_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class SymlinkAni final { +public: + static void SymlinkSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string target, ani_string srcPath); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_SYMLINK_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.cpp new file mode 100644 index 000000000..849f10d4d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.cpp @@ -0,0 +1,48 @@ +/* + * 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 "utimes_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "utimes_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void UtimesAni::Utimes( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_double mtime) +{ + auto [succPath, newPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + auto ret = UtimesCore::DoUtimes(newPath, static_cast(mtime)); + if (!ret.IsSuccess()) { + HILOGE("Utimes failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.h new file mode 100644 index 000000000..118f7d25a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/utimes_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_UTIMES_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_UTIMES_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class UtimesAni final { +public: + static void Utimes( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_double mtime); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_UTIMES_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.cpp new file mode 100644 index 000000000..f0641c93f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.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 "watcher_ani.h" + +#include "ani_helper.h" +#include "error_handler.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_watcher_wrapper.h" +#include "watch_event_listener.h" +#include "watcher_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +using namespace OHOS::FileManagement::ModuleFileIO; + +ani_object WatcherAni::CreateWatcherSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_double events, ani_ref listener) +{ + auto [succPath, filePath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + ani_ref cbRef; + if (ANI_OK != env->GlobalReference_Create(move(listener), &cbRef)) { + HILOGE("Failed to get callback"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + ani_vm *vm = nullptr; + env->GetVM(&vm); + auto eventListener = CreateSharedPtr(vm, cbRef); + if (eventListener == nullptr) { + HILOGE("Failed to request heap memory."); + ErrorHandler::Throw(env, ENOMEM); + return nullptr; + } + + FsResult ret = + WatcherCore::DoCreateWatcher(filePath, static_cast(events), move(eventListener)); + if (!ret.IsSuccess()) { + HILOGE("Create watcher failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + const FsWatcher *watcher = ret.GetData().value(); + auto result = FsWatcherWrapper::Wrap(env, move(watcher)); + if (result == nullptr) { + delete watcher; + watcher = nullptr; + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.h new file mode 100644 index 000000000..1175c2f6f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/watcher_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_WATCHER_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_WATCHER_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class WatcherAni final { +public: + static ani_object CreateWatcherSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_double events, ani_ref listener); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_WATCHER_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.cpp new file mode 100644 index 000000000..2a69e0bd2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.cpp @@ -0,0 +1,98 @@ +/* + * 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 "xattr_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" +#include "xattr_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +void XattrAni::SetXattrSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string key, ani_string value) +{ + auto [pathSucc, pathStr] = TypeConverter::ToUTF8String(env, path); + if (!pathSucc) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [keySucc, keyStr] = TypeConverter::ToUTF8String(env, key); + if (!keySucc) { + HILOGE("Invalid xattr key"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [valueSucc, valueStr] = TypeConverter::ToUTF8String(env, value); + if (!valueSucc) { + HILOGE("Invalid xattr value"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = XattrCore::DoSetXattr(pathStr, keyStr, valueStr); + if (!ret.IsSuccess()) { + HILOGE("DoSetXattr failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +ani_string XattrAni::GetXattrSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string key) +{ + auto [pathSucc, pathStr] = TypeConverter::ToUTF8String(env, path); + if (!pathSucc) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto [keySucc, keyStr] = TypeConverter::ToUTF8String(env, key); + if (!keySucc) { + HILOGE("Invalid xattr key"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = XattrCore::DoGetXattr(pathStr, keyStr); + if (!ret.IsSuccess()) { + HILOGE("DoSetXattr failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const auto &res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Create ani_string error"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.h b/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.h new file mode 100644 index 000000000..2bc788d12 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/ani/xattr_ani.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_XATTR_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_XATTR_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class XattrAni final { +public: + static void SetXattrSync( + ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string key, ani_string value); + static ani_string GetXattrSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_string key); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_ANI_XATTR_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.cpp b/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.cpp new file mode 100644 index 000000000..999a460b8 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "filemgmt_libhilog.h" +#include "distributed_file_daemon_manager.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace fs = std::filesystem; + +FsResult ConnectDfsCore::ConnectDfsExec(const std::string &networkId, sptr listener) +{ + if (networkId == "" || listener == nullptr) { + return FsResult::Error(E_PARAMS); + } + + int result = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance(). + OpenP2PConnectionEx(networkId, listener); + if (result != ERRNO_NOERR) { + HILOGE("Fail to openp2pconnection"); + return FsResult::Error(result); + } + return FsResult::Success(); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.h b/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.h new file mode 100644 index 000000000..9e6d713bc --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/connectdfs_core.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CONNECTDFS_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CONNECTDFS_CORE_H +#include +#include +#include +#include +#include "bundle_mgr_client_impl.h" +#include "dfs_listener/file_dfs_listener_stub.h" +#include "distributed_file_daemon_manager.h" +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class ConnectDfsCore final { +public: + static FsResult ConnectDfsExec(const std::string &networkId, sptr listener); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CONNECTDFS_CORE_H + diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp new file mode 100644 index 000000000..45403ca6d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_core.cpp @@ -0,0 +1,887 @@ +/* + * 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 "copy_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "datashare_helper.h" +#include "file_uri.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "ipc_skeleton.h" +#include "system_ability_definition.h" +#include "trans_listener_core.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace AppFileService::ModuleFileUri; +namespace fs = std::filesystem; +const std::string FILE_PREFIX_NAME = "file://"; +const std::string NETWORK_PARA = "?networkid="; +const string PROCEDURE_COPY_NAME = "FileFSCopy"; +const std::string MEDIALIBRARY_DATA_URI = "datashare:///media"; +const std::string MEDIA = "media"; +const int SLEEP_TIME = 100000; +constexpr int DISMATCH = 0; +constexpr int MATCH = 1; +constexpr int BUF_SIZE = 1024; +constexpr size_t MAX_SIZE = 1024 * 1024 * 4; +constexpr std::chrono::milliseconds NOTIFY_PROGRESS_DELAY(300); +std::recursive_mutex CopyCore::mutex_; +std::map> CopyCore::callbackMap_; + +static int OpenSrcFile(const string &srcPth, std::shared_ptr infos, int32_t &srcFd) +{ + Uri uri(infos->srcUri); + if (uri.GetAuthority() == MEDIA) { + std::shared_ptr dataShareHelper = nullptr; + sptr remote = new (std::nothrow) IRemoteStub(); + if (!remote) { + HILOGE("Failed to get remote object"); + return ENOMEM; + } + dataShareHelper = DataShare::DataShareHelper::Creator(remote->AsObject(), MEDIALIBRARY_DATA_URI); + if (!dataShareHelper) { + HILOGE("Failed to connect to datashare"); + return E_PERMISSION; + } + srcFd = dataShareHelper->OpenFile(uri, FsUtils::GetModeFromFlags(O_RDONLY)); + if (srcFd < 0) { + HILOGE("Open media uri by data share fail. ret = %{public}d", srcFd); + return EPERM; + } + } else { + srcFd = open(srcPth.c_str(), O_RDONLY); + if (srcFd < 0) { + HILOGE("Error opening src file descriptor. errno = %{public}d", errno); + return errno; + } + } + return ERRNO_NOERR; +} + +static int SendFileCore(std::unique_ptr srcFdg, std::unique_ptr destFdg, + std::shared_ptr infos) +{ + std::unique_ptr sendFileReq = { new (nothrow) uv_fs_t, + FsUtils::FsReqCleanup }; + if (sendFileReq == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int64_t offset = 0; + struct stat srcStat {}; + if (fstat(srcFdg->GetFD(), &srcStat) < 0) { + HILOGE("Failed to get stat of file by fd: %{public}d ,errno = %{public}d", srcFdg->GetFD(), errno); + return errno; + } + int32_t ret = 0; + int64_t size = static_cast(srcStat.st_size); + while (size >= 0) { + ret = uv_fs_sendfile(nullptr, sendFileReq.get(), destFdg->GetFD(), srcFdg->GetFD(), offset, MAX_SIZE, nullptr); + if (ret < 0) { + HILOGE("Failed to sendfile by errno : %{public}d", errno); + return errno; + } + if (infos != nullptr && infos->taskSignal != nullptr) { + if (infos->taskSignal->CheckCancelIfNeed(infos->srcPath)) { + return ECANCELED; + } + } + offset += static_cast(ret); + size -= static_cast(ret); + if (ret == 0) { + break; + } + } + if (size != 0) { + HILOGE("The execution of the sendfile task was terminated, remaining file size %{public}" PRIu64, size); + return EIO; + } + return ERRNO_NOERR; +} + +bool CopyCore::IsValidUri(const std::string &uri) +{ + return uri.find(FILE_PREFIX_NAME) == 0; +} + +bool CopyCore::ValidOperand(std::string uriStr) +{ + return IsValidUri(uriStr); +} + +bool CopyCore::IsRemoteUri(const std::string &uri) +{ + // NETWORK_PARA + return uri.find(NETWORK_PARA) != uri.npos; +} + +bool CopyCore::IsDirectory(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGE("stat failed, errno is %{public}d", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFDIR; +} + +bool CopyCore::IsFile(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGI("stat failed, errno is %{public}d, ", errno); + return false; + } + return (buf.st_mode & S_IFMT) == S_IFREG; +} + +bool CopyCore::IsMediaUri(const std::string &uriPath) +{ + Uri uri(uriPath); + string bundleName = uri.GetAuthority(); + return bundleName == MEDIA; +} + +tuple CopyCore::GetFileSize(const std::string &path) +{ + struct stat buf {}; + int ret = stat(path.c_str(), &buf); + if (ret == -1) { + HILOGI("Stat failed."); + return { errno, 0 }; + } + return { ERRNO_NOERR, buf.st_size }; +} + +int CopyCore::CheckOrCreatePath(const std::string &destPath) +{ + std::error_code errCode; + if (!filesystem::exists(destPath, errCode) && errCode.value() == ERRNO_NOERR) { + HILOGI("destPath not exist"); + auto file = open(destPath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (file < 0) { + HILOGE("Error opening file descriptor. errno = %{public}d", errno); + return errno; + } + close(file); + } else if (errCode.value() != 0) { + return errCode.value(); + } + return ERRNO_NOERR; +} + +int CopyCore::CopyFile(const string &src, const string &dest, std::shared_ptr infos) +{ + HILOGD("src = %{public}s, dest = %{public}s", GetAnonyString(src).c_str(), GetAnonyString(dest).c_str()); + int32_t srcFd = -1; + int32_t ret = OpenSrcFile(src, infos, srcFd); + if (srcFd < 0) { + return ret; + } + auto destFd = open(dest.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (destFd < 0) { + HILOGE("Error opening dest file descriptor. errno = %{public}d", errno); + close(srcFd); + return errno; + } + auto srcFdg = CreateUniquePtr(srcFd, true); + auto destFdg = CreateUniquePtr(destFd, true); + if (srcFdg == nullptr || destFdg == nullptr) { + HILOGE("Failed to request heap memory."); + close(srcFd); + close(destFd); + return ENOMEM; + } + return SendFileCore(move(srcFdg), move(destFdg), infos); +} + +int CopyCore::MakeDir(const string &path) +{ + filesystem::path destDir(path); + std::error_code errCode; + if (!filesystem::create_directory(destDir, errCode)) { + HILOGE("Failed to create directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +int CopyCore::CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos) +{ + std::error_code errCode; + if (!filesystem::exists(destPath, errCode) && errCode.value() == ERRNO_NOERR) { + int res = MakeDir(destPath); + if (res != ERRNO_NOERR) { + HILOGE("Failed to mkdir"); + return res; + } + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + uint32_t watchEvents = IN_MODIFY; + if (infos->notifyFd >= 0) { + int newWd = inotify_add_watch(infos->notifyFd, destPath.c_str(), watchEvents); + if (newWd < 0) { + HILOGE("inotify_add_watch, newWd is unvaild, newWd = %{public}d", newWd); + return errno; + } + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + auto receiveInfo = CreateSharedPtr(); + if (receiveInfo == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + receiveInfo->path = destPath; + if (iter == CopyCore::callbackMap_.end() || iter->second == nullptr) { + HILOGE("Failed to find infos, srcPath = %{public}s, destPath = %{public}s", + GetAnonyString(infos->srcPath).c_str(), GetAnonyString(infos->destPath).c_str()); + return UNKNOWN_ERR; + } + iter->second->wds.push_back({ newWd, receiveInfo }); + } + } + return RecurCopyDir(srcPath, destPath, infos); +} + +static int FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return DISMATCH; + } + return MATCH; +} + +struct NameList { + struct dirent **namelist = { nullptr }; + int direntNum = 0; +}; + +static void Deleter(struct NameList *arg) +{ + for (int i = 0; i < arg->direntNum; i++) { + free((arg->namelist)[i]); + (arg->namelist)[i] = nullptr; + } + free(arg->namelist); + arg->namelist = nullptr; + delete arg; + arg = nullptr; +} + +std::string CopyCore::GetRealPath(const std::string &path) +{ + fs::path tempPath(path); + fs::path realPath {}; + for (const auto &component : tempPath) { + if (component == ".") { + continue; + } else if (component == "..") { + realPath = realPath.parent_path(); + } else { + realPath /= component; + } + } + return realPath.string(); +} + +uint64_t CopyCore::GetDirSize(std::shared_ptr infos, std::string path) +{ + unique_ptr pNameList = { new (nothrow) struct NameList, Deleter }; + if (pNameList == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, alphasort); + pNameList->direntNum = num; + + long int size = 0; + for (int i = 0; i < num; i++) { + string dest = path + '/' + string((pNameList->namelist[i])->d_name); + if ((pNameList->namelist[i])->d_type == DT_LNK) { + continue; + } + if ((pNameList->namelist[i])->d_type == DT_DIR) { + size += static_cast(GetDirSize(infos, dest)); + } else { + struct stat st {}; + if (stat(dest.c_str(), &st) == -1) { + return size; + } + size += st.st_size; + } + } + return size; +} + +int CopyCore::RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos) +{ + unique_ptr pNameList = { new (nothrow) struct NameList, Deleter }; + if (pNameList == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(srcPath.c_str(), &(pNameList->namelist), FilterFunc, alphasort); + pNameList->direntNum = num; + + for (int i = 0; i < num; i++) { + string src = srcPath + '/' + string((pNameList->namelist[i])->d_name); + string dest = destPath + '/' + string((pNameList->namelist[i])->d_name); + if ((pNameList->namelist[i])->d_type == DT_LNK) { + continue; + } + int ret = ERRNO_NOERR; + if ((pNameList->namelist[i])->d_type == DT_DIR) { + ret = CopySubDir(src, dest, infos); + } else { + infos->filePaths.insert(dest); + ret = CopyFile(src, dest, infos); + } + if (ret != ERRNO_NOERR) { + return ret; + } + } + return ERRNO_NOERR; +} + +int CopyCore::CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos) +{ + HILOGD("CopyDirFunc in, src = %{public}s, dest = %{public}s", GetAnonyString(src).c_str(), + GetAnonyString(dest).c_str()); + size_t found = dest.find(src); + if (found != std::string::npos && found == 0) { + return EINVAL; + } + fs::path srcPath = fs::u8path(src); + std::string dirName; + if (srcPath.has_parent_path()) { + dirName = srcPath.parent_path().filename(); + } + string destStr = dest + "/" + dirName; + return CopySubDir(src, destStr, infos); +} + +int CopyCore::ExecLocal(std::shared_ptr infos, std::shared_ptr callback) +{ + if (infos->isFile) { + if (infos->srcPath == infos->destPath) { + HILOGE("The src and dest is same"); + return EINVAL; + } + int ret = CheckOrCreatePath(infos->destPath); + if (ret != ERRNO_NOERR) { + HILOGE("check or create fail, error code is %{public}d", ret); + return ret; + } + } + if (!infos->hasListener) { + return ExecCopy(infos); + } + auto ret = SubscribeLocalListener(infos, callback); + if (ret != ERRNO_NOERR) { + HILOGE("Failed to subscribe local listener, errno = %{public}d", ret); + return ret; + } + StartNotify(infos, callback); + return ExecCopy(infos); +} + +int CopyCore::SubscribeLocalListener(std::shared_ptr infos, std::shared_ptr callback) +{ + infos->notifyFd = inotify_init(); + if (infos->notifyFd < 0) { + HILOGE("Failed to init inotify, errno:%{public}d", errno); + return errno; + } + infos->eventFd = eventfd(0, EFD_CLOEXEC); + if (infos->eventFd < 0) { + HILOGE("Failed to init eventFd, errno:%{public}d", errno); + return errno; + } + callback->notifyFd = infos->notifyFd; + callback->eventFd = infos->eventFd; + int newWd = inotify_add_watch(infos->notifyFd, infos->destPath.c_str(), IN_MODIFY); + if (newWd < 0) { + auto errCode = errno; + HILOGE("Failed to add watch, errno = %{public}d, notifyFd: %{public}d, destPath: %{public}s", errno, + infos->notifyFd, infos->destPath.c_str()); + CloseNotifyFdLocked(infos, callback); + return errCode; + } + auto receiveInfo = CreateSharedPtr(); + if (receiveInfo == nullptr) { + HILOGE("Failed to request heap memory."); + inotify_rm_watch(infos->notifyFd, newWd); + CloseNotifyFdLocked(infos, callback); + return ENOMEM; + } + receiveInfo->path = infos->destPath; + callback->wds.push_back({ newWd, receiveInfo }); + if (!infos->isFile) { + callback->totalSize = GetDirSize(infos, infos->srcPath); + return ERRNO_NOERR; + } + auto [err, fileSize] = GetFileSize(infos->srcPath); + if (err == ERRNO_NOERR) { + callback->totalSize = fileSize; + } + return err; +} + +std::shared_ptr CopyCore::RegisterListener(const std::shared_ptr &infos) +{ + auto callback = CreateSharedPtr(infos->listener); + if (callback == nullptr) { + HILOGE("Failed to request heap memory."); + return nullptr; + } + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter != callbackMap_.end()) { + HILOGE("CopyCore::RegisterListener, already registered."); + return nullptr; + } + callbackMap_.insert({ *infos, callback }); + return callback; +} + +void CopyCore::UnregisterListener(std::shared_ptr fileInfos) +{ + if (fileInfos == nullptr) { + HILOGE("fileInfos is nullptr"); + return; + } + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*fileInfos); + if (iter == callbackMap_.end()) { + HILOGI("It is not be registered."); + return; + } + callbackMap_.erase(*fileInfos); +} + +void CopyCore::ReceiveComplete(std::shared_ptr entry) +{ + if (entry == nullptr) { + HILOGE("entry pointer is nullptr."); + return; + } + if (entry->callback == nullptr) { + HILOGE("entry callback pointer is nullptr."); + return; + } + auto processedSize = entry->progressSize; + if (processedSize < entry->callback->maxProgressSize) { + return; + } + entry->callback->maxProgressSize = processedSize; + auto listener = entry->callback->listener; + if (listener == nullptr) { + HILOGE("listener pointer is nullptr."); + return; + } + listener->InvokeListener(processedSize, entry->totalSize); +} + +FsUvEntry *CopyCore::GetUVEntry(std::shared_ptr infos) +{ + FsUvEntry *entry = nullptr; + { + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter == callbackMap_.end()) { + HILOGE("Failed to find callback"); + return nullptr; + } + auto callback = iter->second; + entry = new (std::nothrow) FsUvEntry(iter->second, infos); + if (entry == nullptr) { + HILOGE("entry ptr is nullptr."); + return nullptr; + } + entry->progressSize = callback->progressSize; + entry->totalSize = callback->totalSize; + } + return entry; +} + +void CopyCore::OnFileReceive(std::shared_ptr infos) +{ + std::shared_ptr entry(GetUVEntry(infos)); + if (entry == nullptr) { + HILOGE("failed to get uv entry"); + return; + } + ReceiveComplete(entry); +} + +std::shared_ptr CopyCore::GetReceivedInfo(int wd, std::shared_ptr callback) +{ + auto it = find_if(callback->wds.begin(), callback->wds.end(), [wd](const auto &item) { return item.first == wd; }); + if (it != callback->wds.end()) { + return it->second; + } + return nullptr; +} + +bool CopyCore::CheckFileValid(const std::string &filePath, std::shared_ptr infos) +{ + return infos->filePaths.count(filePath) != 0; +} + +int CopyCore::UpdateProgressSize( + const std::string &filePath, std::shared_ptr receivedInfo, std::shared_ptr callback) +{ + auto [err, fileSize] = GetFileSize(filePath); + if (err != ERRNO_NOERR) { + HILOGE("GetFileSize failed, err: %{public}d.", err); + return err; + } + auto size = fileSize; + auto iter = receivedInfo->fileList.find(filePath); + if (iter == receivedInfo->fileList.end()) { + receivedInfo->fileList.insert({ filePath, size }); + callback->progressSize += size; + } else { // file + if (size > iter->second) { + callback->progressSize += (size - iter->second); + iter->second = size; + } + } + return ERRNO_NOERR; +} + +std::shared_ptr CopyCore::GetRegisteredListener(std::shared_ptr infos) +{ + std::lock_guard lock(mutex_); + auto iter = callbackMap_.find(*infos); + if (iter == callbackMap_.end()) { + HILOGE("It is not registered."); + return nullptr; + } + return iter->second; +} + +void CopyCore::CloseNotifyFd(std::shared_ptr infos, std::shared_ptr callback) +{ + callback->closed = false; + infos->eventFd = -1; + infos->notifyFd = -1; + { + std::unique_lock lock(callback->cvLock); + callback->CloseFd(); + callback->cv.notify_one(); + } +} + +void CopyCore::CloseNotifyFdLocked(std::shared_ptr infos, std::shared_ptr callback) +{ + { + lock_guard lock(callback->readMutex); + callback->closed = true; + if (callback->reading) { + HILOGE("close while reading"); + return; + } + } + CloseNotifyFd(infos, callback); +} + +tuple CopyCore::HandleProgress( + inotify_event *event, std::shared_ptr infos, std::shared_ptr callback) +{ + if (callback == nullptr) { + return { true, EINVAL, false }; + } + auto receivedInfo = GetReceivedInfo(event->wd, callback); + if (receivedInfo == nullptr) { + return { true, EINVAL, false }; + } + std::string fileName = receivedInfo->path; + if (!infos->isFile) { // files under subdir + fileName += "/" + string(event->name); + if (!CheckFileValid(fileName, infos)) { + return { true, EINVAL, false }; + } + auto err = UpdateProgressSize(fileName, receivedInfo, callback); + if (err != ERRNO_NOERR) { + return { false, err, false }; + } + } else { + auto [err, fileSize] = GetFileSize(fileName); + if (err != ERRNO_NOERR) { + return { false, err, false }; + } + callback->progressSize = fileSize; + } + return { true, callback->errorCode, true }; +} + +void CopyCore::ReadNotifyEvent(std::shared_ptr infos) +{ + char buf[BUF_SIZE] = { 0 }; + struct inotify_event *event = nullptr; + int len = 0; + int64_t index = 0; + auto callback = GetRegisteredListener(infos); + while (infos->run && ((len = read(infos->notifyFd, &buf, sizeof(buf))) < 0) && (errno == EINTR)) { + } + while (infos->run && index < len) { + event = reinterpret_cast(buf + index); + auto [needContinue, errCode, needSend] = HandleProgress(event, infos, callback); + if (!needContinue) { + infos->exceptionCode = errCode; + return; + } + if (needContinue && !needSend) { + index += static_cast(sizeof(struct inotify_event) + event->len); + continue; + } + if (!callback || (callback->progressSize == callback->totalSize)) { + infos->run = false; + return; + } + auto currentTime = std::chrono::steady_clock::now(); + if (currentTime >= infos->notifyTime) { + OnFileReceive(infos); + infos->notifyTime = currentTime + NOTIFY_PROGRESS_DELAY; + } + index += static_cast(sizeof(struct inotify_event) + event->len); + } +} + +void CopyCore::ReadNotifyEventLocked(std::shared_ptr infos, std::shared_ptr callback) +{ + { + std::lock_guard lock(callback->readMutex); + if (callback->closed) { + HILOGE("read after close"); + return; + } + callback->reading = true; + } + ReadNotifyEvent(infos); + { + std::lock_guard lock(callback->readMutex); + callback->reading = false; + if (callback->closed) { + HILOGE("close after read"); + CloseNotifyFd(infos, callback); + return; + } + } +} + +void CopyCore::GetNotifyEvent(std::shared_ptr infos) +{ + auto callback = GetRegisteredListener(infos); + if (callback == nullptr) { + infos->exceptionCode = EINVAL; + return; + } + prctl(PR_SET_NAME, "NotifyThread"); + nfds_t nfds = 2; + struct pollfd fds[2]; + fds[0].events = 0; + fds[1].events = POLLIN; + fds[0].fd = infos->eventFd; + fds[1].fd = infos->notifyFd; + while (infos->run && infos->exceptionCode == ERRNO_NOERR && infos->eventFd != -1 && infos->notifyFd != -1) { + auto ret = poll(fds, nfds, -1); + if (ret > 0) { + if (static_cast(fds[0].revents) & POLLNVAL) { + infos->run = false; + return; + } + if (static_cast(fds[1].revents) & POLLIN) { + ReadNotifyEventLocked(infos, callback); + } + } else if (ret < 0 && errno == EINTR) { + continue; + } else { + infos->exceptionCode = errno; + return; + } + { + std::unique_lock lock(callback->cvLock); + callback->cv.wait_for( + lock, std::chrono::microseconds(SLEEP_TIME), [callback]() -> bool { return callback->notifyFd == -1; }); + } + } +} + +tuple> CopyCore::CreateFileInfos( + const std::string &srcUri, const std::string &destUri, const std::optional &options) +{ + auto infos = CreateSharedPtr(); + if (infos == nullptr) { + HILOGE("Failed to request heap memory."); + return { ENOMEM, nullptr }; + } + infos->srcUri = srcUri; + infos->destUri = destUri; + FileUri srcFileUri(infos->srcUri); + infos->srcPath = srcFileUri.GetRealPath(); + FileUri dstFileUri(infos->destUri); + infos->destPath = dstFileUri.GetPath(); + infos->srcPath = GetRealPath(infos->srcPath); + infos->destPath = GetRealPath(infos->destPath); + infos->isFile = IsMediaUri(infos->srcUri) || IsFile(infos->srcPath); + infos->notifyTime = std::chrono::steady_clock::now() + NOTIFY_PROGRESS_DELAY; + if (options.has_value()) { + auto listener = options.value().progressListener; + if (listener) { + infos->hasListener = true; + infos->listener = listener; + } + auto copySignal = options.value().copySignal; + if (copySignal) { + infos->taskSignal = copySignal->GetTaskSignal(); + } + } + + return { ERRNO_NOERR, infos }; +} + +void CopyCore::StartNotify(std::shared_ptr infos, std::shared_ptr callback) +{ + if (infos->hasListener && callback != nullptr) { + callback->notifyHandler = std::thread([infos] { GetNotifyEvent(infos); }); + } +} + +int CopyCore::ExecCopy(std::shared_ptr infos) +{ + if (infos->isFile && IsFile(infos->destPath)) { + // copyFile + return CopyFile(infos->srcPath.c_str(), infos->destPath.c_str(), infos); + } + if (!infos->isFile && IsDirectory(infos->destPath)) { + if (infos->srcPath.back() != '/') { + infos->srcPath += '/'; + } + if (infos->destPath.back() != '/') { + infos->destPath += '/'; + } + // copyDir + return CopyDirFunc(infos->srcPath.c_str(), infos->destPath.c_str(), infos); + } + return EINVAL; +} + +bool CopyCore::ValidParams(const string &src, const string &dest) +{ + auto succSrc = ValidOperand(src); + auto succDest = ValidOperand(dest); + if (!succSrc || !succDest) { + HILOGE("The first/second argument requires uri/uri"); + return false; + } + return true; +} + +void CopyCore::WaitNotifyFinished(std::shared_ptr callback) +{ + if (callback != nullptr) { + if (callback->notifyHandler.joinable()) { + callback->notifyHandler.join(); + } + } +} + +void CopyCore::CopyComplete(std::shared_ptr infos, std::shared_ptr callback) +{ + if (callback != nullptr && infos->hasListener) { + callback->progressSize = callback->totalSize; + OnFileReceive(infos); + } +} + +FsResult CopyCore::DoCopy(const string &src, const string &dest, std::optional &options) +{ + auto isValid = ValidParams(src, dest); + if (!isValid) { + return FsResult::Error(E_PARAMS); + } + + auto [errCode, infos] = CreateFileInfos(src, dest, options); + if (errCode != ERRNO_NOERR) { + return FsResult::Error(errCode); + } + + auto callback = RegisterListener(infos); + if (callback == nullptr) { + return FsResult::Error(EINVAL); + } + + if (IsRemoteUri(infos->srcUri)) { + if (infos->taskSignal != nullptr) { + infos->taskSignal->MarkRemoteTask(); + } + auto ret = TransListenerCore::CopyFileFromSoftBus(infos->srcUri, infos->destUri, infos, std::move(callback)); + UnregisterListener(infos); + if (ret != ERRNO_NOERR) { + return FsResult::Error(ret); + } else { + return FsResult::Success(); + } + } + auto result = CopyCore::ExecLocal(infos, callback); + CloseNotifyFdLocked(infos, callback); + infos->run = false; + WaitNotifyFinished(callback); + if (result != ERRNO_NOERR) { + infos->exceptionCode = result; + UnregisterListener(infos); + return FsResult::Error(infos->exceptionCode); + } + CopyComplete(infos, callback); + UnregisterListener(infos); + if (infos->exceptionCode != ERRNO_NOERR) { + return FsResult::Error(infos->exceptionCode); + } else { + return FsResult::Success(); + } +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_core.h b/interfaces/kits/js/src/mod_fs/properties/copy_core.h new file mode 100644 index 000000000..387792260 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_core.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H + +#include +#include +#include +#include +#include + +#include "bundle_mgr_client_impl.h" +#include "filemgmt_libfs.h" +#include "filemgmt_libhilog.h" +#include "fs_task_signal.h" +#include "i_progress_listener.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::AppExecFwk; +using namespace DistributedFS::ModuleTaskSignal; + +struct CopyOptions { + std::shared_ptr progressListener; + std::shared_ptr copySignal; +}; + +struct ReceiveInfo { + std::string path; // dir name + std::map fileList; // filename, proceededSize +}; + +struct FsCallbackObject { + std::shared_ptr listener = nullptr; + int32_t notifyFd = -1; + int32_t eventFd = -1; + std::vector>> wds; + uint64_t totalSize = 0; + uint64_t progressSize = 0; + uint64_t maxProgressSize = 0; + int32_t errorCode = 0; + std::thread notifyHandler; + std::mutex readMutex; + std::condition_variable cv; + std::mutex cvLock; + bool reading = false; + bool closed = false; + explicit FsCallbackObject(std::shared_ptr listener) : listener(listener) {} + + void CloseFd() + { + if (eventFd != -1) { + close(eventFd); + eventFd = -1; + } + if (notifyFd == -1) { + return; + } + for (auto item : wds) { + inotify_rm_watch(notifyFd, item.first); + } + close(notifyFd); + notifyFd = -1; + } + + ~FsCallbackObject() + { + CloseFd(); + } +}; + +struct FsFileInfos { + std::string srcUri; + std::string destUri; + std::string srcPath; + std::string destPath; + bool isFile = false; + std::chrono::steady_clock::time_point notifyTime; + int32_t notifyFd = -1; + int32_t eventFd = -1; + bool run = true; + bool hasListener = false; + std::shared_ptr listener = nullptr; + std::shared_ptr taskSignal = nullptr; + std::set filePaths; + int exceptionCode = ERRNO_NOERR; // notify copy thread or listener thread has exceptions. + bool operator==(const FsFileInfos &infos) const + { + return (srcUri == infos.srcUri && destUri == infos.destUri); + } + bool operator<(const FsFileInfos &infos) const + { + if (srcUri == infos.srcUri) { + return destUri < infos.destUri; + } + return srcUri < infos.srcUri; + } +}; + +struct FsUvEntry { + std::shared_ptr callback; + std::shared_ptr fileInfos; + uint64_t progressSize = 0; + uint64_t totalSize = 0; + FsUvEntry(const std::shared_ptr &cb, std::shared_ptr fileInfos) + : callback(cb), fileInfos(fileInfos) + { + } + explicit FsUvEntry(const std::shared_ptr &cb) : callback(cb) {} +}; + +class CopyCore final { +public: + static FsResult DoCopy(const string &src, const string &dest, std::optional &options); + +private: + // operator of params + static bool ValidOperand(std::string uriStr); + static int CheckOrCreatePath(const std::string &destPath); + static bool ValidParams(const string &src, const string &dest); + + // operator of local listener + static std::shared_ptr RegisterListener(const std::shared_ptr &infos); + static std::shared_ptr GetRegisteredListener(std::shared_ptr infos); + static void UnregisterListener(std::shared_ptr fileInfos); + static int ExecLocal(std::shared_ptr infos, std::shared_ptr callback); + static void CopyComplete(std::shared_ptr infos, std::shared_ptr callback); + static void WaitNotifyFinished(std::shared_ptr callback); + static void ReadNotifyEvent(std::shared_ptr infos); + static void ReadNotifyEventLocked(std::shared_ptr infos, std::shared_ptr callback); + static int SubscribeLocalListener(std::shared_ptr infos, std::shared_ptr callback); + static void OnFileReceive(std::shared_ptr infos); + static void GetNotifyEvent(std::shared_ptr infos); + static void StartNotify(std::shared_ptr infos, std::shared_ptr callback); + static FsUvEntry *GetUVEntry(std::shared_ptr infos); + static void ReceiveComplete(std::shared_ptr entry); + static void CloseNotifyFd(std::shared_ptr infos, std::shared_ptr callback); + static void CloseNotifyFdLocked(std::shared_ptr infos, std::shared_ptr callback); + + // operator of file + static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos); + static tuple GetFileSize(const std::string &path); + static uint64_t GetDirSize(std::shared_ptr infos, std::string path); + static int CopyFile(const string &src, const string &dest, std::shared_ptr infos); + static int MakeDir(const string &path); + static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos); + static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos); + static tuple> CreateFileInfos( + const std::string &srcUri, const std::string &destUri, const std::optional &options); + static int ExecCopy(std::shared_ptr infos); + + // operator of file size + static int UpdateProgressSize(const std::string &filePath, std::shared_ptr receivedInfo, + std::shared_ptr callback); + static tuple HandleProgress( + inotify_event *event, std::shared_ptr infos, std::shared_ptr callback); + static std::shared_ptr GetReceivedInfo(int wd, std::shared_ptr callback); + static bool CheckFileValid(const std::string &filePath, std::shared_ptr infos); + + // operator of uri or path + static bool IsValidUri(const std::string &uri); + static bool IsRemoteUri(const std::string &uri); + static bool IsDirectory(const std::string &path); + static bool IsFile(const std::string &path); + static bool IsMediaUri(const std::string &uriPath); + static std::string ConvertUriToPath(const std::string &uri); + static std::string GetRealPath(const std::string &path); + +private: + static std::recursive_mutex mutex_; + static std::map> callbackMap_; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.cpp new file mode 100644 index 000000000..b824647e3 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.cpp @@ -0,0 +1,257 @@ +/* + * 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 "copy_dir_core.h" + +#include +#include +#include +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int RecurCopyDir( + const string &srcPath, const string &destPath, const int mode, vector &errfiles); + +static bool EndWithSlash(const string &src) +{ + return src.back() == '/'; +} + +static bool AllowToCopy(const string &src, const string &dest) +{ + if (src == dest) { + HILOGE("Failed to copy file, the same path"); + return false; + } + if (EndWithSlash(src) ? dest.find(src) == 0 : dest.find(src + "/") == 0) { + HILOGE("Failed to copy file, dest is under src"); + return false; + } + if (filesystem::path(src).parent_path() == dest) { + HILOGE("Failed to copy file, src's parent path is dest"); + return false; + } + return true; +} + +static tuple ParseAndCheckOperand(const string &src, const string &dest, const optional &mode) +{ + error_code errCode; + if (!filesystem::is_directory(filesystem::status(src, errCode))) { + HILOGE("Invalid src, errCode = %{public}d", errCode.value()); + return { false, 0 }; + } + if (!filesystem::is_directory(filesystem::status(dest, errCode))) { + HILOGE("Invalid dest, errCode = %{public}d", errCode.value()); + return { false, 0 }; + } + if (!AllowToCopy(src, dest)) { + return { false, 0 }; + } + int32_t modeValue = 0; + if (mode.has_value()) { + modeValue = mode.value(); + if (modeValue < COPYMODE_MIN || modeValue > COPYMODE_MAX) { + HILOGE("Invalid mode"); + return { false, 0 }; + } + } + return { true, modeValue }; +} + +static int MakeDir(const string &path) +{ + filesystem::path destDir(path); + error_code errCode; + if (!filesystem::create_directory(destDir, errCode)) { + HILOGE("Failed to create directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +struct NameList { + struct dirent **namelist = { nullptr }; + int direntNum = 0; +}; + +static int RemoveFile(const string &destPath) +{ + filesystem::path destFile(destPath); + error_code errCode; + if (!filesystem::remove(destFile, errCode)) { + HILOGE("Failed to remove file with path, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +static void Deleter(struct NameList *arg) +{ + for (int i = 0; i < arg->direntNum; i++) { + free((arg->namelist)[i]); + (arg->namelist)[i] = nullptr; + } + free(arg->namelist); + arg->namelist = nullptr; + delete arg; + arg = nullptr; +} + +static int CopyFile(const string &src, const string &dest, const int mode) +{ + filesystem::path dstPath(dest); + error_code errCode; + if (filesystem::exists(dstPath, errCode)) { + int ret = (mode == DIRMODE_FILE_COPY_THROW_ERR) ? EEXIST : RemoveFile(dest); + if (ret) { + HILOGE("Failed to copy file due to existing destPath with throw err"); + return ret; + } + } + if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + filesystem::path srcPath(src); + if (!filesystem::copy_file(srcPath, dstPath, filesystem::copy_options::overwrite_existing, errCode)) { + HILOGE("Failed to copy file, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +static int CopySubDir( + const string &srcPath, const string &destPath, const int mode, vector &errfiles) +{ + error_code errCode; + if (!filesystem::exists(destPath, errCode) && errCode.value() == ERRNO_NOERR) { + int res = MakeDir(destPath); + if (res != ERRNO_NOERR) { + HILOGE("Failed to mkdir"); + return res; + } + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + return RecurCopyDir(srcPath, destPath, mode, errfiles); +} + +static int FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return DISMATCH; + } + return MATCH; +} + +static int RecurCopyDir( + const string &srcPath, const string &destPath, const int mode, vector &errfiles) +{ + unique_ptr pNameList = { new (nothrow) struct NameList, Deleter }; + if (pNameList == nullptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(srcPath.c_str(), &(pNameList->namelist), FilterFunc, alphasort); + if (num < 0) { + HILOGE("scandir fail errno is %{public}d", errno); + return errno; + } + pNameList->direntNum = num; + + for (int i = 0; i < num; i++) { + if ((pNameList->namelist[i])->d_type == DT_DIR) { + string srcTemp = srcPath + '/' + string((pNameList->namelist[i])->d_name); + string destTemp = destPath + '/' + string((pNameList->namelist[i])->d_name); + int res = CopySubDir(srcTemp, destTemp, mode, errfiles); + if (res == ERRNO_NOERR) { + continue; + } + return res; + } else { + string src = srcPath + '/' + string((pNameList->namelist[i])->d_name); + string dest = destPath + '/' + string((pNameList->namelist[i])->d_name); + int res = CopyFile(src, dest, mode); + if (res == EEXIST) { + errfiles.emplace_back(src, dest); + continue; + } else if (res == ERRNO_NOERR) { + continue; + } else { + HILOGE("Failed to copy file for error %{public}d", res); + return res; + } + } + } + return ERRNO_NOERR; +} + +static int CopyDirFunc(const string &src, const string &dest, const int mode, vector &errfiles) +{ + size_t found = string(src).rfind('/'); + if (found == string::npos) { + return EINVAL; + } + string dirName = string(src).substr(found); + string destStr = dest + dirName; + error_code errCode; + if (!filesystem::exists(destStr, errCode) && errCode.value() == ERRNO_NOERR) { + int res = MakeDir(destStr); + if (res != ERRNO_NOERR) { + HILOGE("Failed to mkdir"); + return res; + } + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + int res = RecurCopyDir(src, destStr, mode, errfiles); + if (!errfiles.empty() && res == ERRNO_NOERR) { + return EEXIST; + } + return res; +} + +struct CopyDirResult CopyDirCore::DoCopyDir(const string &src, const string &dest, const optional &mode) +{ + auto [succ, modeValue] = ParseAndCheckOperand(src, dest, mode); + if (!succ) { + return { FsResult::Error(EINVAL), nullopt }; + } + + vector errfiles = {}; + int ret = CopyDirFunc(src, dest, modeValue, errfiles); + if (ret == EEXIST && modeValue == DIRMODE_FILE_COPY_THROW_ERR) { + return { FsResult::Error(EEXIST), make_optional>(move(errfiles)) }; + } else if (ret) { + return { FsResult::Error(ret), nullopt }; + } + return { FsResult::Success(), nullopt }; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.h b/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.h new file mode 100644 index 000000000..e031e2a1d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_dir_core.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_DIR_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_DIR_CORE_H + +#include +#include + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +constexpr int COPYMODE_MIN = 0; +constexpr int COPYMODE_MAX = 1; +constexpr int COPYDIR_DEFAULT_PERM = 0770; + +constexpr int DISMATCH = 0; +constexpr int MATCH = 1; + +enum ModeOfCopyDir { DIRMODE_FILE_COPY_THROW_ERR = 0, DIRMODE_FILE_COPY_REPLACE }; + +struct CopyDirResult { + FsResult fsResult; + optional> errFiles; +}; + +class CopyDirCore final { +public: + static struct CopyDirResult DoCopyDir( + const string &src, const string &dest, const optional &mode = nullopt); +}; + +struct ConflictFiles { + string srcFiles; + string destFiles; + ConflictFiles(const string &src, const string &dest) : srcFiles(src), destFiles(dest) {} + ~ConflictFiles() = default; +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_DIR_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.cpp new file mode 100644 index 000000000..58be19337 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.cpp @@ -0,0 +1,93 @@ +/* + * 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 "progress_listener_ani.h" + +#include +#include "ani_helper.h" +#include "ani_signature.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "type_converter.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +void ProgressListenerAni::InvokeListener(uint64_t progressSize, uint64_t totalSize) const +{ + auto task = [this, progressSize, totalSize]() { SendCopyProgress(progressSize, totalSize); }; + AniHelper::SendEventToMainThread(task); +} + +static ani_object WrapCopyProgress(ani_env *env, uint64_t progressSize, uint64_t totalSize) +{ + auto classDesc = FS::ProgressInner::classDesc.c_str(); + ani_class cls; + if (ANI_OK != env->FindClass(classDesc, &cls)) { + HILOGE("Cannot find class %{private}s", classDesc); + return nullptr; + } + auto ctorDesc = FS::ProgressInner::ctorDesc.c_str(); + auto ctorSig = FS::ProgressInner::ctorSig.c_str(); + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, ctorDesc, ctorSig, &ctor)) { + HILOGE("Cannot find constructor method for class %{private}s", classDesc); + return nullptr; + } + + const ani_double aniProgressSize = static_cast(progressSize <= MAX_VALUE ? progressSize : 0); + const ani_double aniTotalSize = static_cast(totalSize <= MAX_VALUE ? totalSize : 0); + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj, aniProgressSize, aniTotalSize)) { + HILOGE("Create %{private}s object failed!", classDesc); + return nullptr; + } + return obj; +} + +void ProgressListenerAni::SendCopyProgress(uint64_t progressSize, uint64_t totalSize) const +{ + if (vm == nullptr) { + HILOGE("Cannot send copy progress because the vm is null."); + return; + } + if (listener == nullptr) { + HILOGE("Cannot send copy progress because the listener is null."); + return; + } + ani_env *env = AniHelper::GetThreadEnv(vm); + if (env == nullptr) { + HILOGE("Cannot send copy progress because the env is null."); + return; + } + auto evtObj = WrapCopyProgress(env, progressSize, totalSize); + if (evtObj == nullptr) { + HILOGE("Create copy progress obj failed!"); + return; + } + vector args = { static_cast(evtObj) }; + auto argc = args.size(); + ani_ref result; + auto cbObj = static_cast(listener); + auto status = env->FunctionalObject_Call(cbObj, argc, args.data(), &result); + if (status != ANI_OK) { + HILOGE("Failed to call FunctionalObject_Call, status: %{public}d", static_cast(status)); + return; + } +} + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.h b/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.h new file mode 100644 index 000000000..07894982a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/ani/progress_listener_ani.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_ANI_PROGRESS_LISTENER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_ANI_PROGRESS_LISTENER_H + +#include +#include +#include "i_progress_listener.h" + +namespace OHOS::FileManagement::ModuleFileIO::ANI { + +class ProgressListenerAni final : public IProgressListener { +public: + ProgressListenerAni(ani_vm *vm, const ani_ref &listener) : vm(vm), listener(listener) {} + void InvokeListener(uint64_t progressSize, uint64_t totalSize) const override; + +private: + void SendCopyProgress(uint64_t progressSize, uint64_t totalSize) const; + +private: + ani_vm *vm; + ani_ref listener; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::ANI +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_ANI_PROGRESS_LISTENER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/i_progress_listener.h b/interfaces/kits/js/src/mod_fs/properties/copy_listener/i_progress_listener.h new file mode 100644 index 000000000..f51f4f421 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/i_progress_listener.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_I_PROGRESS_LISTENER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_I_PROGRESS_LISTENER_H + +#include + +namespace OHOS::FileManagement::ModuleFileIO { +const uint64_t MAX_VALUE = 0x7FFFFFFFFFFFFFFF; + +class IProgressListener { +public: + virtual ~IProgressListener() = default; + virtual void InvokeListener(uint64_t progressSize, uint64_t totalSize) const = 0; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_I_PROGRESS_LISTENER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.cpp new file mode 100644 index 000000000..0b8d32b78 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.cpp @@ -0,0 +1,318 @@ +/* + * 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 "trans_listener_core.h" + +#include +#include +#include + +#include "dfs_event_dfx.h" +#include "ipc_skeleton.h" +#include "sandbox_helper.h" +#include "uri.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace OHOS::AppFileService; +using namespace AppFileService::ModuleFileUri; +const std::string NETWORK_PARA = "?networkid="; +const std::string FILE_MANAGER_AUTHORITY = "docs"; +const std::string MEDIA_AUTHORITY = "media"; +const std::string DISTRIBUTED_PATH = "/data/storage/el2/distributedfiles/"; +std::atomic TransListenerCore::getSequenceId_ = 0; + +void TransListenerCore::RmDir(const std::string &path) +{ + HILOGI("RmDirm path : %{public}s", GetAnonyString(path).c_str()); + std::filesystem::path pathName(path); + std::error_code errCode; + if (std::filesystem::exists(pathName, errCode)) { + std::filesystem::remove_all(pathName, errCode); + if (errCode.value() != 0) { + HILOGE("Failed to remove directory, error code: %{public}d", errCode.value()); + } + } else { + HILOGE("pathName is not exists, error code: %{public}d", errCode.value()); + } +} + +std::string TransListenerCore::CreateDfsCopyPath() +{ + std::random_device rd; + std::string random = std::to_string(rd()); + while (std::filesystem::exists(DISTRIBUTED_PATH + random)) { + random = std::to_string(rd()); + } + return random; +} + +int TransListenerCore::HandleCopyFailure(CopyEvent ©Event, const Storage::DistributedFile::HmdfsInfo &info, + const std::string &disSandboxPath, const std::string ¤tId) +{ + if (info.authority != FILE_MANAGER_AUTHORITY && info.authority != MEDIA_AUTHORITY) { + RmDir(disSandboxPath); + } + auto it = softbusErr2ErrCodeTable.find(copyEvent.errorCode); + if (it == softbusErr2ErrCodeTable.end()) { + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE, RadarReporter::SEND_FILE_ERROR, + RadarReporter::CONCURRENT_ID, currentId, RadarReporter::PACKAGE_NAME, to_string(copyEvent.errorCode)); + return EIO; + } + if (copyEvent.errorCode != DFS_CANCEL_SUCCESS) { + HILOGE("HandleCopyFailure failed, copyEvent.errorCode = %{public}d.", copyEvent.errorCode); + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE, RadarReporter::SEND_FILE_ERROR, + RadarReporter::CONCURRENT_ID, currentId, RadarReporter::PACKAGE_NAME, to_string(copyEvent.errorCode)); + } + return it->second; +} + +int TransListenerCore::WaitForCopyResult(TransListenerCore *transListener) +{ + if (transListener == nullptr) { + HILOGE("transListener is nullptr"); + return FAILED; + } + std::unique_lock lock(transListener->cvMutex_); + transListener->cv_.wait(lock, [&transListener]() { + return transListener->copyEvent_.copyResult == SUCCESS || transListener->copyEvent_.copyResult == FAILED; + }); + return transListener->copyEvent_.copyResult; +} + +int TransListenerCore::CopyFileFromSoftBus(const std::string &srcUri, const std::string &destUri, + std::shared_ptr fileInfos, std::shared_ptr callback) +{ + HILOGI("CopyFileFromSoftBus begin."); + std::string currentId = "CopyFile_" + std::to_string(getpid()) + "_" + std::to_string(getSequenceId_); + ++getSequenceId_; + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_SUCCESS, + RadarReporter::BIZ_STATE, RadarReporter::DFX_BEGIN, RadarReporter::PACKAGE_NAME, std::to_string(getpid()), + RadarReporter::CONCURRENT_ID, currentId); + sptr transListener = new (std::nothrow) TransListenerCore(); + if (transListener == nullptr) { + HILOGE("new trans listener failed"); + return ENOMEM; + } + transListener->callback_ = std::move(callback); + + Storage::DistributedFile::HmdfsInfo info {}; + Uri uri(destUri); + info.authority = uri.GetAuthority(); + info.sandboxPath = SandboxHelper::Decode(uri.GetPath()); + std::string disSandboxPath; + auto ret = PrepareCopySession(srcUri, destUri, transListener, info, disSandboxPath); + if (ret != ERRNO_NOERR) { + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE, + RadarReporter::PREPARE_COPY_SESSION_ERROR, RadarReporter::CONCURRENT_ID, currentId, + RadarReporter::PACKAGE_NAME, to_string(ret)); + return EIO; + } + if (fileInfos->taskSignal != nullptr) { + fileInfos->taskSignal->SetFileInfoOfRemoteTask(info.sessionName, fileInfos->srcPath); + } + auto copyResult = WaitForCopyResult(transListener); + if (copyResult == FAILED) { + return HandleCopyFailure(transListener->copyEvent_, info, disSandboxPath, currentId); + } + if (info.authority == FILE_MANAGER_AUTHORITY || info.authority == MEDIA_AUTHORITY) { + HILOGW("Public or media path not copy"); + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_SUCCESS, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::CONCURRENT_ID, currentId); + return ERRNO_NOERR; + } + + ret = CopyToSandBox(srcUri, disSandboxPath, info.sandboxPath, currentId); + RmDir(disSandboxPath); + if (ret != ERRNO_NOERR) { + HILOGE("CopyToSandBox failed, ret = %{public}d.", ret); + return EIO; + } + return ERRNO_NOERR; +} + +int32_t TransListenerCore::PrepareCopySession(const std::string &srcUri, const std::string &destUri, + TransListenerCore *transListener, Storage::DistributedFile::HmdfsInfo &info, std::string &disSandboxPath) +{ + std::string tmpDir; + if (info.authority != FILE_MANAGER_AUTHORITY && info.authority != MEDIA_AUTHORITY) { + tmpDir = CreateDfsCopyPath(); + disSandboxPath = DISTRIBUTED_PATH + tmpDir; + std::error_code errCode; + if (!std::filesystem::create_directory(disSandboxPath, errCode)) { + HILOGE("Create dir failed, error code: %{public}d", errCode.value()); + return errCode.value(); + } + + auto pos = info.sandboxPath.rfind('/'); + if (pos == std::string::npos) { + HILOGE("invalid file path"); + return EIO; + } + auto sandboxDir = info.sandboxPath.substr(0, pos); + if (std::filesystem::exists(sandboxDir, errCode)) { + info.dirExistFlag = true; + } + } + + info.copyPath = tmpDir; + auto networkId = GetNetworkIdFromUri(srcUri); + HILOGI("dfs PrepareSession begin."); + auto ret = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PrepareSession( + srcUri, destUri, networkId, transListener, info); + if (ret != ERRNO_NOERR) { + HILOGE("PrepareSession failed, ret = %{public}d.", ret); + if (info.authority != FILE_MANAGER_AUTHORITY && info.authority != MEDIA_AUTHORITY) { + RmDir(disSandboxPath); + } + return EIO; + } + return ERRNO_NOERR; +} + +int32_t TransListenerCore::CopyToSandBox(const std::string &srcUri, const std::string &disSandboxPath, + const std::string &sandboxPath, const std::string ¤tId) +{ + std::error_code errCode; + if (std::filesystem::exists(sandboxPath) && std::filesystem::is_directory(sandboxPath)) { + HILOGI("Copy dir"); + std::filesystem::copy(disSandboxPath, sandboxPath, + std::filesystem::copy_options::recursive | std::filesystem::copy_options::update_existing, errCode); + if (errCode.value() != 0) { + HILOGE("Copy dir failed: errCode: %{public}d", errCode.value()); + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE, + RadarReporter::COPY_TO_SANDBOX_ERROR, RadarReporter::CONCURRENT_ID, currentId, + RadarReporter::PACKAGE_NAME, to_string(errCode.value())); + return EIO; + } + } else { + HILOGI("Copy file."); + Uri uri(srcUri); + auto fileName = GetFileName(uri.GetPath()); + if (fileName.empty()) { + HILOGE("Get filename failed"); + RmDir(disSandboxPath); + return EIO; + } + std::filesystem::copy( + disSandboxPath + fileName, sandboxPath, std::filesystem::copy_options::update_existing, errCode); + if (errCode.value() != 0) { + HILOGE("Copy file failed: errCode: %{public}d", errCode.value()); + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE, + RadarReporter::COPY_TO_SANDBOX_ERROR, RadarReporter::CONCURRENT_ID, currentId, + RadarReporter::PACKAGE_NAME, to_string(errCode.value())); + return EIO; + } + } + HILOGI("Copy file success."); + RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_SUCCESS, + RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::CONCURRENT_ID, currentId); + return ERRNO_NOERR; +} + +std::string TransListenerCore::GetFileName(const std::string &path) +{ + auto pos = path.find_last_of('/'); + if (pos == std::string::npos) { + HILOGE("invalid path"); + return ""; + } + return SandboxHelper::Decode(path.substr(pos)); +} + +std::string TransListenerCore::GetNetworkIdFromUri(const std::string &uri) +{ + return uri.substr(uri.find(NETWORK_PARA) + NETWORK_PARA.size(), uri.size()); +} + +void TransListenerCore::CallbackComplete(std::shared_ptr entry) +{ + if (entry == nullptr) { + HILOGE("entry pointer is nullptr."); + return; + } + + if (entry->callback == nullptr) { + HILOGE("entry callback pointer is nullptr."); + return; + } + + auto listener = entry->callback->listener; + if (listener == nullptr) { + HILOGE("listener pointer is nullptr."); + return; + } + listener->InvokeListener(entry->progressSize, entry->totalSize); +} + +int32_t TransListenerCore::OnFileReceive(uint64_t totalBytes, uint64_t processedBytes) +{ + std::lock_guard lock(callbackMutex_); + if (callback_ == nullptr) { + HILOGE("Failed to parse watcher callback"); + return ENOMEM; + } + + std::shared_ptr entry = std::make_shared(callback_); + if (entry == nullptr) { + HILOGE("entry ptr is nullptr"); + return ENOMEM; + } + entry->progressSize = processedBytes; + entry->totalSize = totalBytes; + CallbackComplete(entry); + return ERRNO_NOERR; +} + +int32_t TransListenerCore::OnFinished(const std::string &sessionName) +{ + HILOGI("OnFinished"); + { + std::lock_guard lock(callbackMutex_); + callback_ = nullptr; + } + { + std::lock_guard lock(cvMutex_); + copyEvent_.copyResult = SUCCESS; + cv_.notify_all(); + } + return ERRNO_NOERR; +} + +int32_t TransListenerCore::OnFailed(const std::string &sessionName, int32_t errorCode) +{ + HILOGI("OnFailed, errorCode is %{public}d", errorCode); + { + std::lock_guard lock(callbackMutex_); + callback_ = nullptr; + } + { + std::lock_guard lock(cvMutex_); + copyEvent_.copyResult = FAILED; + copyEvent_.errorCode = errorCode; + cv_.notify_all(); + } + return ERRNO_NOERR; +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.h b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.h new file mode 100644 index 000000000..9688e7940 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener_core.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_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_TRANS_LISTENER_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_TRANS_LISTENER_CORE_H + +#include + +#include "copy_core.h" +#include "distributed_file_daemon_manager.h" +#include "file_trans_listener_stub.h" +#include "file_uri.h" +#include "hmdfs_info.h" +#include "uv.h" + +constexpr int NONE = 0; +constexpr int SUCCESS = 1; +constexpr int FAILED = 2; +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +struct CopyEvent { + int copyResult = NONE; + int32_t errorCode = 0; +}; +class TransListenerCore : public Storage::DistributedFile::FileTransListenerStub { +public: + int32_t OnFileReceive(uint64_t totalBytes, uint64_t processedBytes) override; + int32_t OnFinished(const std::string &sessionName) override; + int32_t OnFailed(const std::string &sessionName, int32_t errorCode) override; + static int CopyFileFromSoftBus(const std::string &srcUri, const std::string &destUri, + std::shared_ptr fileInfos, std::shared_ptr callback); + +private: + static std::string GetNetworkIdFromUri(const std::string &uri); + static void CallbackComplete(std::shared_ptr entry); + static void RmDir(const std::string &path); + static std::string CreateDfsCopyPath(); + static std::string GetFileName(const std::string &path); + static int32_t CopyToSandBox(const std::string &srcUri, const std::string &disSandboxPath, + const std::string &sandboxPath, const std::string ¤tId); + static int32_t PrepareCopySession(const std::string &srcUri, const std::string &destUri, + TransListenerCore *transListener, Storage::DistributedFile::HmdfsInfo &info, std::string &disSandboxPath); + static int HandleCopyFailure(CopyEvent ©Event, const Storage::DistributedFile::HmdfsInfo &info, + const std::string &disSandboxPath, const std::string ¤tId); + static int WaitForCopyResult(TransListenerCore *transListener); + static std::atomic getSequenceId_; + std::mutex cvMutex_; + std::condition_variable cv_; + CopyEvent copyEvent_; + std::mutex callbackMutex_; + std::shared_ptr callback_; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_COPY_LISTENER_TRANS_LISTENER_CORE_H diff --git a/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.cpp b/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.cpp new file mode 100644 index 000000000..d7d99779d --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.cpp @@ -0,0 +1,208 @@ +/* + * 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 "create_randomaccessfile_core.h" + +#include + +#include "file_entity.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_randomaccessfile.h" +#include "fs_utils.h" +#include "randomaccessfile_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static tuple ParseStringToFileInfo(const string &path) +{ + OHOS::DistributedFS::FDGuard sfd; + auto fdg = CreateUniquePtr(sfd, false); + if (fdg == nullptr) { + HILOGE("Failed to request heap memory."); + close(sfd); + return { false, FileInfo { false, nullptr, nullptr }, ENOMEM}; + } + size_t length = path.length() + 1; + auto chars = std::make_unique(length); + auto ret = strncpy_s(chars.get(), length, path.c_str(), length - 1); + if (ret != EOK) { + HILOGE("Copy file path failed!"); + return { false, FileInfo { false, nullptr, nullptr }, ENOMEM}; + } + return { true, FileInfo { true, move(chars), move(fdg) }, ERRNO_NOERR}; +} + +static tuple ParseFdToFileInfo(const int32_t &fd) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return { false, FileInfo { false, nullptr, nullptr }, EINVAL}; + } + auto dupFd = dup(fd); + if (dupFd < 0) { + HILOGE("Failed to get valid fd, fail reason: %{public}s, fd: %{public}d", strerror(errno), fd); + return { false, FileInfo { false, nullptr, nullptr }, EINVAL}; + } + auto fdg = CreateUniquePtr(dupFd, false); + if (fdg == nullptr) { + HILOGE("Failed to request heap memory."); + close(dupFd); + return { false, FileInfo { false, nullptr, nullptr }, ENOMEM}; + } + return { true, FileInfo { false, nullptr, move(fdg) }, ERRNO_NOERR}; +} + +static tuple ValidRafOptions(const optional &options) +{ + RandomAccessFileOptions op = options.value(); + int64_t opStart = INVALID_POS; + int64_t opEnd = INVALID_POS; + + optional startOp = op.start; + optional endOp = op.end; + + if (startOp.has_value()) { + int64_t start = 0; + start = startOp.value(); + if (start < 0) { + HILOGE("Invalid option.start, positive integer is desired"); + return {false, opStart, opEnd}; + } + opStart = start; + } + if (endOp.has_value()) { + int64_t end = 0; + end = endOp.value(); + if (end < 0) { + HILOGE("Invalid option.end, positive integer is desired"); + return {false, opStart, opEnd}; + } + opEnd = end; + } + return {true, opStart, opEnd}; +} + +static tuple ValidAndConvertFlags(const optional &mode, + const optional &options, FileInfo &fileInfo) +{ + uint32_t flags = O_RDONLY; + int64_t start = INVALID_POS; + int64_t end = INVALID_POS; + if (fileInfo.isPath && mode.has_value()) { + auto modeValue = mode.value(); + if (modeValue < 0) { + HILOGE("Invalid flags"); + return {false, flags, start, end}; + } + flags = FsUtils::ConvertFlags(static_cast(modeValue)); + } + if (options.has_value()) { + auto [succOpt, start, end] = ValidRafOptions(options); + if (!succOpt) { + HILOGE("invalid RandomAccessFile options"); + return {false, flags, start, end}; + } + } + + return {true, flags, start, end}; +} + +static FsResult InstantiateRandomAccessFile(unique_ptr fdg, + int64_t fp, + int64_t start = INVALID_POS, + int64_t end = INVALID_POS) +{ + FsResult result = FsRandomAccessFile::Constructor(); + if (!result.IsSuccess()) { + HILOGE("Failed to instantiate class"); + return FsResult::Error(EIO); + } + + const FsRandomAccessFile *objRAF = result.GetData().value(); + if (!objRAF) { + HILOGE("Cannot instantiate randomaccessfile"); + return FsResult::Error(EIO); + } + + auto *rafEntity = objRAF->GetRAFEntity(); + if (!rafEntity) { + HILOGE("Cannot instantiate randomaccessfile because of void entity"); + return FsResult::Error(EIO); + } + rafEntity->fd.swap(fdg); + rafEntity->filePointer = fp; + rafEntity->start = start; + rafEntity->end = end; + return result; +} + +FsResult CreateRandomAccessFileCore::DoCreateRandomAccessFile( + const string &path, const optional &mode, const optional &options) +{ + auto [succ, fileInfo, err] = ParseStringToFileInfo(path); + if (!succ) { + return FsResult::Error(err); + } + + auto [succFlags, flags, ignoreStart, ignoreEnd] = ValidAndConvertFlags(mode, options, fileInfo); + if (!succFlags) { + return FsResult::Error(EINVAL); + } + + unique_ptr openReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!openReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + int ret = uv_fs_open(nullptr, openReq.get(), fileInfo.path.get(), flags, S_IRUSR | + S_IWUSR | S_IRGRP | S_IWGRP, NULL); + if (ret < 0) { + return FsResult::Error(ret); + } + + fileInfo.fdg->SetFD(openReq.get()->result, false); + + if (options.has_value()) { + auto [succ, start, end] = ValidRafOptions(options); + if (succ) { + return InstantiateRandomAccessFile(move(fileInfo.fdg), 0, start, end); + } + } + return InstantiateRandomAccessFile(move(fileInfo.fdg), 0); +} + +FsResult CreateRandomAccessFileCore::DoCreateRandomAccessFile( + const int32_t &fd, const optional &options) +{ + auto [succ, fileInfo, err] = ParseFdToFileInfo(fd); + if (!succ) { + return FsResult::Error(err); + } + if (options.has_value()) { + auto [succ, start, end] = ValidRafOptions(options); + if (succ) { + return InstantiateRandomAccessFile(move(fileInfo.fdg), 0, start, end); + } + } + return InstantiateRandomAccessFile(move(fileInfo.fdg), 0); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.h b/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.h new file mode 100644 index 000000000..aa7b3a2b0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_randomaccessfile_core.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_RANDOMACCESSFILE_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_RANDOMACCESSFILE_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_file.h" +#include "fs_randomaccessfile.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +struct RandomAccessFileOptions { + optional start = nullopt; + optional end = nullopt; +}; + +class CreateRandomAccessFileCore final { +public: + static FsResult DoCreateRandomAccessFile( + const string &path, const optional &mode = nullopt, + const optional &options = nullopt); + static FsResult DoCreateRandomAccessFile( + const int32_t &fd, const optional &options = nullopt); +}; +const string PROCEDURE_CREATERAT_NAME = "FileIOCreateRandomAccessFile"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_RANDOMACCESSFILE_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/create_stream_core.cpp b/interfaces/kits/js/src/mod_fs/properties/create_stream_core.cpp new file mode 100644 index 000000000..e17d5a1ba --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_stream_core.cpp @@ -0,0 +1,44 @@ +/* + * 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 "create_stream_core.h" + +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" +#include "stream_instantiator.h" +#include "stream_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult CreateStreamCore::DoCreateStream(const std::string &path, const std::string &mode) +{ + FILE *file = fopen(path.c_str(), mode.c_str()); + if (!file) { + HILOGE("Failed to fopen file by path"); + return FsResult::Error(errno); + } + + return StreamInstantiator::InstantiateStream(move(file)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/create_stream_core.h b/interfaces/kits/js/src/mod_fs/properties/create_stream_core.h new file mode 100644 index 000000000..8c0a2aade --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/create_stream_core.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_stream.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class CreateStreamCore final { +public: + static FsResult DoCreateStream(const std::string &path, const std::string &mode); +}; + +struct AsyncCreateStreamArg { + std::shared_ptr fp { nullptr }; +}; + +const std::string PROCEDURE_CREATESTREAM_NAME = "FileIOCreateStream"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_CREATE_STREAM_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.cpp b/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.cpp new file mode 100644 index 000000000..a77a6ff26 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024 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 "file_dfs_listener_stub.h" +#include "file_dfs_listener_interface_code.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace FileManagement; +namespace { + constexpr int NO_ERROR = 0; + constexpr int E_INVAL_ARG = 1; +} + +FileDfsListenerStub::FileDfsListenerStub() +{ + opToInterfaceMap_[static_cast + (Storage::DistributedFile::FileDfsListenerInterfaceCode::FILE_DFS_LISTENER_ON_STATUS)] = + &FileDfsListenerStub::HandleOnStatus; +} + +int32_t FileDfsListenerStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, + MessageParcel &reply, + MessageOption &option) +{ + if (data.ReadInterfaceToken() != GetDescriptor()) { + return FILE_DFS_LISTENER_DESCRIPTOR_IS_EMPTY; + } + switch (code) { + case static_cast(Storage::DistributedFile::FileDfsListenerInterfaceCode::FILE_DFS_LISTENER_ON_STATUS): + return HandleOnStatus(data, reply); + default: + HILOGE("Cannot response request %{public}d: unknown tranction", code); + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } +} + +int32_t FileDfsListenerStub::HandleOnStatus(MessageParcel &data, MessageParcel &reply) +{ + std::string networkId; + if (!data.ReadString(networkId)) { + HILOGE("read networkId failed"); + return E_INVAL_ARG; + } + int32_t status; + if (!data.ReadInt32(status)) { + HILOGE("read status failed"); + return E_INVAL_ARG; + } + if (networkId.empty() || status < 0) { + HILOGE("Invalid arguments"); + return E_INVAL_ARG; + } + OnStatus(networkId, status); + return NO_ERROR; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.h b/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.h new file mode 100644 index 000000000..bafb64cad --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dfs_listener/file_dfs_listener_stub.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 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 FILEMANAGEMENT_FILE_API_FILE_DFS_LISTENER_STUB_H +#define FILEMANAGEMENT_FILE_API_FILE_DFS_LISTENER_STUB_H + +#include +#include "i_file_dfs_listener.h" +#include "iremote_stub.h" +#include "message_option.h" +#include "message_parcel.h" +#include "refbase.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class FileDfsListenerStub : public IRemoteStub { +public: + FileDfsListenerStub(); + virtual ~FileDfsListenerStub() = default; + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + using FileDfsListenerInterface = int32_t (FileDfsListenerStub::*)(MessageParcel &data, MessageParcel &reply); + std::map opToInterfaceMap_; + + int32_t HandleOnStatus(MessageParcel &data, MessageParcel &reply); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // FILEMANAGEMENT_FILE_API_FILE_DFS_LISTENER_STUB_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.cpp b/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.cpp new file mode 100644 index 000000000..92020ae37 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "filemgmt_libhilog.h" +#include "distributed_file_daemon_manager.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace fs = std::filesystem; + +FsResult DisConnectDfsCore::DisConnectDfsExec(const std::string &networkId) +{ + if (networkId == "") { + return FsResult::Error(E_PARAMS); + } + + int result = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance(). + CloseP2PConnectionEx(networkId); + if (result != ERRNO_NOERR) { + HILOGE("Fail to Closep2pconnection"); + return FsResult::Error(result); + } + return FsResult::Success(); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.h b/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.h new file mode 100644 index 000000000..0cc11a1b9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/disconnectdfs_core.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DISCONNECTDFS_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DISCONNECTDFS_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class DisConnectDfsCore final { +public: + static FsResult DisConnectDfsExec(const std::string &networkId); +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DISCONNECTDFS_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp b/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp new file mode 100644 index 000000000..716205149 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dup_core.cpp @@ -0,0 +1,65 @@ +/* + * 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 "dup_core.h" + +#include +#include +#include +#include + +#include "file_entity.h" +#include "file_instantiator.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static bool ValidFd(const int32_t &fd) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return false; + } + return true; +} + +FsResult DupCore::DoDup(const int32_t &fd) +{ + if (!ValidFd(fd)) { + return FsResult::Error(EINVAL); + } + int dstFd = dup(fd); + if (dstFd < 0) { + HILOGE("Failed to dup fd, errno: %{public}d", errno); + return FsResult::Error(errno); + } + unique_ptr readLinkReq = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!readLinkReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + string path = "/proc/self/fd/" + to_string(dstFd); + int ret = uv_fs_readlink(nullptr, readLinkReq.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to readlink fd, ret: %{public}d", ret); + return FsResult::Error(ret); + } + return FileInstantiator::InstantiateFile(dstFd, string(static_cast(readLinkReq->ptr)), false); +} +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/dup_core.h b/interfaces/kits/js/src/mod_fs/properties/dup_core.h new file mode 100644 index 000000000..074d07a8e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/dup_core.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_file.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class DupCore final { +public: + static FsResult DoDup(const int32_t &fd); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_DUP_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.cpp b/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.cpp new file mode 100644 index 000000000..38996fda0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.cpp @@ -0,0 +1,45 @@ +/* + * 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 "fdatasync_core.h" + +#include +#include +#include +#include +#include + +#include "filemgmt_libhilog.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +FsResult FDataSyncCore::DoFDataSync(const int32_t &fd) +{ + std::unique_ptr fDataSyncReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!fDataSyncReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + int ret = uv_fs_fdatasync(nullptr, fDataSyncReq.get(), fd, nullptr); + if (ret < 0) { + HILOGE("Failed to transfer data associated with file descriptor: %{public}d, ret:%{public}d", fd, ret); + return FsResult::Error(ret); + } + + return FsResult::Success(); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.h b/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.h new file mode 100644 index 000000000..5e26c9140 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdatasync_core.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDATASYNC_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDATASYNC_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class FDataSyncCore final { +public: + static FsResult DoFDataSync(const int32_t &fd); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDATASYNC_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.cpp b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.cpp new file mode 100644 index 000000000..4337cd766 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.cpp @@ -0,0 +1,49 @@ +/* + * 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 "fdopen_stream_core.h" + +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_utils.h" +#include "stream_instantiator.h" +#include "stream_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult FdopenStreamCore::DoFdopenStream(const int &fd, const string &mode) +{ + if (fd < 0) { + HILOGE("Invalid fd"); + return FsResult::Error(EINVAL); + } + + FILE *file = fdopen(fd, mode.c_str()); + if (!file) { + HILOGE("Failed to fopen file by fd"); + return FsResult::Error(errno); + } + + return StreamInstantiator::InstantiateStream(move(file)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.h b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.h new file mode 100644 index 000000000..a319480fd --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fdopen_stream_core.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_stream.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class FdopenStreamCore final { +public: + static FsResult DoFdopenStream(const int &fd, const string &mode); +}; + +struct AsyncFdopenStreamArg { + std::shared_ptr fp { nullptr }; +}; + +const std::string PROCEDURE_FDOPENSTREAM_NAME = "FileIOFdopenStream"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FDOPEN_STREAM_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fsync_core.cpp b/interfaces/kits/js/src/mod_fs/properties/fsync_core.cpp new file mode 100644 index 000000000..d902ff1f3 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fsync_core.cpp @@ -0,0 +1,42 @@ +/* + * 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 "fsync_core.h" + +#include +#include +#include + +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +FsResult FsyncCore::DoFsync(const int32_t &fd) +{ + std::unique_ptr fsyncReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!fsyncReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_fsync(nullptr, fsyncReq.get(), fd, nullptr); + if (ret < 0) { + HILOGE("Failed to transfer data associated with file descriptor: %{public}d", fd); + return FsResult::Error(ret); + } + return FsResult::Success(); +} +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/fsync_core.h b/interfaces/kits/js/src/mod_fs/properties/fsync_core.h new file mode 100644 index 000000000..ce2b66835 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/fsync_core.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FSYNC_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FSYNC_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +class FsyncCore final { +public: + static FsResult DoFsync(const int32_t &fd); +}; +const std::string PROCEDURE_FSYNC_NAME = "FileIOFsync"; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_FSYNC_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/lseek_core.cpp b/interfaces/kits/js/src/mod_fs/properties/lseek_core.cpp new file mode 100644 index 000000000..dfec873c9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/lseek_core.cpp @@ -0,0 +1,53 @@ +/* + * 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 "lseek_core.h" + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult LseekCore::DoLseek(const int32_t &fd, const int64_t &offset, + const optional &pos) +{ + if (fd < 0) { + HILOGE("Invalid fd from JS first argument"); + return FsResult::Error(EINVAL); + } + + SeekPos whence = SeekPos::START; + if (pos.has_value()) { + if (pos.value() < SeekPos::START || pos.value() > SeekPos::END) { + HILOGE("Invalid whence from JS third argument"); + return FsResult::Error(EINVAL); + } + whence = pos.value(); + } + + int64_t ret = ::Lseek(fd, offset, whence); + if (ret < 0) { + HILOGE("Failed to lseek, error:%{public}d", errno); + return FsResult::Error(errno); + } + + return FsResult::Success(ret); +} + +} // ModuleFileIO +} // FileManagement +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/lseek_core.h b/interfaces/kits/js/src/mod_fs/properties/lseek_core.h new file mode 100644 index 000000000..dd399f652 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/lseek_core.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSEEK_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSEEK_CORE_H + +#include "filemgmt_libfs.h" +#include "rust_file.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +class LseekCore final { +public: + static FsResult DoLseek(const int32_t &fd, const int64_t &offset, + const optional &pos = nullopt); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSEEK_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/lstat_core.cpp b/interfaces/kits/js/src/mod_fs/properties/lstat_core.cpp new file mode 100644 index 000000000..cef683a91 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/lstat_core.cpp @@ -0,0 +1,68 @@ +/* + * 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 "lstat_core.h" + +#include +#include + +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "stat_instantiator.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +FsResult LstatCore::DoLstat(const string &path) +{ + std::unique_ptr lstat_req = { new (std::nothrow) uv_fs_t, + FsUtils::FsReqCleanup }; + if (!lstat_req) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_lstat(nullptr, lstat_req.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to get stat of file, ret: %{public}d", ret); + return FsResult::Error(ret); + } + +#if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) + size_t length = path.length() + 1; + auto chars = std::make_unique(length); + ret = strncpy_s(chars.get(), length, path.c_str(), length - 1); + if (ret != EOK) { + HILOGE("Copy file path failed!"); + return FsResult::Error(ret); + } + struct FileInfo info = { true, move(chars), {} }; + auto arg = CreateSharedPtr(move(info)); + if (arg == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + auto stat = StatInstantiator::InstantiateStat(lstat_req->statbuf, arg); +#else + auto stat = StatInstantiator::InstantiateStat(lstat_req->statbuf); +#endif + if (stat == nullptr) { + return FsResult::Error(ENOMEM); + } + return FsResult::Success(stat); +} + +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/lstat_core.h b/interfaces/kits/js/src/mod_fs/properties/lstat_core.h new file mode 100644 index 000000000..8f95142b8 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/lstat_core.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSTAT_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSTAT_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_stat.h" +#include "fs_utils.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class LstatCore final { +public: + static FsResult DoLstat(const string &path); +}; +const std::string PROCEDURE_LSTAT_NAME = "FileIOLstat"; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_LSTAT_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.cpp b/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.cpp new file mode 100644 index 000000000..487f35c69 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.cpp @@ -0,0 +1,44 @@ +/* + * 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_core.h" + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult MkdtempCore::DoMkdtemp(const string &path) +{ + unique_ptr mkdtempReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!mkdtempReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_mkdtemp(nullptr, mkdtempReq.get(), const_cast(path.c_str()), nullptr); + if (ret < 0) { + HILOGE("Failed to create a temporary directory with path"); + return FsResult::Error(ret); + } + + return FsResult::Success(move(mkdtempReq->path)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.h b/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.h new file mode 100644 index 000000000..df936597f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/mkdtemp_core.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDTEMP_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDTEMP_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class MkdtempCore final { +public: + static FsResult DoMkdtemp(const std::string &path); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MKDTEMP_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/movedir_core.cpp b/interfaces/kits/js/src/mod_fs/properties/movedir_core.cpp new file mode 100644 index 000000000..f882c1aa2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/movedir_core.cpp @@ -0,0 +1,302 @@ +/* + * 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 "movedir_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int RecurMoveDir(const string &srcPath, const string &destPath, const int mode, + deque &errfiles); + +static tuple JudgeExistAndEmpty(const string &path) +{ + std::error_code errCode; + filesystem::path pathName(path); + if (filesystem::exists(pathName, errCode)) { + if (filesystem::is_empty(pathName, errCode)) { + return { true, true }; + } + return { true, false }; + } + return { false, false }; +} + +static int RmDirectory(const string &path) +{ + filesystem::path pathName(path); + std::error_code errCode; + if (filesystem::exists(pathName, errCode)) { + std::error_code errCode; + (void)filesystem::remove_all(pathName, errCode); + if (errCode.value() != 0) { + HILOGE("Failed to remove directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +static int RemovePath(const string& pathStr) +{ + filesystem::path pathTarget(pathStr); + std::error_code errCode; + if (!filesystem::remove(pathTarget, errCode)) { + HILOGE("Failed to remove file or directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +static int CopyAndDeleteFile(const string &src, const string &dest) +{ + filesystem::path dstPath(dest); + std::error_code errCode; + if (filesystem::exists(dstPath, errCode)) { + int removeRes = RemovePath(dest); + if (removeRes != 0) { + HILOGE("Failed to remove dest file"); + return removeRes; + } + } + filesystem::path srcPath(src); + if (!filesystem::copy_file(srcPath, dstPath, filesystem::copy_options::overwrite_existing, errCode)) { + HILOGE("Failed to copy file, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return RemovePath(src); +} + +static int RenameFile(const string &src, const string &dest, const int mode, deque &errfiles) +{ + filesystem::path dstPath(dest); + std::error_code errCode; + if (filesystem::exists(dstPath, errCode)) { + if (filesystem::is_directory(dstPath, errCode)) { + errfiles.emplace_front(src, dest); + return ERRNO_NOERR; + } + if (mode == DIRMODE_FILE_THROW_ERR) { + errfiles.emplace_back(src, dest); + return ERRNO_NOERR; + } + } + if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists or is_directory fail, errcode is %{public}d", errCode.value()); + } + filesystem::path srcPath(src); + filesystem::rename(srcPath, dstPath, errCode); + if (errCode.value() == EXDEV) { + HILOGD("Failed to rename file due to EXDEV"); + return CopyAndDeleteFile(src, dest); + } + return errCode.value(); +} + +static int32_t FilterFunc(const struct dirent *filename) +{ + if (string_view(filename->d_name) == "." || string_view(filename->d_name) == "..") { + return FILE_DISMATCH; + } + return FILE_MATCH; +} + +static int RenameDir(const string &src, const string &dest, const int mode, deque &errfiles) +{ + filesystem::path destPath(dest); + std::error_code errCode; + if (filesystem::exists(destPath, errCode)) { + return RecurMoveDir(src, dest, mode, errfiles); + } else if (errCode.value() != ERRNO_NOERR) { + HILOGE("fs exists fail, errcode is %{public}d", errCode.value()); + return errCode.value(); + } + filesystem::path srcPath(src); + filesystem::rename(srcPath, destPath, errCode); + if (errCode.value() == EXDEV) { + HILOGD("Failed to rename file due to EXDEV"); + if (!filesystem::create_directory(destPath, errCode)) { + HILOGE("Failed to create directory, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return RecurMoveDir(src, dest, mode, errfiles); + } + if (errCode.value() != 0) { + HILOGE("Failed to rename file, error code: %{public}d", errCode.value()); + return errCode.value(); + } + return ERRNO_NOERR; +} + +struct NameListArg { + struct dirent** namelist; + int num; +}; + +static void Deleter(struct NameListArg *arg) +{ + for (int i = 0; i < arg->num; i++) { + free((arg->namelist)[i]); + (arg->namelist)[i] = nullptr; + } + free(arg->namelist); + arg->namelist = nullptr; + delete arg; + arg = nullptr; +} + +static int RecurMoveDir(const string &srcPath, const string &destPath, const int mode, + deque &errfiles) +{ + filesystem::path dpath(destPath); + std::error_code errCode; + if (!filesystem::is_directory(dpath, errCode)) { + errfiles.emplace_front(srcPath, destPath); + return ERRNO_NOERR; + } + + unique_ptr ptr = {new struct NameListArg, Deleter}; + if (!ptr) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + int num = scandir(srcPath.c_str(), &(ptr->namelist), FilterFunc, alphasort); + ptr->num = num; + + for (int i = 0; i < num; i++) { + if ((ptr->namelist[i])->d_type == DT_DIR) { + string srcTemp = srcPath + '/' + string((ptr->namelist[i])->d_name); + string destTemp = destPath + '/' + string((ptr->namelist[i])->d_name); + size_t size = errfiles.size(); + int res = RenameDir(srcTemp, destTemp, mode, errfiles); + if (res != ERRNO_NOERR) { + return res; + } + if (size != errfiles.size()) { + continue; + } + res = RemovePath(srcTemp); + if (res) { + return res; + } + } else { + string src = srcPath + '/' + string((ptr->namelist[i])->d_name); + string dest = destPath + '/' + string((ptr->namelist[i])->d_name); + int res = RenameFile(src, dest, mode, errfiles); + if (res != ERRNO_NOERR) { + HILOGE("Failed to rename file for error %{public}d", res); + return res; + } + } + } + return ERRNO_NOERR; +} + +static int MoveDirFunc(const string &src, const string &dest, const int mode, deque &errfiles) +{ + size_t found = string(src).rfind('/'); + if (found == std::string::npos) { + return EINVAL; + } + string dirName = string(src).substr(found); + string destStr = dest + dirName; + auto [destStrExist, destStrEmpty] = JudgeExistAndEmpty(destStr); + if (destStrExist && !destStrEmpty) { + if (mode == DIRMODE_DIRECTORY_REPLACE) { + int removeRes = RmDirectory(destStr); + if (removeRes) { + HILOGE("Failed to remove dest directory in DIRMODE_DIRECTORY_REPLACE"); + return removeRes; + } + } + if (mode == DIRMODE_DIRECTORY_THROW_ERR) { + HILOGE("Failed to move directory in DIRMODE_DIRECTORY_THROW_ERR"); + return ENOTEMPTY; + } + } + int res = RenameDir(src, destStr, mode, errfiles); + if (res == ERRNO_NOERR) { + if (!errfiles.empty()) { + HILOGE("Failed to movedir with some conflicted files"); + return EEXIST; + } + int removeRes = RmDirectory(src); + if (removeRes) { + HILOGE("Failed to remove src directory"); + return removeRes; + } + } + return res; +} + +static tuple ValidMoveDirArg( + const string &src, const string &dest, optional mode) +{ + std::error_code errCode; + if (!filesystem::is_directory(filesystem::status(src.c_str(), errCode))) { + HILOGE("Invalid src, errCode = %{public}d", errCode.value()); + return { false, 0 }; + } + if (!filesystem::is_directory(filesystem::status(dest.c_str(), errCode))) { + HILOGE("Invalid dest,errCode = %{public}d", errCode.value()); + return { false, 0 }; + } + int modeType = 0; + if (mode.has_value()) { + modeType = mode.value(); + if (modeType < DIRMODE_MIN || modeType > DIRMODE_MAX) { + HILOGE("Invalid mode"); + return { false, 0 }; + } + } + return { true, modeType }; +} + +MoveDirResult MoveDirCore::DoMoveDir( + const string &src, const string &dest, optional modeType) +{ + auto [succ, mode] = ValidMoveDirArg(src, dest, modeType); + if (!succ) { + return { FsResult::Error(EINVAL), nullopt }; + } + deque errfiles = {}; + int ret = MoveDirFunc(src, dest, mode, errfiles); + if (ret == EEXIST) { + return { FsResult::Error(EEXIST), optional> { errfiles } }; + } else if (ret) { + return { FsResult::Error(ret), nullopt }; + } + return { FsResult::Success(), nullopt }; +} + +} // ModuleFileIO +} // FileManagement +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/movedir_core.h b/interfaces/kits/js/src/mod_fs/properties/movedir_core.h new file mode 100755 index 000000000..f10eaa532 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/movedir_core.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MOVEDIR_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MOVEDIR_CORE_H + +#include +#include + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +constexpr int DIRMODE_MIN = 0; +constexpr int DIRMODE_MAX = 3; + +constexpr int FILE_DISMATCH = 0; +constexpr int FILE_MATCH = 1; +constexpr int MOVEDIR_DEFAULT_PERM = 0770; + +enum ModeOfMoveDir { + DIRMODE_DIRECTORY_THROW_ERR = 0, + DIRMODE_FILE_THROW_ERR, + DIRMODE_FILE_REPLACE, + DIRMODE_DIRECTORY_REPLACE +}; + +struct ErrFiles { + std::string srcFiles; + std::string destFiles; + ErrFiles(const std::string& src, const std::string& dest) : srcFiles(src), destFiles(dest) {} + ~ErrFiles() = default; +}; + +struct MoveDirResult { + FsResult fsResult; + optional> errFiles; +}; + +class MoveDirCore final { +public: + static MoveDirResult DoMoveDir( + const std::string &src, const std::string &dest, std::optional mode = std::nullopt); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_MOVEDIR_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_lines_core.cpp b/interfaces/kits/js/src/mod_fs/properties/read_lines_core.cpp new file mode 100644 index 000000000..1f9869151 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_lines_core.cpp @@ -0,0 +1,106 @@ +/* + * 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_lines_core.h" + +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "rust_file.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static int CheckOptionArg(Options option) +{ + auto encoding = option.encoding; + if (encoding != "utf-8") { + return EINVAL; + } + + return ERRNO_NOERR; +} + +static int GetFileSize(const string &path, int64_t &offset) +{ + std::unique_ptr readLinesReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!readLinesReq) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + + int ret = uv_fs_stat(nullptr, readLinesReq.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to get file stat by path"); + return ret; + } + + offset = static_cast(readLinesReq->statbuf.st_size); + return ERRNO_NOERR; +} + +static FsResult InstantiateReaderIterator(void *iterator, int64_t offset) +{ + if (iterator == nullptr) { + HILOGE("Invalid argument iterator"); + return FsResult::Error(EINVAL); + } + + auto readeriterator = FsReaderIterator::Constructor(); + if (!readeriterator.IsSuccess()) { + HILOGE("Failed to instantiate class ReaderIterator"); + return FsResult::Error(UNKNOWN_ERR); + } + + auto readerIteratorEntity = readeriterator.GetData().value()->GetReaderIteratorEntity(); + if (!readerIteratorEntity) { + HILOGE("Failed to get readerIteratorEntity"); + return FsResult::Error(UNKNOWN_ERR); + } + readerIteratorEntity->iterator = iterator; + readerIteratorEntity->offset = offset; + return FsResult::Success(readeriterator.GetData().value()); +} + +FsResult ReadLinesCore::DoReadLines(const string &path, optional option) +{ + if (option.has_value()) { + int ret = CheckOptionArg(option.value()); + if (ret) { + HILOGE("Invalid option.encoding parameter"); + return FsResult::Error(ret); + } + } + + auto iterator = ::ReaderIterator(path.c_str()); + if (iterator == nullptr) { + HILOGE("Failed to read lines of the file, error: %{public}d", errno); + return FsResult::Error(errno); + } + + int64_t offset = 0; + int ret = GetFileSize(path, offset); + if (ret != 0) { + HILOGE("Failed to get size of the file"); + return FsResult::Error(ret); + } + return InstantiateReaderIterator(iterator, offset); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_lines_core.h b/interfaces/kits/js/src/mod_fs/properties/read_lines_core.h new file mode 100644 index 000000000..67cae2c52 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_lines_core.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_CORE_H + +#include + +#include "filemgmt_libfs.h" +#include "fs_reader_iterator.h" +#include "fs_utils.h" +#include "readeriterator_entity.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +struct Options final { + std::string encoding; +}; + +class ReadLinesCore final { +public: + static FsResult DoReadLines( + const std::string &path, std::optional option = std::nullopt); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rename_core.cpp b/interfaces/kits/js/src/mod_fs/properties/rename_core.cpp new file mode 100644 index 000000000..1edff30a2 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rename_core.cpp @@ -0,0 +1,46 @@ +/* + * 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_core.h" + +#include +#include +#include + +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult RenameCore::DoRename(const string &src, const string &dest) +{ + std::unique_ptr renameReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!renameReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_rename(nullptr, renameReq.get(), src.c_str(), dest.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to rename file with path"); + return FsResult::Error(ret); + } + return FsResult::Success(); +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/rename_core.h b/interfaces/kits/js/src/mod_fs/properties/rename_core.h new file mode 100644 index 000000000..0eded1168 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/rename_core.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RENAME_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RENAME_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +class RenameCore { +public: + static FsResult DoRename(const string &src, const string &dest); +}; + +const string PROCEDURE_RENAME_NAME = "FileIORename"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_RENAME_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/symlink_core.cpp b/interfaces/kits/js/src/mod_fs/properties/symlink_core.cpp new file mode 100644 index 000000000..217f429fd --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/symlink_core.cpp @@ -0,0 +1,47 @@ +/* + * 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 "symlink_core.h" + +#include +#include +#include +#include + +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult SymlinkCore::DoSymlink(const string &target, const string &srcPath) +{ + std::unique_ptr symlinkReq = { new uv_fs_t, FsUtils::FsReqCleanup }; + if (!symlinkReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_symlink(nullptr, symlinkReq.get(), target.c_str(), srcPath.c_str(), 0, nullptr); + if (ret < 0) { + HILOGE("Failed to create a link for old path"); + return FsResult::Error(ret); + } + return FsResult::Success(); +} +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/symlink_core.h b/interfaces/kits/js/src/mod_fs/properties/symlink_core.h new file mode 100644 index 000000000..223c8b683 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/symlink_core.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_SYMLINK_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_SYMLINK_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class SymlinkCore final { +public: + static FsResult DoSymlink(const string &target, const string &srcPath); +}; +const std::string PROCEDURE_RMDIRENT_NAME = "FileIOSymLink"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_SYMLINK_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/utimes_core.cpp b/interfaces/kits/js/src/mod_fs/properties/utimes_core.cpp new file mode 100644 index 000000000..4b517167b --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/utimes_core.cpp @@ -0,0 +1,64 @@ +/* + * 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 "utimes_core.h" + +#include + +#include "filemgmt_libhilog.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +FsResult UtimesCore::DoUtimes(const string &path, const double mtime) +{ + if (mtime < 0) { + HILOGE("Invalid mtime"); + return FsResult::Error(EINVAL); + } + std::unique_ptr statReq = { + new (std::nothrow) uv_fs_t, FsUtils::FsReqCleanup }; + if (!statReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + int ret = uv_fs_stat(nullptr, statReq.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to get stat of the file by path"); + return FsResult::Error(ret); + } + + std::unique_ptr utimesReq = { + new uv_fs_t, FsUtils::FsReqCleanup }; + if (!utimesReq) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + + double atime = static_cast(statReq->statbuf.st_atim.tv_sec) + + static_cast(statReq->statbuf.st_atim.tv_nsec) / NS; + ret = uv_fs_utime(nullptr, utimesReq.get(), path.c_str(), atime, mtime / MS, nullptr); + if (ret < 0) { + HILOGE("Failed to chang mtime of the file for %{public}d", ret); + return FsResult::Error(ret); + } + return FsResult::Success(); +} +} // ModuleFileIO +} // FileManagement +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/utimes_core.h b/interfaces/kits/js/src/mod_fs/properties/utimes_core.h new file mode 100644 index 000000000..86fe8c4fd --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/utimes_core.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UTIMES_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UTIMES_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +class UtimesCore final { +public: + static FsResult DoUtimes(const string &path, const double mtime); +}; +const std::string PROCEDURE_RMDIRENT_NAME = "FileIOUtimes"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_UTIMES_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp new file mode 100644 index 000000000..1ea4a713a --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "watcher_core.h" + +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +static FsResult InstantiateWatcher() +{ + if (FsFileWatcher::GetInstance().GetNotifyId() < 0 && !FsFileWatcher::GetInstance().InitNotify()) { + HILOGE("Failed to get notifyId or initnotify fail"); + return FsResult::Error(errno); + } + FsResult result = FsWatcher::Constructor(); + if (!result.IsSuccess()) { + HILOGE("Failed to instantiate watcher"); + return FsResult::Error(EIO); + } + return result; +} + +shared_ptr ToWatcherInfo( + const string &path, const int32_t events, shared_ptr callback, int32_t &errCode) +{ + if (events <= 0 || !FsFileWatcher::GetInstance().CheckEventValid(events)) { + HILOGE("Failed to get watcher event."); + errCode = EINVAL; + return nullptr; + } + + if (!callback) { + HILOGE("Failed to get callback"); + errCode = EINVAL; + return nullptr; + } + + auto info = CreateSharedPtr(callback); + if (info == nullptr) { + HILOGE("Failed to request heap memory."); + errCode = ENOMEM; + return nullptr; + } + + info->events = static_cast(events); + info->fileName = move(path); + return info; +} + +FsResult WatcherCore::DoCreateWatcher( + const string &path, const int32_t events, shared_ptr callback) +{ + int errCode = 0; + auto info = ToWatcherInfo(path, events, callback, errCode); + if (errCode != 0) { + HILOGE("Failed to parse param"); + return FsResult::Error(errCode); + } + + auto result = InstantiateWatcher(); + if (!result.IsSuccess()) { + return result; + } + + const FsWatcher *objWatcher = result.GetData().value(); + if (!objWatcher) { + HILOGE("Failed to get fsWatcher"); + return FsResult::Error(EIO); + } + + auto *watchEntity = objWatcher->GetWatchEntity(); + if (!watchEntity) { + HILOGE("Failed to get watchEntity."); + delete objWatcher; + objWatcher = nullptr; + return FsResult::Error(EIO); + } + + watchEntity->data_ = info; + + bool ret = FsFileWatcher::GetInstance().AddWatcherInfo(info); + if (!ret) { + HILOGE("Failed to add watcher info."); + return FsResult::Error(EINVAL); + } + return result; +} +} // namespace OHOS::FileManagement::ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/properties/watcher_core.h b/interfaces/kits/js/src/mod_fs/properties/watcher_core.h new file mode 100644 index 000000000..4a303dbcb --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/watcher_core.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_WATCHER_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_WATCHER_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_watch_entity.h" +#include "fs_watcher.h" + +namespace OHOS::FileManagement::ModuleFileIO { + +class WatcherCore final { +public: + static FsResult DoCreateWatcher( + const std::string &path, const int32_t events, std::shared_ptr callback); +}; + +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_WATCHER_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/xattr_core.cpp b/interfaces/kits/js/src/mod_fs/properties/xattr_core.cpp new file mode 100644 index 000000000..ba22e42c7 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/xattr_core.cpp @@ -0,0 +1,87 @@ +/* + * 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 "xattr_core.h" + +#include +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +constexpr size_t MAX_XATTR_SIZE = 4096; + +static bool IsIllegalXattr(const char *key, const char *value) +{ + bool isIllegalKey = strnlen(key, MAX_XATTR_SIZE + 1) > MAX_XATTR_SIZE; + if (isIllegalKey) { + HILOGE("key is too long"); + } + bool isIllegalValue = strnlen(value, MAX_XATTR_SIZE + 1) > MAX_XATTR_SIZE; + if (isIllegalValue) { + HILOGE("value is too long"); + } + return isIllegalKey || isIllegalValue; +} + +static int32_t GetXattrCore(const char *path, const char *key, std::shared_ptr result) +{ + ssize_t xAttrSize = getxattr(path, key, nullptr, 0); + if (xAttrSize == -1 || xAttrSize == 0) { + *result = ""; + return ERRNO_NOERR; + } + auto xattrValue = CreateUniquePtr(static_cast(xAttrSize) + 1); + xAttrSize = getxattr(path, key, xattrValue.get(), static_cast(xAttrSize)); + if (xAttrSize == -1) { + return errno; + } + xattrValue[xAttrSize] = '\0'; + *result = std::string(xattrValue.get()); + return ERRNO_NOERR; +} + +FsResult XattrCore::DoSetXattr(const string &path, const string &key, const string &value) +{ + if (IsIllegalXattr(key.c_str(), value.c_str())) { + HILOGE("Invalid xattr value"); + return FsResult::Error(EINVAL); + } + if (setxattr(path.c_str(), key.c_str(), value.c_str(), strnlen(value.c_str(), MAX_XATTR_SIZE), 0) < 0) { + HILOGE("setxattr fail, errno is %{public}d", errno); + return FsResult::Error(errno); + } + return FsResult::Success(); +} + +FsResult XattrCore::DoGetXattr(const string &path, const string &key) +{ + auto result = make_shared(); + int32_t ret = GetXattrCore(path.c_str(), key.c_str(), result); + if (ret != ERRNO_NOERR) { + HILOGE("Invalid getxattr"); + return FsResult::Error(ret); + } + return FsResult::Success(move(*result)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/xattr_core.h b/interfaces/kits/js/src/mod_fs/properties/xattr_core.h new file mode 100644 index 000000000..71ca376e9 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/xattr_core.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_XATTR_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_XATTR_CORE_H + +#include "filemgmt_libfs.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +class XattrCore final { +public: + static FsResult DoSetXattr(const string &path, const string &key, const string &value); + static FsResult DoGetXattr(const string &path, const string &key); +}; + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_XATTR_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp index 5ab549948..9f8f7b08f 100644 --- a/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp +++ b/interfaces/kits/js/src/mod_hash/ani/bind_function_class.cpp @@ -17,6 +17,7 @@ #include "ani_signature.h" #include "bind_function.h" #include "hash_ani.h" +#include "hashstream_ani.h" using namespace OHOS::FileManagement::ModuleFileIO::ANI; using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; @@ -30,6 +31,19 @@ static ani_status BindStaticMethods(ani_env *env) return BindClass(env, classDesc, methods); } +static ani_status BindHashStreamMethods(ani_env *env) +{ + auto classDesc = HASH::HashStreamImpl::classDesc.c_str(); + auto ctorDesc = HASH::HashStreamImpl::ctorDesc.c_str(); + auto ctorSig = HASH::HashStreamImpl::ctorSig.c_str(); + std::array methods = { + ani_native_function { "digest", nullptr, reinterpret_cast(HashStreamAni::Digest) }, + ani_native_function { "update", nullptr, reinterpret_cast(HashStreamAni::Update) }, + ani_native_function { ctorDesc, ctorSig, reinterpret_cast(HashStreamAni::Constructor) }, + }; + return BindClass(env, classDesc, methods); +} + ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) { if (vm == nullptr) { @@ -55,6 +69,12 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) return status; }; + status = BindHashStreamMethods(env); + if (status != ANI_OK) { + HILOGE("Cannot bind native static methods for hashstream!"); + return status; + }; + *result = ANI_VERSION_1; return ANI_OK; -} \ No newline at end of file +} diff --git a/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets index 7b825ee14..c9b4d5840 100644 --- a/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets +++ b/interfaces/kits/js/src/mod_hash/ani/ets/@ohos.file.hash.ets @@ -14,7 +14,7 @@ */ import { BusinessError, AsyncCallback } from '@ohos.base'; -// import stream from '@ohos.util.stream'; +import stream from '@ohos.util.stream'; export default namespace hash { export function hash(path: string, algorithm: string): Promise { @@ -23,8 +23,8 @@ export default namespace hash { promise.then((ret: NullishType): void => { let res = ret as string; resolve(res); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -36,51 +36,63 @@ export default namespace hash { e.code = 0; let res = ret as string; callback(e, res); - }).catch((e: BusinessError): void => { - callback(e, ""); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); }); } - // export function createHash(algorithm: string): HashStream { - // return new HashStream(algorithm); - // } - - // export class HashStream extends stream.Transform { - // hs: hash.HashStream; - // hashBuf?: ArrayBuffer; - - // constructor(algorithm: string) { - // super(); - // this.hs = new hash.HashStream(algorithm); - // } - - // digest(): string { - // return this.hs.digest(); - // } - - // update(data: ArrayBuffer): void { - // this.hs.update(data); - // } - - // doTransform(chunk: string, encoding: string, callback: () => void): void { - // let charCodes: number[] = []; - // for (let i = 0; i < chunk.length; i++) { - // charCodes = [...charCodes, chunk.charCodeAt(i)]; - // } - // const buf = new Uint8Array(charCodes).buffer; - // this.hs.update((buf as ArrayBuffer)); - // this.push(chunk); - // callback(); - // } - - // doWrite(chunk: string | Uint8Array, encoding: string, callback: () => void): void { - // callback(); - // } - - // doFlush(callback: () => void): void { - // callback(); - // } - // } + export function createHash(algorithm: string): HashStream { + return new HashStream(algorithm); + } + + export class HashStream extends stream.Transform { + hs: HashStreamImpl; + hashBuf?: ArrayBuffer; + + constructor(algorithm: string) { + super(); + this.hs = new HashStreamImpl(algorithm); + } + + digest(): string { + return this.hs.digest(); + } + + update(data: ArrayBuffer): void { + this.hs.update(data); + } + + doTransform(chunk: string, encoding: string, callback: () => void): void { + let charCodes: number[] = []; + for (let i = 0; i < chunk.length; i++) { + charCodes = [...charCodes, chunk.charCodeAt(i)]; + } + const buf = new Uint8Array(charCodes).buffer; + this.hs.update((buf as ArrayBuffer)); + this.push(chunk); + callback(); + } + + doWrite(chunk: string | Uint8Array, encoding: string, callback: () => void): void { + callback(); + } + + doFlush(callback: () => void): void { + callback(); + } + } +} + +export class HashStreamImpl extends stream.Transform { + + static { + loadLibrary("ani_file_hash"); + } + private nativePtr: long = 0; + + native constructor(alg: string); + native digest(): string; + native update(data: ArrayBuffer): void; } class HashImpl { diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp new file mode 100644 index 000000000..49079f114 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.cpp @@ -0,0 +1,123 @@ +/* + * 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 "hashstream_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "hs_hashstream.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { +namespace fs = std::filesystem; +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; + +HsHashStream *Unwrap(ani_env *env, ani_object object) +{ + ani_long nativePtr; + auto ret = env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr); + if (ret != ANI_OK) { + HILOGE("Unwrap hashstream err: %{private}d", ret); + return nullptr; + } + uintptr_t ptrValue = static_cast(nativePtr); + HsHashStream *hashStream = reinterpret_cast(ptrValue); + return hashStream; +} + +void HashStreamAni::Update(ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buffer) +{ + auto hashStream = Unwrap(env, object); + if (hashStream == nullptr) { + HILOGE("Cannot unwrap hashStream!"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto [succ, arrayBuffer] = TypeConverter::ToArrayBuffer(env, buffer); + if (!succ) { + HILOGE("illegal array buffer"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = hashStream->Update(arrayBuffer); + if (!ret.IsSuccess()) { + HILOGE("Cannot Update!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } +} + +ani_string HashStreamAni::Digest(ani_env *env, [[maybe_unused]] ani_object object) +{ + auto hashStream = Unwrap(env, object); + if (hashStream == nullptr) { + HILOGE("Cannot unwrap hashStream!"); + ErrorHandler::Throw(env, EINVAL); + return nullptr; + } + + auto ret = hashStream->Digest(); + if (!ret.IsSuccess()) { + HILOGE("Cannot Digest!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return nullptr; + } + + const auto &res = ret.GetData().value(); + auto [succ, result] = TypeConverter::ToAniString(env, res); + if (!succ) { + HILOGE("Convert result to ani string failed"); + ErrorHandler::Throw(env, UNKNOWN_ERR); + return nullptr; + } + return result; +} + +void HashStreamAni::Constructor(ani_env *env, ani_object obj, ani_string alg) +{ + auto [succ, algorithm] = TypeConverter::ToUTF8String(env, alg); + if (!succ) { + HILOGE("Invalid alg"); + ErrorHandler::Throw(env, EINVAL); + return; + } + + auto ret = HsHashStream::Constructor(algorithm); + if (!ret.IsSuccess()) { + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return; + } + + if (ANI_OK != + env->Object_SetFieldByName_Long(obj, "nativePtr", reinterpret_cast(ret.GetData().value()))) { + HILOGE("Failed to wrap entity for obj HashStream"); + ErrorHandler::Throw(env, EIO); + return; + } +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.h b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.h new file mode 100644 index 000000000..c5f98974e --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/ani/hashstream_ani.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_HASH_HASHSTREAM_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_HASHSTREAM_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class HashStreamAni final { +public: + static void Constructor(ani_env *env, ani_object obj, ani_string alg); + static ani_string Digest(ani_env *env, [[maybe_unused]] ani_object object); + static void Update(ani_env *env, [[maybe_unused]] ani_object object, ani_arraybuffer buffer); +}; +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_HASHSTREAM_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.cpp b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.cpp new file mode 100644 index 000000000..b03eb2b15 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.cpp @@ -0,0 +1,161 @@ +/* + * 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 "hs_hashstream.h" + +#include +#include + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static HASH_ALGORITHM_TYPE GetHashAlgorithm(const string &alg) +{ + return (algorithmMaps.find(alg) != algorithmMaps.end()) ? algorithmMaps.at(alg) : HASH_ALGORITHM_TYPE_UNSUPPORTED; +} + +static string HashFinal(const unique_ptr &hashBuf, size_t hashLen) +{ + stringstream ss; + for (size_t i = 0; i < hashLen; ++i) { + const int hexPerByte = 2; + ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex + << static_cast(hashBuf[i]); + } + + return ss.str(); +} + +tuple HsHashStream::GetHsEntity() +{ + if (!entity) { + return { false, nullptr }; + } + return { true, entity.get() }; +} + +FsResult HsHashStream::Update(ArrayBuffer &buffer) +{ + auto [succ, hsEntity] = GetHsEntity(); + if (!succ) { + HILOGE("Failed to get entity of HashStream"); + return FsResult::Error(EIO); + } + + switch (hsEntity->algType) { + case HASH_ALGORITHM_TYPE_MD5: + MD5_Update(&hsEntity->md5Ctx, buffer.buf, buffer.length); + break; + case HASH_ALGORITHM_TYPE_SHA1: + SHA1_Update(&hsEntity->shaCtx, buffer.buf, buffer.length); + break; + case HASH_ALGORITHM_TYPE_SHA256: + SHA256_Update(&hsEntity->sha256Ctx, buffer.buf, buffer.length); + break; + default: + break; + } + + return FsResult::Success(); +} + +FsResult HsHashStream::Digest() +{ + auto [succ, hsEntity] = GetHsEntity(); + if (!succ) { + HILOGE("Failed to get entity of HashStream"); + return FsResult::Error(EIO); + } + + string digestStr; + switch (hsEntity->algType) { + case HASH_ALGORITHM_TYPE_MD5: { + auto res = make_unique(MD5_DIGEST_LENGTH); + MD5_Final(res.get(), &hsEntity->md5Ctx); + digestStr = HashFinal(res, MD5_DIGEST_LENGTH); + break; + } + case HASH_ALGORITHM_TYPE_SHA1: { + auto res = make_unique(SHA_DIGEST_LENGTH); + SHA1_Final(res.get(), &hsEntity->shaCtx); + digestStr = HashFinal(res, SHA_DIGEST_LENGTH); + break; + } + case HASH_ALGORITHM_TYPE_SHA256: { + auto res = make_unique(SHA256_DIGEST_LENGTH); + SHA256_Final(res.get(), &hsEntity->sha256Ctx); + digestStr = HashFinal(res, SHA256_DIGEST_LENGTH); + break; + } + default: + break; + } + return FsResult::Success(digestStr); +} + +FsResult HsHashStream::Constructor(string alg) +{ + HASH_ALGORITHM_TYPE algType = GetHashAlgorithm(alg); + if (algType == HASH_ALGORITHM_TYPE_UNSUPPORTED) { + HILOGE("algType is not found."); + return FsResult::Error(EINVAL); + } + + HsHashStreamEntity *rawPtr = new (std::nothrow) HsHashStreamEntity(); + if (rawPtr == nullptr) { + HILOGE("Failed to request heap memory."); + return FsResult::Error(ENOMEM); + } + std::unique_ptr hsEntity(rawPtr); + hsEntity->algType = algType; + + switch (algType) { + case HASH_ALGORITHM_TYPE_MD5: { + MD5_CTX ctx; + MD5_Init(&ctx); + hsEntity->md5Ctx = ctx; + break; + } + case HASH_ALGORITHM_TYPE_SHA1: { + SHA_CTX ctx; + SHA1_Init(&ctx); + hsEntity->shaCtx = ctx; + break; + } + case HASH_ALGORITHM_TYPE_SHA256: { + SHA256_CTX ctx; + SHA256_Init(&ctx); + hsEntity->sha256Ctx = ctx; + break; + } + default: + break; + } + + HsHashStream *hsStreamPtr = new HsHashStream(move(hsEntity)); + if (hsStreamPtr == nullptr) { + HILOGE("Failed to create HsHashStream object on heap."); + return FsResult::Error(ENOMEM); + } + + return FsResult::Success(move(hsStreamPtr)); +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.h b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.h new file mode 100644 index 000000000..b39b86fb2 --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_CORE_H + +#include +#include "filemgmt_libfs.h" +#include "fs_utils.h" +#include "hs_hashstream_entity.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; + +class HsHashStream { +public: + HsHashStream(const HsHashStream &) = delete; + HsHashStream &operator=(const HsHashStream &) = delete; + + tuple GetHsEntity(); + FsResult Update(ArrayBuffer &buffer); + FsResult Digest(); + + static FsResult Constructor(string alg); + ~HsHashStream() = default; + +private: + unique_ptr entity; + explicit HsHashStream(unique_ptr entity) : entity(move(entity)) {} +}; + +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_CORE_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream_entity.h b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream_entity.h new file mode 100644 index 000000000..de1700cad --- /dev/null +++ b/interfaces/kits/js/src/mod_hash/class_hashstream/hs_hashstream_entity.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_ENTITY_H + +#include +#include +#include + +#include "hash_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +struct HsHashStreamEntity { + MD5_CTX md5Ctx; + SHA_CTX shaCtx; + SHA256_CTX sha256Ctx; + HASH_ALGORITHM_TYPE algType = HASH_ALGORITHM_TYPE_UNSUPPORTED; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_HASH_CLASS_HASHSTREAM_HS_HASHSTREAM_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets b/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets index 06e659dc2..4f81cef3d 100644 --- a/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets +++ b/interfaces/kits/js/src/mod_securitylabel/ani/ets/@ohos.file.securityLabel.ets @@ -23,8 +23,8 @@ namespace securityLabel { let promise = taskpool.execute((path: string, type: DataLevel): void => SecurityLabelImpl.setSecurityLabelSync(path, type), path, type); promise.then((ret: NullishType): void => { resolve(undefined); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -35,8 +35,8 @@ namespace securityLabel { let e = new BusinessError(); e.code = 0; callback(e, undefined); - }).catch((e: BusinessError): void => { - callback(e, undefined); + }).catch((e: Error): void => { + callback(e as BusinessError, undefined); }); } @@ -50,8 +50,8 @@ namespace securityLabel { promise.then((ret: NullishType): void => { let r = ret as string; resolve(r); - }).catch((e: BusinessError): void => { - reject(e); + }).catch((e: Error): void => { + reject(e as BusinessError); }); }); } @@ -63,8 +63,8 @@ namespace securityLabel { e.code = 0; let r = ret as string; callback(e, r); - }).catch((e: BusinessError): void => { - callback(e, ""); + }).catch((e: Error): void => { + callback(e as BusinessError, ""); }); } diff --git a/interfaces/kits/js/src/mod_statvfs/ani/bind_function_class.cpp b/interfaces/kits/js/src/mod_statvfs/ani/bind_function_class.cpp new file mode 100644 index 000000000..33782a3d1 --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/ani/bind_function_class.cpp @@ -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. + */ + +#include +#include +#include "ani_signature.h" +#include "bind_function.h" +#include "statvfs_ani.h" + +using namespace OHOS::FileManagement::ModuleFileIO::ANI; +using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature; + +static ani_status BindStaticMethods(ani_env *env) +{ + auto classDesc = Impl::StatvfsImpl::classDesc.c_str(); + + std::array methods = { + ani_native_function { "getFreeSizeSync", nullptr, reinterpret_cast(StatvfsAni::GetFreeSizeSync) }, + ani_native_function { "getTotalSizeSync", nullptr, reinterpret_cast(StatvfsAni::GetTotalSizeSync) }, + }; + return BindClass(env, classDesc, methods); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + HILOGE("Invalid parameter vm"); + return ANI_INVALID_ARGS; + } + + if (result == nullptr) { + HILOGE("Invalid parameter result"); + return ANI_INVALID_ARGS; + } + + ani_env *env; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + HILOGE("Invalid ani version!"); + return ANI_INVALID_VERSION; + } + + if ((status = BindStaticMethods(env)) != ANI_OK) { + HILOGE("Cannot bind native static methods for statvfs!"); + return status; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_statvfs/ani/ets/@ohos.file.statvfs.ets b/interfaces/kits/js/src/mod_statvfs/ani/ets/@ohos.file.statvfs.ets new file mode 100644 index 000000000..f3c569c80 --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/ani/ets/@ohos.file.statvfs.ets @@ -0,0 +1,86 @@ +/* + * 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 { BusinessError, AsyncCallback } from '@ohos.base'; + +namespace statfs { + export function getFreeSizeSync(path: string): number { + return StatvfsImpl.getFreeSizeSync(path); + } + + export function getFreeSize(path: string): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute(StatvfsImpl.getFreeSizeSync, path); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: Error): void => { + reject(e as BusinessError); + }); + }); + } + + export function getFreeSize(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute(StatvfsImpl.getFreeSizeSync, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); + }); + } + + export function getTotalSizeSync(path: string): number { + return StatvfsImpl.getTotalSizeSync(path); + } + + export function getTotalSize(path: string): Promise { + return new Promise((resolve: (result: number) => void, reject: (e: BusinessError) => void): void => { + let promise = taskpool.execute(StatvfsImpl.getTotalSizeSync, path); + promise.then((ret: NullishType): void => { + let result = ret as number + resolve(result); + }).catch((e: Error): void => { + reject(e as BusinessError); + }); + }); + } + + export function getTotalSize(path: string, callback: AsyncCallback): void { + let promise = taskpool.execute(StatvfsImpl.getTotalSizeSync, path); + promise.then((ret: NullishType): void => { + let e = new BusinessError(); + e.code = 0; + let result = ret as number; + callback(e, result); + }).catch((e: Error): void => { + callback(e as BusinessError, 0); + }); + } +} + +export default statfs; + +class StatvfsImpl { + + static { + loadLibrary("ani_file_statvfs"); + } + + static native getFreeSizeSync(path: string): number; + static native getTotalSizeSync(path: string): number; +} diff --git a/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.cpp b/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.cpp new file mode 100644 index 000000000..337b78f84 --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.cpp @@ -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. + */ + +#include "statvfs_ani.h" + +#include "error_handler.h" +#include "filemgmt_libhilog.h" +#include "statvfs_core.h" +#include "type_converter.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +using namespace std; +using namespace OHOS::FileManagement::ModuleFileIO; +using namespace OHOS::FileManagement::ModuleStatvfs; + +ani_double StatvfsAni::GetFreeSizeSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return 0; + } + + auto ret = StatvfsCore::DoGetFreeSize(srcPath); + if (!ret.IsSuccess()) { + HILOGE("Get freesize failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return 0; + } + + return static_cast(ret.GetData().value()); +} + +ani_double StatvfsAni::GetTotalSizeSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path) +{ + auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path); + if (!succPath) { + HILOGE("Invalid path"); + ErrorHandler::Throw(env, EINVAL); + return 0; + } + + auto ret = StatvfsCore::DoGetTotalSize(srcPath); + if (!ret.IsSuccess()) { + HILOGE("Get totalsize failed"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); + return 0; + } + + return static_cast(ret.GetData().value()); +} + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.h b/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.h new file mode 100644 index 000000000..1eaf5081f --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/ani/statvfs_ani.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_STATVFS_ANI_STATVFS_ANI_H +#define INTERFACES_KITS_JS_SRC_MOD_STATVFS_ANI_STATVFS_ANI_H + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace ANI { + +class StatvfsAni final { +public: + static ani_double GetFreeSizeSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); + static ani_double GetTotalSizeSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path); +}; + +} // namespace ANI +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_KITS_JS_SRC_MOD_STATVFS_ANI_STATVFS_ANI_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_statvfs/statvfs_core.cpp b/interfaces/kits/js/src/mod_statvfs/statvfs_core.cpp new file mode 100644 index 000000000..7a9aa9db6 --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/statvfs_core.cpp @@ -0,0 +1,52 @@ +/* + * 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 "statvfs_core.h" + +#include +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleStatvfs { +using namespace std; + +FsResult StatvfsCore::DoGetFreeSize(const string &path) +{ + struct statvfs diskInfo; + int ret = statvfs(path.c_str(), &diskInfo); + if (ret != 0) { + return FsResult::Error(errno); + } + unsigned long long freeSize = static_cast(diskInfo.f_bsize) * + static_cast(diskInfo.f_bfree); + return FsResult::Success(static_cast(freeSize)); +} + +FsResult StatvfsCore::DoGetTotalSize(const string &path) +{ + struct statvfs diskInfo; + int ret = statvfs(path.c_str(), &diskInfo); + if (ret != 0) { + return FsResult::Error(errno); + } + unsigned long long totalSize = static_cast(diskInfo.f_bsize) * + static_cast(diskInfo.f_blocks); + return FsResult::Success(static_cast(totalSize)); +} + +} // namespace ModuleStatfs +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_statvfs/statvfs_core.h b/interfaces/kits/js/src/mod_statvfs/statvfs_core.h new file mode 100644 index 000000000..24817f3eb --- /dev/null +++ b/interfaces/kits/js/src/mod_statvfs/statvfs_core.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_STATVFS_STATVFS_CORE_H +#define INTERFACES_KITS_JS_SRC_MOD_STATVFS_STATVFS_CORE_H + +#include "filemgmt_libfs.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleStatvfs { +using namespace ModuleFileIO; + +class StatvfsCore final { +public: + static FsResult DoGetFreeSize(const string &path); + static FsResult DoGetTotalSize(const string &path); +}; + +} // namespace ModuleStatvfs +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_STATVFS_STATVFS_CORE_H \ No newline at end of file diff --git a/interfaces/test/unittest/BUILD.gn b/interfaces/test/unittest/BUILD.gn index 5aeda1645..9a6fe09bf 100644 --- a/interfaces/test/unittest/BUILD.gn +++ b/interfaces/test/unittest/BUILD.gn @@ -18,10 +18,12 @@ group("file_api_unittest") { deps = [ "class_file:class_file_test", "filemgmt_libn_test:filemgmt_libn_test", + "js:ani_file_environment_test", "js:ani_file_fs_mock_test", "js:ani_file_fs_test", "js:ani_file_hash_test", "js:ani_file_securitylabel_test", + "js:ani_file_statvfs_test", "remote_uri:remote_uri_test", "task_signal:task_signal_test", ] diff --git a/interfaces/test/unittest/filemgmt_libn_test/BUILD.gn b/interfaces/test/unittest/filemgmt_libn_test/BUILD.gn index bd8ecb347..9641789b8 100644 --- a/interfaces/test/unittest/filemgmt_libn_test/BUILD.gn +++ b/interfaces/test/unittest/filemgmt_libn_test/BUILD.gn @@ -3,7 +3,7 @@ # 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 +# 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, @@ -14,16 +14,17 @@ import("//build/test.gni") import("//foundation/filemanagement/file_api/file_api.gni") -group("unittest") { +ohos_unittest("filemgmt_libn_test") { + branch_protector_ret = "pac_ret" testonly = true - deps = [ ":filemgmt_libn_test" ] -} -ohos_unittest("filemgmt_libn_test") { module_out_path = "file_api/file_api" include_dirs = [ "./include" ] - sources = [ "./src/n_class_test.cpp" ] + sources = [ + "./src/n_class_test.cpp", + "./src/napi_mock.cpp", + ] deps = [ "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", @@ -34,9 +35,12 @@ ohos_unittest("filemgmt_libn_test") { "access_token:libaccesstoken_sdk", "c_utils:utils", "c_utils:utilsbase", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "napi:ace_napi", ] + + defines = [ "ENABLE_NAPI_MOCK" ] } diff --git a/interfaces/test/unittest/filemgmt_libn_test/include/napi_mock.h b/interfaces/test/unittest/filemgmt_libn_test/include/napi_mock.h new file mode 100644 index 000000000..1c5a4d1c4 --- /dev/null +++ b/interfaces/test/unittest/filemgmt_libn_test/include/napi_mock.h @@ -0,0 +1,114 @@ +/* + * 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_FILEMGMT_LIBN_TEST_INCLUDE_NAPI_MOCK_H +#define INTERFACES_TEST_UNITTEST_FILEMGMT_LIBN_TEST_INCLUDE_NAPI_MOCK_H + +#pragma once +#include +#include "n_napi.h" + +namespace OHOS { +namespace FileManagement { +namespace LibN { +namespace Test { + +class INapiMock { +public: + virtual ~INapiMock() = default; + + virtual napi_status napi_define_class(napi_env env, const char *name, size_t length, napi_callback constructor, + void *data, size_t property_count, const napi_property_descriptor *properties, napi_value *result) = 0; + + virtual napi_status napi_create_reference( + napi_env env, napi_value value, uint32_t initial_refcount, napi_ref *result) = 0; + + virtual napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void *arg), void *arg) = 0; + + virtual napi_status napi_delete_reference(napi_env env, napi_ref ref) = 0; + + virtual napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result) = 0; + + virtual napi_status napi_new_instance( + napi_env env, napi_value constructor, size_t argc, const napi_value *argv, napi_value *result) = 0; + + virtual napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) = 0; + + virtual napi_status napi_wrap(napi_env env, napi_value js_object, void *native_object, napi_finalize finalize_cb, + void *finalize_hint, napi_ref *result) = 0; + + virtual napi_status napi_remove_wrap(napi_env env, napi_value js_object, void **result) = 0; +}; + +class NapiMock : public INapiMock { +public: + MOCK_METHOD(napi_status, napi_define_class, + (napi_env, const char *, size_t, napi_callback, void *, size_t, const napi_property_descriptor *, napi_value *), + (override)); + + MOCK_METHOD(napi_status, napi_create_reference, (napi_env, napi_value, uint32_t, napi_ref *), (override)); + + MOCK_METHOD(napi_status, napi_add_env_cleanup_hook, (napi_env env, void (*fun)(void *arg), void *arg), (override)); + + MOCK_METHOD(napi_status, napi_delete_reference, (napi_env env, napi_ref ref), (override)); + + MOCK_METHOD(napi_status, napi_get_reference_value, (napi_env env, napi_ref ref, napi_value *result), (override)); + + MOCK_METHOD(napi_status, napi_new_instance, + (napi_env env, napi_value constructor, size_t argc, const napi_value *argv, napi_value *result), (override)); + + MOCK_METHOD(napi_status, napi_unwrap, (napi_env env, napi_value js_object, void **result), (override)); + + MOCK_METHOD(napi_status, napi_wrap, + (napi_env env, napi_value js_object, void *native_object, napi_finalize finalize_cb, void *finalize_hint, + napi_ref *result), + (override)); + + MOCK_METHOD(napi_status, napi_remove_wrap, (napi_env env, napi_value js_object, void **result), (override)); +}; + +NapiMock &GetNapiMock(); +void SetNapiMock(NapiMock *mock); +void ResetNapiMock(); + +class ScopedNapiMock { +public: + explicit ScopedNapiMock(NapiMock *mock) : mock_(mock) + { + SetNapiMock(mock_); + } + + ~ScopedNapiMock() + { + ResetNapiMock(); + } + + NapiMock &GetMock() + { + return *mock_; + } + + ScopedNapiMock(const ScopedNapiMock &) = delete; + ScopedNapiMock &operator=(const ScopedNapiMock &) = delete; + +private: + NapiMock *mock_; +}; + +} // namespace Test +} // namespace LibN +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_TEST_UNITTEST_FILEMGMT_LIBN_TEST_INCLUDE_NAPI_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/filemgmt_libn_test/src/n_class_test.cpp b/interfaces/test/unittest/filemgmt_libn_test/src/n_class_test.cpp index a39ef9806..ccbb9dc17 100644 --- a/interfaces/test/unittest/filemgmt_libn_test/src/n_class_test.cpp +++ b/interfaces/test/unittest/filemgmt_libn_test/src/n_class_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2023-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 @@ -13,44 +13,571 @@ * limitations under the License. */ -#include "n_class_test.h" +#include +#include + +#include +#include + #include "n_class.h" +#include "napi_mock.h" +namespace OHOS { +namespace FileManagement { +namespace LibN { +namespace Test { using namespace std; -using namespace OHOS; -using namespace testing::ext; -namespace OHOS { -namespace Media { -void FilemangementLibnTest::SetUpTestCase(void) {} +class NClassTest : public testing::Test { +public: + static void SetUpTestSuite(void) {} + static void TearDownTestSuite(void) {} + + void SetUp() override + { + mock_ = std::make_unique(); + scopedMock_ = std::make_unique(mock_.get()); + } + + void TearDown() override + { + scopedMock_.reset(); + mock_.reset(); + } + + NapiMock &GetMock() + { + return *mock_; + } + +private: + std::unique_ptr mock_; + std::unique_ptr scopedMock_; +}; + +/** + * @tc.name: NClassTest_DefineClass_001 + * @tc.desc: Test function of NClass::DefineClass interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_DefineClass_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_DefineClass_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_DefineClass_001"; + napi_callback callback = reinterpret_cast(0x1122); + vector props = {}; -void FilemangementLibnTest::TearDownTestCase(void) {} + // Set mock behaviors + napi_value expectedClass = reinterpret_cast(0x1234); + EXPECT_CALL(GetMock(), napi_define_class(testing::_, testing::_, testing::_, testing::_, testing::_, testing::_, + testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<7>(expectedClass), testing::Return(napi_ok))); -void FilemangementLibnTest::SetUp() {} + // Do testing + auto [succ, classValue] = NClass::DefineClass(env, className, callback, std::move(props)); + + // Verify results + EXPECT_TRUE(succ); + EXPECT_EQ(classValue, expectedClass); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_DefineClass_001"; +} -void FilemangementLibnTest::TearDown() {} - -HWTEST_F(FilemangementLibnTest, NClassTest_DefineClass_001, TestSize.Level1) +/** + * @tc.name: NClassTest_DefineClass_002 + * @tc.desc: Test function of NClass::DefineClass interface for FAILURE when napi_define_class fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_DefineClass_002, testing::ext::TestSize.Level1) { - string className = "TestClassAB"; - napi_callback vlaue = nullptr; + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_DefineClass_002"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_DefineClass_002"; + napi_callback callback = reinterpret_cast(0x1122); vector props = {}; - bool succ = false; - napi_value classValue = nullptr; - napi_env envTest = nullptr; - tie(succ, classValue) = FileManagement::LibN::NClass::DefineClass(envTest, className, vlaue, std::move(props)); - EXPECT_EQ(succ, false); - EXPECT_EQ((classValue == nullptr), true); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_define_class(testing::_, testing::_, testing::_, testing::_, testing::_, testing::_, + testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Do testing + auto [succ, classValue] = NClass::DefineClass(env, className, callback, std::move(props)); + + // Verify results + EXPECT_FALSE(succ); + EXPECT_EQ(classValue, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_DefineClass_002"; +} + +/** + * @tc.name: NClassTest_SaveClass_001 + * @tc.desc: Test function of NClass::SaveClass interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_SaveClass_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_SaveClass_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_SaveClass_001"; + + // Set mock behaviors + napi_value classValue = reinterpret_cast(0x1234); + napi_ref mockReference = reinterpret_cast(0x2345); + EXPECT_CALL(GetMock(), napi_create_reference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<3>(mockReference), testing::Return(napi_ok))); + + EXPECT_CALL(GetMock(), napi_add_env_cleanup_hook(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + + // Do testing + bool succ = NClass::SaveClass(env, className, classValue); + + // Verify results + EXPECT_TRUE(succ); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_SaveClass_001"; +} + +/** + * @tc.name: NClassTest_SaveClass_002 + * @tc.desc: Test function of NClass::SaveClass interface for FAILURE when napi_create_reference fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_SaveClass_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_SaveClass_002"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_SaveClass_002"; + napi_value classValue = reinterpret_cast(0x1234); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_create_reference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Do testing + bool succ = NClass::SaveClass(env, className, classValue); + + // Verify results + EXPECT_FALSE(succ); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_SaveClass_002"; +} + +/** + * @tc.name: NClassTest_CleanClass_001 + * @tc.desc: Test function of NClass::CleanClass interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_CleanClass_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_CleanClass_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_delete_reference(testing::_, testing::_)).WillOnce(testing::Return(napi_ok)); + + // Do testing + NClass::CleanClass(env); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_CleanClass_001"; +} + +/** + * @tc.name: NClassTest_InstantiateClass_001 + * @tc.desc: Test function of NClass::InstantiateClass interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_InstantiateClass_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_InstantiateClass_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_InstantiateClass_001"; + vector emptyArgs = {}; + + // Set mock behaviors + napi_value classValue = reinterpret_cast(0x1234); + napi_ref mockReference = reinterpret_cast(0x2345); + EXPECT_CALL(GetMock(), napi_create_reference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<3>(mockReference), testing::Return(napi_ok))); + + EXPECT_CALL(GetMock(), napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + + napi_value expectedInstance = reinterpret_cast(0x3456); + EXPECT_CALL(GetMock(), napi_new_instance(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<4>(expectedInstance), testing::Return(napi_ok))); + + // Prepare instance + bool succ = NClass::SaveClass(env, className, classValue); + EXPECT_TRUE(succ); + + // Do testing + auto instance = NClass::InstantiateClass(env, className, emptyArgs); + + // Verify results + EXPECT_EQ(instance, expectedInstance); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_InstantiateClass_001"; +} + +/** + * @tc.name: NClassTest_InstantiateClass_002 + * @tc.desc: Test function of NClass::InstantiateClass interface for FAILURE when class hasn't been saved yet. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_InstantiateClass_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_InstantiateClass_002"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_InstantiateClass_002"; + vector emptyArgs = {}; + + // Do testing + auto instance = NClass::InstantiateClass(env, className, emptyArgs); + + // Verify results + EXPECT_EQ(instance, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_InstantiateClass_002"; +} + +/** + * @tc.name: NClassTest_InstantiateClass_003 + * @tc.desc: Test function of NClass::InstantiateClass interface for FAILURE when napi_get_reference_value fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_InstantiateClass_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_InstantiateClass_003"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_InstantiateClass_003"; + vector emptyArgs = {}; + + // Set mock behaviors + napi_value classValue = reinterpret_cast(0x1234); + napi_ref mockReference = reinterpret_cast(0x2345); + EXPECT_CALL(GetMock(), napi_create_reference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<3>(mockReference), testing::Return(napi_ok))); + + EXPECT_CALL(GetMock(), napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_invalid_arg)); + + // Prepare instance + bool succ = NClass::SaveClass(env, className, classValue); + EXPECT_TRUE(succ); + + // Do testing + auto instance = NClass::InstantiateClass(env, className, emptyArgs); + + // Verify results + EXPECT_EQ(instance, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_InstantiateClass_003"; +} + +/** + * @tc.name: NClassTest_InstantiateClass_004 + * @tc.desc: Test function of NClass::InstantiateClass interface for FAILURE when napi_new_instance fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_InstantiateClass_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_InstantiateClass_004"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + string className = "NClassTest_InstantiateClass_004"; + vector emptyArgs = {}; + + // Set mock behaviors + napi_value classValue = reinterpret_cast(0x1234); + napi_ref mockReference = reinterpret_cast(0x2345); + EXPECT_CALL(GetMock(), napi_create_reference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<3>(mockReference), testing::Return(napi_ok))); + + EXPECT_CALL(GetMock(), napi_get_reference_value(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + + EXPECT_CALL(GetMock(), napi_new_instance(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Prepare instance + bool succ = NClass::SaveClass(env, className, classValue); + EXPECT_TRUE(succ); + + // Do testing + auto instance = NClass::InstantiateClass(env, className, emptyArgs); + + // Verify results + EXPECT_EQ(instance, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_InstantiateClass_004"; +} + +/** + * @tc.name: NClassTest_GetEntityOf_001 + * @tc.desc: Test function of NClass::GetEntityOf interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_GetEntityOf_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_GetEntityOf_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + void *expectedEntity = reinterpret_cast(0x23456); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(expectedEntity), testing::Return(napi_ok))); + + // Do testing + auto entity = NClass::GetEntityOf(env, object); + + // Verify results + EXPECT_EQ(entity, expectedEntity); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_GetEntityOf_001"; } -HWTEST_F(FilemangementLibnTest, NClassTest_SaveClass_001, TestSize.Level1) +/** + * @tc.name: NClassTest_GetEntityOf_002 + * @tc.desc: Test function of NClass::GetEntityOf interface for FAILURE when arg env nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_GetEntityOf_002, testing::ext::TestSize.Level1) { - string className = "TestClassAB"; - bool succ = false; - napi_value classValue = nullptr; - napi_env envTest = nullptr; - succ = FileManagement::LibN::NClass::SaveClass(envTest, className, classValue); - EXPECT_EQ(succ, false); + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_GetEntityOf_002"; + // Prepare test parameters + napi_value object = reinterpret_cast(0x1234); + + // Do testing + auto entity = NClass::GetEntityOf(nullptr, object); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_GetEntityOf_002"; +} + +/** + * @tc.name: NClassTest_GetEntityOf_003 + * @tc.desc: Test function of NClass::GetEntityOf interface for FAILURE when arg objStat nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_GetEntityOf_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_GetEntityOf_003"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + + // Do testing + auto entity = NClass::GetEntityOf(env, nullptr); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_GetEntityOf_003"; +} + +/** + * @tc.name: NClassTest_GetEntityOf_004 + * @tc.desc: Test function of NClass::GetEntityOf interface for FAILURE when napi_unwrap fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_GetEntityOf_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_GetEntityOf_004"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_unwrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Do testing + auto entity = NClass::GetEntityOf(env, object); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_GetEntityOf_004"; +} + +/** + * @tc.name: NClassTest_SetEntityFor_001 + * @tc.desc: Test function of NClass::SetEntityFor interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_SetEntityFor_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_SetEntityFor_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + string entity = "NClassTest_SetEntityFor_001"; + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_wrap(testing::_, testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_ok)); + + // Do testing + bool result = NClass::SetEntityFor(env, object, make_unique(entity)); + + // Verify results + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_SetEntityFor_001"; } -} // namespace Media + +/** + * @tc.name: NClassTest_SetEntityFor_002 + * @tc.desc: Test function of NClass::SetEntityFor interface for FAILURE when napi_wrap fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_SetEntityFor_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_SetEntityFor_002"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + string entity = "NClassTest_SetEntityFor_001"; + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_wrap(testing::_, testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Do testing + bool result = NClass::SetEntityFor(env, object, make_unique(entity)); + + // Verify results + EXPECT_FALSE(result); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_SetEntityFor_002"; +} + +/** + * @tc.name: NClassTest_RemoveEntityOfFinal_001 + * @tc.desc: Test function of NClass::RemoveEntityOfFinal interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_RemoveEntityOfFinal_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_RemoveEntityOfFinal_001"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + void *expectedEntity = reinterpret_cast(0x23456); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_remove_wrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::DoAll(testing::SetArgPointee<2>(expectedEntity), testing::Return(napi_ok))); + + // Do testing + auto entity = NClass::RemoveEntityOfFinal(env, object); + + // Verify results + EXPECT_EQ(entity, expectedEntity); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_RemoveEntityOfFinal_001"; +} + +/** + * @tc.name: NClassTest_RemoveEntityOfFinal_002 + * @tc.desc: Test function of NClass::RemoveEntityOfFinal interface for FAILURE when arg env nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_RemoveEntityOfFinal_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_RemoveEntityOfFinal_002"; + // Prepare test parameters + napi_value object = reinterpret_cast(0x1234); + + // Do testing + auto entity = NClass::RemoveEntityOfFinal(nullptr, object); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_RemoveEntityOfFinal_002"; +} + +/** + * @tc.name: NClassTest_RemoveEntityOfFinal_003 + * @tc.desc: Test function of NClass::RemoveEntityOfFinal interface for FAILURE when arg objStat nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_RemoveEntityOfFinal_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_RemoveEntityOfFinal_003"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + + // Do testing + auto entity = NClass::RemoveEntityOfFinal(env, nullptr); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_RemoveEntityOfFinal_003"; +} + +/** + * @tc.name: NClassTest_RemoveEntityOfFinal_004 + * @tc.desc: Test function of NClass::RemoveEntityOfFinal interface for FAILURE when napi_remove_wrap fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(NClassTest, NClassTest_RemoveEntityOfFinal_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin NClassTest_RemoveEntityOfFinal_004"; + // Prepare test parameters + napi_env env = reinterpret_cast(0x1000); + napi_value object = reinterpret_cast(0x1234); + + // Set mock behaviors + EXPECT_CALL(GetMock(), napi_remove_wrap(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(napi_generic_failure)); + + // Do testing + auto entity = NClass::RemoveEntityOfFinal(env, object); + + // Verify results + EXPECT_EQ(entity, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end NClassTest_RemoveEntityOfFinal_004"; +} + +} // namespace Test +} // namespace LibN +} // namespace FileManagement } // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/filemgmt_libn_test/src/napi_mock.cpp b/interfaces/test/unittest/filemgmt_libn_test/src/napi_mock.cpp new file mode 100644 index 000000000..096ca426b --- /dev/null +++ b/interfaces/test/unittest/filemgmt_libn_test/src/napi_mock.cpp @@ -0,0 +1,106 @@ +/* + * 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 "napi_mock.h" + +#include + +namespace OHOS { +namespace FileManagement { +namespace LibN { +namespace Test { + +namespace { +std::mutex g_mockMutex; +NapiMock *g_currentMock = nullptr; +NapiMock g_defaultMock; +} // namespace + +NapiMock &GetNapiMock() +{ + std::lock_guard lock(g_mockMutex); + return g_currentMock ? *g_currentMock : g_defaultMock; +} + +void SetNapiMock(NapiMock *mock) +{ + std::lock_guard lock(g_mockMutex); + g_currentMock = mock; +} + +void ResetNapiMock() +{ + SetNapiMock(nullptr); +} + +} // namespace Test +} // namespace LibN +} // namespace FileManagement +} // namespace OHOS + +#ifdef ENABLE_NAPI_MOCK +extern "C" { +using namespace OHOS::FileManagement::LibN::Test; + +napi_status napi_define_class(napi_env env, const char *name, size_t length, napi_callback constructor, void *data, + size_t property_count, const napi_property_descriptor *properties, napi_value *result) +{ + return GetNapiMock().napi_define_class(env, name, length, constructor, data, property_count, properties, result); +} + +napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref *result) +{ + return GetNapiMock().napi_create_reference(env, value, initial_refcount, result); +} + +napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void *arg), void *arg) +{ + return GetNapiMock().napi_add_env_cleanup_hook(env, fun, arg); +} + +napi_status napi_delete_reference(napi_env env, napi_ref ref) +{ + return GetNapiMock().napi_delete_reference(env, ref); +} + +napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value *result) +{ + return GetNapiMock().napi_get_reference_value(env, ref, result); +} + +napi_status napi_new_instance( + napi_env env, napi_value constructor, size_t argc, const napi_value *argv, napi_value *result) +{ + return GetNapiMock().napi_new_instance(env, constructor, argc, argv, result); +} + +napi_status napi_unwrap(napi_env env, napi_value js_object, void **result) +{ + return GetNapiMock().napi_unwrap(env, js_object, result); +} + +napi_status napi_wrap(napi_env env, napi_value js_object, void *native_object, napi_finalize finalize_cb, + void *finalize_hint, napi_ref *result) +{ + return GetNapiMock().napi_wrap(env, js_object, native_object, finalize_cb, finalize_hint, result); +} + +napi_status napi_remove_wrap(napi_env env, napi_value js_object, void **result) +{ + return GetNapiMock().napi_remove_wrap(env, js_object, result); +} + +} // extern "C" +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/BUILD.gn b/interfaces/test/unittest/js/BUILD.gn index dd2a44757..d7b5876fc 100644 --- a/interfaces/test/unittest/js/BUILD.gn +++ b/interfaces/test/unittest/js/BUILD.gn @@ -1,186 +1,311 @@ -# 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("ani_file_fs_mock_test") { - branch_protector_ret = "pac_ret" - testonly = true - - module_out_path = "file_api/file_api" - - include_dirs = [ - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", - "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", - "${file_api_path}/interfaces/test/unittest/js/mod_fs/properties/mock", - ] - - sources = [ - "mod_fs/class_file/fs_file_mock_test.cpp", - "mod_fs/class_stat/fs_stat_mock_test.cpp", - "mod_fs/properties/access_core_mock_test.cpp", - "mod_fs/properties/copy_file_core_mock_test.cpp", - "mod_fs/properties/mkdir_core_mock_test.cpp", - "mod_fs/properties/move_core_mock_test.cpp", - "mod_fs/properties/mock/system_mock.cpp", - "mod_fs/properties/mock/uv_fs_mock.cpp", - "mod_fs/properties/open_core_mock_test.cpp", - "mod_fs/properties/read_core_mock_test.cpp", - "mod_fs/properties/stat_core_mock_test.cpp", - "mod_fs/properties/truncate_core_mock_test.cpp", - "mod_fs/properties/unlink_core_mock_test.cpp", - "mod_fs/properties/write_core_mock_test.cpp", - ] - - deps = [ - "${file_api_path}/interfaces/kits/native:remote_uri_native", - "${file_api_path}/interfaces/kits/native:task_signal_native", - "${file_api_path}/interfaces/kits/rust:rust_file", - "${utils_path}/filemgmt_libfs:filemgmt_libfs", - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${file_api_path}/interfaces/kits/js:ani_file_fs", - ] - - external_deps = [ - "ability_runtime:ability_manager", - "app_file_service:fileuri_native", - "c_utils:utils", - "googletest:gmock_main", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_core", - "libuv:uv", - ] - - defines = [ - "private=public", - ] -} - -ohos_unittest("ani_file_fs_test") { - branch_protector_ret = "pac_ret" - testonly = true - - module_out_path = "file_api/file_api" - - resource_config_file = "../resource/ohos_test.xml" - - include_dirs = [ - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_randomaccessfile", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_readeriterator", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", - "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", - "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", - ] - - sources = [ - "mod_fs/class_file/fs_file_test.cpp", - "mod_fs/class_stat/fs_stat_test.cpp", - "mod_fs/properties/access_core_test.cpp", - "mod_fs/properties/close_core_test.cpp", - "mod_fs/properties/copy_file_core_test.cpp", - "mod_fs/properties/listfile_core_test.cpp", - "mod_fs/properties/move_core_test.cpp", - "mod_fs/properties/open_core_test.cpp", - "mod_fs/properties/read_core_test.cpp", - "mod_fs/properties/read_text_core_test.cpp", - "mod_fs/properties/rmdir_core_test.cpp", - "mod_fs/properties/stat_core_test.cpp", - "mod_fs/properties/truncate_core_test.cpp", - "mod_fs/properties/write_core_test.cpp", - ] - - deps = [ - "${file_api_path}/interfaces/kits/native:remote_uri_native", - "${file_api_path}/interfaces/kits/native:task_signal_native", - "${file_api_path}/interfaces/kits/rust:rust_file", - "${utils_path}/filemgmt_libfs:filemgmt_libfs", - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${file_api_path}/interfaces/kits/js:ani_file_fs", - ] - - external_deps = [ - "ability_runtime:ability_manager", - "app_file_service:fileuri_native", - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_core", - "libuv:uv", - ] - - defines = [ - "private=public", - ] -} - -ohos_unittest("ani_file_hash_test") { - module_out_path = "file_api/file_api" - - resource_config_file = "../resource/ohos_test.xml" - - sources = [ - "mod_hash/hash_core_test.cpp", - ] - - include_dirs = [ - "mock/libuv", - "${file_api_path}/interfaces/kits/js/src/mod_hash", - ] - - deps = [ - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${utils_path}/filemgmt_libfs:filemgmt_libfs", - "${file_api_path}/interfaces/kits/js:ani_file_hash", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "libuv:uv", - "googletest:gmock_main", - "googletest:gtest_main", - ] -} - -ohos_unittest("ani_file_securitylabel_test") { - module_out_path = "file_api/file_api" - - resource_config_file = "../resource/ohos_test.xml" - - sources = [ - "mod_securitylabel/securitylabel_core_test.cpp", - ] - - include_dirs = [ - "${file_api_path}/interfaces/kits/js/src/mod_securitylabel", - ] - - deps = [ - "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", - "${utils_path}/filemgmt_libfs:filemgmt_libfs", - "${file_api_path}/interfaces/kits/js:ani_file_securitylabel", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "googletest:gmock_main", - "googletest:gtest_main", - ] -} \ No newline at end of file +# 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("ani_file_environment_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + include_dirs = [ + "${src_path}/mod_environment", + "${src_path}/mod_environment/ani", + "${file_api_path}/interfaces/test/unittest/js/mod_environment/mock", + ] + + sources = [ + "mod_environment/environment_core_mock_test.cpp", + "mod_environment/mock/accesstoken_kit_mock.cpp", + "mod_environment/mock/ipc_skeleton_mock.cpp", + "mod_environment/mock/parameter_mock.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_environment", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "init:libbegetutil", + "ipc:ipc_core", + "libuv:uv", + "openssl:libcrypto_shared", + "os_account:os_account_innerkits", + "runtime_core:ani", + "runtime_core:libarkruntime", + ] + + defines = [ "private=public" ] +} + +ohos_unittest("ani_file_fs_mock_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_randomaccessfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_readeriterator", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_watcher", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/copy_listener", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/class_stream/mock", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/common", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/mock", + "${file_api_path}/interfaces/test/unittest/js/mod_fs/properties/mock", + ] + + sources = [ + "mod_fs/class_file/fs_file_mock_test.cpp", + "mod_fs/class_randomaccessfile/fs_randomaccessfile_mock_test.cpp", + "mod_fs/class_readeriterator/fs_reader_iterator_mock_test.cpp", + "mod_fs/class_stat/fs_stat_mock_test.cpp", + "mod_fs/class_stream/fs_stream_mock_test.cpp", + "mod_fs/class_stream/mock/c_mock.cpp", + "mod_fs/class_watcher/fs_file_watcher_mock_test.cpp", + "mod_fs/class_watcher/fs_watcher_mock_test.cpp", + "mod_fs/mock/eventfd_mock.cpp", + "mod_fs/mock/inotify_mock.cpp", + "mod_fs/mock/poll_mock.cpp", + "mod_fs/mock/unistd_mock.cpp", + "mod_fs/properties/access_core_mock_test.cpp", + "mod_fs/properties/copy_core_mock_test.cpp", + "mod_fs/properties/copy_file_core_mock_test.cpp", + "mod_fs/properties/create_randomaccessfile_core_mock_test.cpp", + "mod_fs/properties/dup_core_mock_test.cpp", + "mod_fs/properties/fdatasync_core_mock_test.cpp", + "mod_fs/properties/fsync_core_mock_test.cpp", + "mod_fs/properties/lstat_core_mock_test.cpp", + "mod_fs/properties/mkdir_core_mock_test.cpp", + "mod_fs/properties/mkdtemp_core_mock_test.cpp", + "mod_fs/properties/mock/system_mock.cpp", + "mod_fs/properties/mock/uv_fs_mock.cpp", + "mod_fs/properties/move_core_mock_test.cpp", + "mod_fs/properties/open_core_mock_test.cpp", + "mod_fs/properties/read_core_mock_test.cpp", + "mod_fs/properties/read_lines_core_mock_test.cpp", + "mod_fs/properties/rename_core_mock_test.cpp", + "mod_fs/properties/stat_core_mock_test.cpp", + "mod_fs/properties/symlink_core_mock_test.cpp", + "mod_fs/properties/trans_listener_mock_test.cpp", + "mod_fs/properties/truncate_core_mock_test.cpp", + "mod_fs/properties/unlink_core_mock_test.cpp", + "mod_fs/properties/utimes_core_mock_test.cpp", + "mod_fs/properties/watcher_core_mock_test.cpp", + "mod_fs/properties/write_core_mock_test.cpp", + "mod_fs/properties/xattr_core_mock_test.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_fs", + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "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", + "libuv:uv", + ] + + libs = [ "dl" ] + + defines = [ + "ENABLE_DISTRIBUTED_FILE_MOCK", + "private=public", + ] +} + +ohos_unittest("ani_file_fs_test") { + branch_protector_ret = "pac_ret" + testonly = true + + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + include_dirs = [ + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_atomicfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_file", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_randomaccessfile", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_readeriterator", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stat", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_stream", + "${file_api_path}/interfaces/kits/js/src/mod_fs/class_tasksignal", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties", + "${file_api_path}/interfaces/kits/js/src/mod_fs/properties/copy_listener", + ] + + sources = [ + "mod_fs/class_atomicfile/fs_atomicfile_test.cpp", + "mod_fs/class_file/fs_file_test.cpp", + "mod_fs/class_randomaccessfile/fs_randomaccessfile_test.cpp", + "mod_fs/class_readeriterator/fs_reader_iterator_test.cpp", + "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/properties/access_core_test.cpp", + "mod_fs/properties/close_core_test.cpp", + "mod_fs/properties/copy_core_test.cpp", + "mod_fs/properties/copy_dir_core_test.cpp", + "mod_fs/properties/copy_file_core_test.cpp", + "mod_fs/properties/create_randomaccessfile_core_test.cpp", + "mod_fs/properties/create_stream_core_test.cpp", + "mod_fs/properties/dup_core_test.cpp", + "mod_fs/properties/fdopen_stream_core_test.cpp", + "mod_fs/properties/listfile_core_test.cpp", + "mod_fs/properties/lseek_core_test.cpp", + "mod_fs/properties/lstat_core_test.cpp", + "mod_fs/properties/move_core_test.cpp", + "mod_fs/properties/movedir_core_test.cpp", + "mod_fs/properties/open_core_test.cpp", + "mod_fs/properties/read_core_test.cpp", + "mod_fs/properties/read_lines_core_test.cpp", + "mod_fs/properties/read_text_core_test.cpp", + "mod_fs/properties/rmdir_core_test.cpp", + "mod_fs/properties/stat_core_test.cpp", + "mod_fs/properties/trans_listener_test.cpp", + "mod_fs/properties/truncate_core_test.cpp", + "mod_fs/properties/utimes_core_test.cpp", + "mod_fs/properties/write_core_test.cpp", + "mod_fs/properties/xattr_core_test.cpp", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_fs", + "${file_api_path}/interfaces/kits/native:remote_uri_native", + "${file_api_path}/interfaces/kits/native:task_signal_native", + "${file_api_path}/interfaces/kits/rust:rust_file", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "ability_runtime:ability_manager", + "app_file_service:fileuri_native", + "c_utils:utils", + "dfs_service:distributed_file_daemon_kit_inner", + "dfs_service:libdistributedfileutils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "libuv:uv", + ] + + defines = [ "private=public" ] +} + +ohos_unittest("ani_file_hash_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ "mod_hash/hash_core_test.cpp" ] + + include_dirs = [ + "mock/libuv", + "${file_api_path}/interfaces/kits/js/src/mod_hash", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_hash", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "libuv:uv", + ] +} + +ohos_unittest("ani_file_securitylabel_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ "mod_securitylabel/securitylabel_core_test.cpp" ] + + include_dirs = [ + "mock/libuv", + "${file_api_path}/interfaces/kits/js/src/mod_securitylabel", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_securitylabel", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "libuv:uv", + ] +} + +ohos_unittest("ani_file_statvfs_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ "mod_statvfs/statvfs_core_test.cpp" ] + + include_dirs = [ + "mock/libuv", + "${file_api_path}/interfaces/kits/js/src/mod_statvfs", + ] + + deps = [ + "${file_api_path}/interfaces/kits/js:ani_file_statvfs", + "${utils_path}/filemgmt_libfs:filemgmt_libfs", + "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "libuv:uv", + ] +} diff --git a/interfaces/test/unittest/js/mod_environment/environment_core_mock_test.cpp b/interfaces/test/unittest/js/mod_environment/environment_core_mock_test.cpp new file mode 100644 index 000000000..6b680cc5b --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/environment_core_mock_test.cpp @@ -0,0 +1,521 @@ +/* + * 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 "accesstoken_kit_mock.h" +#include "environment_core.h" +#include "ipc_skeleton_mock.h" +#include "parameter_mock.h" +#include "securec.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class EnvironmentCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr accessToken = nullptr; + static inline std::shared_ptr paramMoc = nullptr; + static inline shared_ptr skeleton = nullptr; +}; + +void EnvironmentCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + accessToken = std::make_shared(); + Backup::BAccessTokenKit::token = accessToken; + paramMoc = std::make_shared(); + AppFileService::ParamMoc::paramMoc = paramMoc; + skeleton = make_shared(); + Backup::IPCSkeletonMock::skeleton = skeleton; +} + +void EnvironmentCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Backup::BAccessTokenKit::token = nullptr; + accessToken = nullptr; + AppFileService::IParamMoc::paramMoc = nullptr; + paramMoc = nullptr; + Backup::IPCSkeletonMock::skeleton = nullptr; + skeleton = nullptr; +} + +void EnvironmentCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void EnvironmentCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetStorageDataDir_001 + * @tc.desc: Test function of DoGetStorageDataDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetStorageDataDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetStorageDataDir_001"; + + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(false)); + + auto res = ModuleEnvironment::DoGetStorageDataDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetStorageDataDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetStorageDataDir_002 + * @tc.desc: Test function of DoGetStorageDataDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetStorageDataDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetStorageDataDir_002"; + + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(true)); + + auto res = ModuleEnvironment::DoGetStorageDataDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetStorageDataDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDataDir_001 + * @tc.desc: Test function of DoGetUserDataDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDataDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDataDir_001"; + + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(false)); + + auto res = ModuleEnvironment::DoGetUserDataDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDataDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDataDir_002 + * @tc.desc: Test function of DoGetUserDataDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDataDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDataDir_002"; + + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(true)); + + auto res = ModuleEnvironment::DoGetUserDataDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDataDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDownloadDir_001 + * @tc.desc: Test function of DoGetUserDownloadDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDownloadDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDownloadDir_001"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillRepeatedly(Invoke([&](const char *, const char *, char *value, uint32_t) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*skeleton, GetOsAccountShortName(_)).WillRepeatedly(Return(ERR_OK)); + + auto res = ModuleEnvironment::DoGetUserDownloadDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDownloadDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDownloadDir_002 + * @tc.desc: Test function of DoGetUserDownloadDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDownloadDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDownloadDir_002"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)).WillOnce(Return(-1)); + + auto res = ModuleEnvironment::DoGetUserDownloadDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDownloadDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDownloadDir_003 + * @tc.desc: Test function of DoGetUserDownloadDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDownloadDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDownloadDir_003"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillRepeatedly(Invoke([&](const char *, const char *, char *value, uint32_t) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*skeleton, GetOsAccountShortName(_)).WillRepeatedly(Return(1)); + + auto res = ModuleEnvironment::DoGetUserDownloadDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDownloadDir_003"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDesktopDir_001 + * @tc.desc: Test function of DoGetUserDesktopDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDesktopDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDesktopDir_001"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + + auto res = ModuleEnvironment::DoGetUserDesktopDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDesktopDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDesktopDir_002 + * @tc.desc: Test function of DoGetUserDesktopDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDesktopDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDesktopDir_002"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return -1; + })); + + auto res = ModuleEnvironment::DoGetUserDesktopDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDesktopDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDesktopDir_003 + * @tc.desc: Test function of DoGetUserDesktopDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDesktopDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDesktopDir_003"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *, const char *, char *value, uint32_t) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*skeleton, GetOsAccountShortName(_)).WillRepeatedly(Return(ERR_OK)); + + auto res = ModuleEnvironment::DoGetUserDesktopDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDesktopDir_003"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDocumentDir_001 + * @tc.desc: Test function of DoGetUserDocumentDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDocumentDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDocumentDir_001"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + + auto res = ModuleEnvironment::DoGetUserDocumentDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDocumentDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDocumentDir_002 + * @tc.desc: Test function of DoGetUserDocumentDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDocumentDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDocumentDir_002"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return -1; + })); + + auto res = ModuleEnvironment::DoGetUserDocumentDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDocumentDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserDocumentDir_003 + * @tc.desc: Test function of DoGetUserDocumentDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserDocumentDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserDocumentDir_003"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *, const char *, char *value, uint32_t) { + strcpy_s(value, 5, "true"); + return 1; + })); + + auto res = ModuleEnvironment::DoGetUserDocumentDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserDocumentDir_003"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetExternalStorageDir_001 + * @tc.desc: Test function of DoGetExternalStorageDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetExternalStorageDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetExternalStorageDir_001"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(false)); + + auto res = ModuleEnvironment::DoGetExternalStorageDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetExternalStorageDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetExternalStorageDir_002 + * @tc.desc: Test function of DoGetExternalStorageDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetExternalStorageDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetExternalStorageDir_002"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(true)); + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillOnce(Return(0)); + EXPECT_CALL(*accessToken, VerifyAccessToken(_, _)).WillOnce(Return(1)); + + auto res = ModuleEnvironment::DoGetExternalStorageDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetExternalStorageDir_002"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetExternalStorageDir_003 + * @tc.desc: Test function of DoGetExternalStorageDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetExternalStorageDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetExternalStorageDir_003"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(true)); + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillOnce(Return(0)); + EXPECT_CALL(*accessToken, VerifyAccessToken(_, _)) + .WillOnce(Return(Security::AccessToken::PermissionState::PERMISSION_GRANTED)); + + auto res = ModuleEnvironment::DoGetExternalStorageDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetExternalStorageDir_003"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetExternalStorageDir_004 + * @tc.desc: Test function of DoGetExternalStorageDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetExternalStorageDir_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetExternalStorageDir_004"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(false)); + + auto res = ModuleEnvironment::DoGetExternalStorageDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetExternalStorageDir_004"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserHomeDir_001 + * @tc.desc: Test function of DoGetUserHomeDir interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserHomeDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserHomeDir_001"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)).WillOnce(Return(1)); + + auto res = ModuleEnvironment::DoGetUserHomeDir(); + + EXPECT_FALSE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserHomeDir_001"; +} + +/** + * @tc.name: EnvironmentCoreTest_DoGetUserHomeDir_002 + * @tc.desc: Test function of DoGetUserHomeDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(EnvironmentCoreTest, EnvironmentCoreTest_DoGetUserHomeDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "EnvironmentCoreTest-begin EnvironmentCoreTest_DoGetUserHomeDir_002"; + + EXPECT_CALL(*paramMoc, GetParameter(_, _, _, _)) + .WillOnce(Invoke([&](const char *key, const char *def, char *value, uint32_t len) { + strcpy_s(value, 5, "true"); + return 1; + })); + EXPECT_CALL(*accessToken, IsSystemAppByFullTokenID(_)).WillOnce(Return(true)); + EXPECT_CALL(*skeleton, GetCallingTokenID()).WillOnce(Return(0)); + EXPECT_CALL(*accessToken, VerifyAccessToken(_, _)) + .WillOnce(Return(Security::AccessToken::PermissionState::PERMISSION_GRANTED)); + + auto res = ModuleEnvironment::DoGetUserHomeDir(); + + EXPECT_TRUE(res.IsSuccess()); + + GTEST_LOG_(INFO) << "EnvironmentCoreTest-end EnvironmentCoreTest_DoGetUserHomeDir_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.cpp b/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.cpp new file mode 100644 index 000000000..021e591fe --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.cpp @@ -0,0 +1,29 @@ +/* + * 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 "accesstoken_kit_mock.h" + +namespace OHOS::Security::AccessToken { + +bool TokenIdKit::IsSystemAppByFullTokenID(uint64_t tokenId) +{ + return OHOS::FileManagement::Backup::BAccessTokenKit::token->IsSystemAppByFullTokenID(tokenId); +} + +int AccessTokenKit::VerifyAccessToken(AccessTokenID tokenID, const std::string &permissionName) +{ + return OHOS::FileManagement::Backup::BAccessTokenKit::token->VerifyAccessToken(tokenID, permissionName); +} +} // namespace OHOS::Security::AccessToken diff --git a/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.h b/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.h new file mode 100644 index 000000000..5f5c0b18b --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/mock/accesstoken_kit_mock.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") = 0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_MOCK_ACCESSTOKEN_KIT_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_MOCK_ACCESSTOKEN_KIT_MOCK_H + +#include + +#include "accesstoken_kit.h" +#include "tokenid_kit.h" + +namespace OHOS::FileManagement::Backup { +class BAccessTokenKit { +public: + virtual bool IsSystemAppByFullTokenID(uint64_t) = 0; + virtual int VerifyAccessToken(Security::AccessToken::AccessTokenID, const std::string &) = 0; + +public: + BAccessTokenKit() = default; + virtual ~BAccessTokenKit() = default; + +public: + static inline std::shared_ptr token = nullptr; +}; + +class AccessTokenKitMock : public BAccessTokenKit { +public: + MOCK_METHOD(bool, IsSystemAppByFullTokenID, (uint64_t)); + MOCK_METHOD(int, VerifyAccessToken, (Security::AccessToken::AccessTokenID, const std::string &)); +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_MOCK_ACCESSTOKEN_KIT_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.cpp b/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.cpp new file mode 100644 index 000000000..a231dfdee --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.cpp @@ -0,0 +1,33 @@ +/* + * 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 "ipc_skeleton_mock.h" + +namespace OHOS { +#ifdef CONFIG_IPC_SINGLE +using namespace IPC_SINGLE; +#endif + +uint32_t IPCSkeleton::GetCallingTokenID() +{ + return OHOS::FileManagement::Backup::BIPCSkeleton::skeleton->GetCallingTokenID(); +} + +ErrCode OHOS::AccountSA::OsAccountManager::GetOsAccountShortName(std::string &shortName) +{ + return OHOS::FileManagement::Backup::BIPCSkeleton::skeleton->GetOsAccountShortName(shortName); +} + +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.h b/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.h new file mode 100644 index 000000000..89c5e9fc8 --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/mock/ipc_skeleton_mock.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") = 0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_IPC_SKELETON_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_IPC_SKELETON_MOCK_H + +#include + +#include "ipc_skeleton.h" +#include "os_account_manager.h" + +using ErrCode = int; + +namespace OHOS::FileManagement::Backup { +class BIPCSkeleton : public RefBase { +public: + virtual uint32_t GetCallingTokenID() = 0; + virtual ErrCode GetOsAccountShortName(std::string &shortName) = 0; + +public: + BIPCSkeleton() = default; + virtual ~BIPCSkeleton() = default; + +public: + static inline std::shared_ptr skeleton = nullptr; +}; + +class IPCSkeletonMock : public BIPCSkeleton { +public: + MOCK_METHOD(uint32_t, GetCallingTokenID, ()); + MOCK_METHOD(ErrCode, GetOsAccountShortName, (std::string & shortName)); +}; +} // namespace OHOS::FileManagement::Backup +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_IPC_SKELETON_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/filemgmt_libn_test/include/n_class_test.h b/interfaces/test/unittest/js/mod_environment/mock/parameter_mock.cpp similarity index 61% rename from interfaces/test/unittest/filemgmt_libn_test/include/n_class_test.h rename to interfaces/test/unittest/js/mod_environment/mock/parameter_mock.cpp index 200927e49..2905890c1 100644 --- a/interfaces/test/unittest/filemgmt_libn_test/include/n_class_test.h +++ b/interfaces/test/unittest/js/mod_environment/mock/parameter_mock.cpp @@ -1,5 +1,5 @@ /* - * 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 @@ -13,20 +13,15 @@ * limitations under the License. */ -#ifndef FILEMGMT_LIBN_TEST_H -#define FILEMGMT_LIBN_TEST_H +#include "parameter_mock.h" -#include +#include "parameter.h" -namespace OHOS { -namespace Media { -class FilemangementLibnTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; -} -} -#endif \ No newline at end of file +using namespace OHOS::AppFileService; +int GetParameter(const char *key, const char *def, char *value, uint32_t len) +{ + if (IParamMoc::paramMoc == nullptr) { + return -1; + } + return IParamMoc::paramMoc->GetParameter(key, def, value, len); +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_environment/mock/parameter_mock.h b/interfaces/test/unittest/js/mod_environment/mock/parameter_mock.h new file mode 100644 index 000000000..41fc24fba --- /dev/null +++ b/interfaces/test/unittest/js/mod_environment/mock/parameter_mock.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_PARAMETER_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_PARAMETER_MOCK_H + +#include +#include + +namespace OHOS { +namespace AppFileService { +class IParamMoc { +public: + virtual ~IParamMoc() = default; + +public: + virtual int GetParameter(const char *key, const char *def, char *value, uint32_t len) = 0; + +public: + static inline std::shared_ptr paramMoc = nullptr; +}; + +class ParamMoc : public IParamMoc { +public: + MOCK_METHOD4(GetParameter, int(const char *key, const char *def, char *value, uint32_t len)); +}; +} // namespace AppFileService +} // namespace OHOS +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_ENVIRONMENT_PARAMETER_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_atomicfile/fs_atomicfile_test.cpp b/interfaces/test/unittest/js/mod_fs/class_atomicfile/fs_atomicfile_test.cpp new file mode 100644 index 000000000..f506c732f --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_atomicfile/fs_atomicfile_test.cpp @@ -0,0 +1,366 @@ +/* + * 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 "fs_atomicfile.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace std; +namespace fs = std::filesystem; + +string g_filePath = "/data/test/FsAtomicfileTest.txt"; +string g_deleteFile = "/data/test/FsAtomicfileDelTest.txt"; + +class FsAtomicfileTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsAtomicfileTest::SetUpTestCase(void) +{ + ofstream tempfile(g_filePath); + tempfile << "hello world"; + tempfile.close(); + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsAtomicfileTest::TearDownTestCase(void) +{ + filesystem::remove(g_filePath); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsAtomicfileTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FsAtomicfileTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsAtomicfileTest_GetPath_001 + * @tc.desc: Test function of FsAtomicFile::GetPath interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_GetPath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_GetPath_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + string path = stream->GetPath(); + EXPECT_EQ(path, g_filePath); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_GetPath_001"; +} + +/** + * @tc.name: FsAtomicfileTest_GetBaseFile_001 + * @tc.desc: Test function of FsAtomicFile::GetBaseFile interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_GetBaseFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_GetBaseFile_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->GetBaseFile(); + EXPECT_TRUE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_GetBaseFile_001"; +} + +/** + * @tc.name: FsAtomicfileTest_GetBaseFile_002 + * @tc.desc: Test function of FsAtomicFile::GetBaseFile interface for path > PATH_MAX. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_GetBaseFile_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_GetBaseFile_002"; + + size_t largeLength = static_cast(PATH_MAX) + 1; + string largeString(largeLength, 'a'); + + auto ret = FsAtomicFile::Constructor(largeString); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->GetBaseFile(); + EXPECT_FALSE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_GetBaseFile_002"; +} + +/** + * @tc.name: FsAtomicfileTest_GetBaseFile_003 + * @tc.desc: Test function of FsAtomicFile::GetBaseFile interface for failed realpath. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_GetBaseFile_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_GetBaseFile_003"; + + string path = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + auto ret = FsAtomicFile::Constructor(path); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->GetBaseFile(); + EXPECT_FALSE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_GetBaseFile_003"; +} + +/** + * @tc.name: FsAtomicfileTest_GetBaseFile_004 + * @tc.desc: Test function of FsAtomicFile::GetBaseFile interface for failed open. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_GetBaseFile_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_GetBaseFile_004"; + + string path = "/data/test/aaaaaaaaaa.txt"; + + auto ret = FsAtomicFile::Constructor(path); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->GetBaseFile(); + EXPECT_FALSE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_GetBaseFile_004"; +} + +/** + * @tc.name: FsAtomicfileTest_StartWrite_001 + * @tc.desc: Test function of FsAtomicFile::StartWrite interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_StartWrite_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_StartWrite_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + EXPECT_TRUE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_StartWrite_001"; +} + +/** + * @tc.name: FsAtomicfileTest_StartWrite_002 + * @tc.desc: Test function of FsAtomicFile::StartWrite interface for no parent dir. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_StartWrite_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_StartWrite_002"; + + string path = "/data/local/tmp/test/test/test/test.txt"; + + auto ret = FsAtomicFile::Constructor(path); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + EXPECT_FALSE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_StartWrite_002"; +} + +/** + * @tc.name: FsAtomicfileTest_StartWrite_003 + * @tc.desc: Test function of FsAtomicFile::StartWrite interface for no permission. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_StartWrite_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_StartWrite_003"; + + string path = "/sys/kernel/address_bits"; + + auto ret = FsAtomicFile::Constructor(path); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + EXPECT_FALSE(retFl.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_StartWrite_003"; +} + +/** + * @tc.name: FsAtomicfileTest_FinishWrite_001 + * @tc.desc: Test function of FsAtomicFile::FinishWrite interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_FinishWrite_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_FinishWrite_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + ASSERT_TRUE(retFl.IsSuccess()); + string newPath = retFl.GetData().value(); + ofstream tempfile(newPath); + tempfile << "hello world"; + tempfile.close(); + + auto retFW = stream->FinishWrite(); + EXPECT_TRUE(retFW.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_FinishWrite_001"; +} + +/** + * @tc.name: FsAtomicfileTest_FailWrite_001 + * @tc.desc: Test function of FsAtomicFile::FailWrite interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_FailWrite_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_FailWrite_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + ASSERT_TRUE(retFl.IsSuccess()); + string newPath = retFl.GetData().value(); + ofstream tempfile(newPath); + tempfile << "hello world"; + tempfile.close(); + + auto retFW = stream->FailWrite(); + EXPECT_TRUE(retFW.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_FailWrite_001"; +} + +/** + * @tc.name: FsAtomicfileTest_Delete_001 + * @tc.desc: Test function of FsAtomicFile::Delete interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_Delete_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_Delete_001"; + + auto ret = FsAtomicFile::Constructor(g_deleteFile); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto retFl = stream->StartWrite(); + ASSERT_TRUE(retFl.IsSuccess()); + string newPath = retFl.GetData().value(); + ofstream tempfile(newPath); + tempfile << "hello world"; + tempfile.close(); + + auto retFW = stream->Delete(); + EXPECT_TRUE(retFW.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_Delete_001"; +} + +/** + * @tc.name: FsAtomicfileTest_ReadFully_001 + * @tc.desc: Test function of FsAtomicFile::ReadFully interface for succ. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_ReadFully_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_ReadFully_001"; + + auto ret = FsAtomicFile::Constructor(g_filePath); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto result = stream->ReadFully(); + ASSERT_TRUE(result.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_ReadFully_001"; +} + +/** + * @tc.name: FsAtomicfileTest_ReadFully_002 + * @tc.desc: Test function of FsAtomicFile::ReadFully interface for valied path. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsAtomicfileTest, FsAtomicfileTest_ReadFully_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsAtomicfileTest-begin FsAtomicfileTest_ReadFully_002"; + + auto ret = FsAtomicFile::Constructor("aaaaaaaaaaaaaaaa"); + ASSERT_TRUE(ret.IsSuccess()); + + shared_ptr stream(move(ret.GetData().value())); + auto result = stream->ReadFully(); + ASSERT_FALSE(result.IsSuccess()); + + GTEST_LOG_(INFO) << "FsAtomicfileTest-end FsAtomicfileTest_ReadFully_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_file/fs_file_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_file/fs_file_mock_test.cpp index 0dcd0e963..90cc1f29f 100644 --- a/interfaces/test/unittest/js/mod_fs/class_file/fs_file_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_file/fs_file_mock_test.cpp @@ -75,12 +75,12 @@ void FsFileMockTest::TearDown(void) } /** -* @tc.name: FsFileMockTest_GetPath_001 -* @tc.desc: Test function of GetPath() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetPath_001 + * @tc.desc: Test function of GetPath() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetPath_001, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetPath_001"; @@ -100,12 +100,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetPath_001, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetPath_002 -* @tc.desc: Test function of GetPath() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetPath_002 + * @tc.desc: Test function of GetPath() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetPath_002, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetPath_002"; @@ -119,12 +119,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetPath_002, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetName_003 -* @tc.desc: Test function of GetName() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetName_003 + * @tc.desc: Test function of GetName() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_003, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetName_003"; @@ -138,12 +138,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_003, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetName_004 -* @tc.desc: Test function of GetName() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetName_004 + * @tc.desc: Test function of GetName() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_004, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetName_004"; @@ -157,12 +157,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_004, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetParent_005 -* @tc.desc: Test function of GetParent() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetParent_005 + * @tc.desc: Test function of GetParent() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_005, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetParent_005"; @@ -176,12 +176,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_005, testing::ext::TestSize.Le } /** -* @tc.name: FsFileMockTest_GetName_006 -* @tc.desc: Test function of GetName() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetName_006 + * @tc.desc: Test function of GetName() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_006, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetName_006"; @@ -201,12 +201,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_006, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetParent_007 -* @tc.desc: Test function of GetParent() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetParent_007 + * @tc.desc: Test function of GetParent() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_007, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetParent_007"; @@ -226,12 +226,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_007, testing::ext::TestSize.Le } /** -* @tc.name: FsFileMockTest_GetName_008 -* @tc.desc: Test function of GetName() interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetName_008 + * @tc.desc: Test function of GetName() interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_008, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetName_008"; @@ -251,12 +251,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetName_008, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_GetParent_009 -* @tc.desc: Test function of GetParent() interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_GetParent_009 + * @tc.desc: Test function of GetParent() interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_009, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_GetParent_009"; @@ -276,12 +276,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_GetParent_009, testing::ext::TestSize.Le } /** -* @tc.name: FsFileMockTest_Lock_010 -* @tc.desc: Test function of Lock() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_Lock_010 + * @tc.desc: Test function of Lock() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_Lock_010, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_Lock_010"; @@ -294,12 +294,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_Lock_010, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileMockTest_Lock_011 -* @tc.desc: Test function of Lock() interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_Lock_011 + * @tc.desc: Test function of Lock() interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_Lock_011, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_Lock_011"; @@ -312,12 +312,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_Lock_011, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileMockTest_TryLock_012 -* @tc.desc: Test function of TryLock() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_TryLock_012 + * @tc.desc: Test function of TryLock() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_TryLock_012, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_TryLock_012"; @@ -330,12 +330,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_TryLock_012, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_TryLock_013 -* @tc.desc: Test function of TryLock() interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_TryLock_013 + * @tc.desc: Test function of TryLock() interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_TryLock_013, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_TryLock_013"; @@ -348,12 +348,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_TryLock_013, testing::ext::TestSize.Leve } /** -* @tc.name: FsFileMockTest_UnLock_014 -* @tc.desc: Test function of UnLock() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_UnLock_014 + * @tc.desc: Test function of UnLock() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_UnLock_014, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_UnLock_014"; @@ -366,12 +366,12 @@ HWTEST_F(FsFileMockTest, FsFileMockTest_UnLock_014, testing::ext::TestSize.Level } /** -* @tc.name: FsFileMockTest_UnLock_015 -* @tc.desc: Test function of UnLock() interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileMockTest_UnLock_015 + * @tc.desc: Test function of UnLock() interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileMockTest, FsFileMockTest_UnLock_015, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileMockTest-begin FsFileMockTest_UnLock_015"; diff --git a/interfaces/test/unittest/js/mod_fs/class_file/fs_file_test.cpp b/interfaces/test/unittest/js/mod_fs/class_file/fs_file_test.cpp index 242d472ff..e432f66f6 100644 --- a/interfaces/test/unittest/js/mod_fs/class_file/fs_file_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_file/fs_file_test.cpp @@ -29,8 +29,8 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - std::unique_ptr fileEntity; - std::unique_ptr fsFile; + unique_ptr fileEntity; + unique_ptr fsFile; }; void FsFileTest::SetUpTestCase(void) @@ -47,13 +47,13 @@ void FsFileTest::SetUp(void) { GTEST_LOG_(INFO) << "SetUp"; - fileEntity = std::make_unique(); + fileEntity = make_unique(); const int fdValue = 3; const bool isClosed = false; - fileEntity->fd_ = std::make_unique(fdValue, isClosed); + fileEntity->fd_ = make_unique(fdValue, isClosed); fileEntity->path_ = "/data/test/file_test.txt"; fileEntity->uri_ = ""; - fsFile = std::make_unique(std::move(fileEntity)); + fsFile = make_unique(move(fileEntity)); } void FsFileTest::TearDown(void) @@ -62,12 +62,12 @@ void FsFileTest::TearDown(void) } /** -* @tc.name: FsFileTest_Constructor_001 -* @tc.desc: Test function of FsFile::Constructor() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_Constructor_001 + * @tc.desc: Test function of FsFile::Constructor() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_Constructor_001, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_Constructor_001"; @@ -79,12 +79,12 @@ HWTEST_F(FsFileTest, FsFileTest_Constructor_001, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetFD_002 -* @tc.desc: Test function of GetFD() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetFD_002 + * @tc.desc: Test function of GetFD() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetFD_002, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetFD_002"; @@ -96,17 +96,17 @@ HWTEST_F(FsFileTest, FsFileTest_GetFD_002, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetFD_003 -* @tc.desc: Test function of GetFD() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetFD_003 + * @tc.desc: Test function of GetFD() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetFD_003, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetFD_003"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->GetFD(); EXPECT_EQ(result.IsSuccess(), false); @@ -114,17 +114,17 @@ HWTEST_F(FsFileTest, FsFileTest_GetFD_003, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetPath_004 -* @tc.desc: Test function of GetPath() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetPath_004 + * @tc.desc: Test function of GetPath() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetPath_004, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetPath_004"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->GetPath(); EXPECT_EQ(result.IsSuccess(), false); @@ -132,17 +132,17 @@ HWTEST_F(FsFileTest, FsFileTest_GetPath_004, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetName_005 -* @tc.desc: Test function of GetName() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetName_005 + * @tc.desc: Test function of GetName() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetName_005, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetName_005"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->GetName(); EXPECT_EQ(result.IsSuccess(), false); @@ -150,17 +150,17 @@ HWTEST_F(FsFileTest, FsFileTest_GetName_005, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetParent_006 -* @tc.desc: Test function of GetParent() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetParent_006 + * @tc.desc: Test function of GetParent() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetParent_006, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetParent_006"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->GetParent(); EXPECT_EQ(result.IsSuccess(), false); @@ -168,17 +168,17 @@ HWTEST_F(FsFileTest, FsFileTest_GetParent_006, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_Lock_007 -* @tc.desc: Test function of Lock() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_Lock_007 + * @tc.desc: Test function of Lock() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_Lock_007, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_Lock_007"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->Lock(true); EXPECT_EQ(result.IsSuccess(), false); @@ -186,17 +186,17 @@ HWTEST_F(FsFileTest, FsFileTest_Lock_007, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_TryLock_008 -* @tc.desc: Test function of TryLock() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_TryLock_008 + * @tc.desc: Test function of TryLock() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_TryLock_008, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_TryLock_008"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->TryLock(true); EXPECT_EQ(result.IsSuccess(), false); @@ -204,17 +204,17 @@ HWTEST_F(FsFileTest, FsFileTest_TryLock_008, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_UnLock_009 -* @tc.desc: Test function of UnLock() interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_UnLock_009 + * @tc.desc: Test function of UnLock() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_UnLock_009, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_UnLock_009"; - fsFile = std::make_unique(nullptr); + fsFile = make_unique(nullptr); auto result = fsFile->UnLock(); EXPECT_EQ(result.IsSuccess(), false); @@ -222,12 +222,12 @@ HWTEST_F(FsFileTest, FsFileTest_UnLock_009, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetName_010 -* @tc.desc: Test function of GetName() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetName_010 + * @tc.desc: Test function of GetName() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetName_010, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetName_010"; @@ -240,12 +240,12 @@ HWTEST_F(FsFileTest, FsFileTest_GetName_010, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetParent_011 -* @tc.desc: Test function of GetParent() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetParent_011 + * @tc.desc: Test function of GetParent() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetParent_011, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetParent_011"; @@ -258,12 +258,12 @@ HWTEST_F(FsFileTest, FsFileTest_GetParent_011, testing::ext::TestSize.Level1) } /** -* @tc.name: FsFileTest_GetPath_012 -* @tc.desc: Test function of GetPath() interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: FsFileTest_GetPath_012 + * @tc.desc: Test function of GetPath() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(FsFileTest, FsFileTest_GetPath_012, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "FsFileTest-begin FsFileTest_GetPath_012"; diff --git a/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_mock_test.cpp new file mode 100644 index 000000000..321d4f59e --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_mock_test.cpp @@ -0,0 +1,250 @@ +/* + * 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 "file_entity.h" +#include "fs_randomaccessfile.h" +#include "uv_fs_mock.h" + + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FsRandomAccessFileMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +protected: + std::unique_ptr rafEntity; + std::unique_ptr raf; +}; + +void FsRandomAccessFileMockTest::SetUpTestCase(void) +{ + uvMock = std::make_shared(); + Uvfs::ins = uvMock; + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsRandomAccessFileMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvMock = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsRandomAccessFileMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + rafEntity = std::make_unique(); + const int fdValue = 3; + const bool isClosed = false; + rafEntity->fd = std::make_unique(fdValue, isClosed); + rafEntity->filePointer = 0; + raf = std::make_unique(std::move(rafEntity)); +} + +void FsRandomAccessFileMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_ReadSync_001 + * @tc.desc: Test function of ReadSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_ReadSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_ReadSync_001"; + + ArrayBuffer buffer(malloc(100), 100); + EXPECT_CALL(*uvMock, uv_fs_read(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + auto result = raf->ReadSync(buffer, std::nullopt); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_ReadSync_001"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_ReadSync_002 + * @tc.desc: Test function of ReadSync() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_ReadSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_ReadSync_002"; + + ArrayBuffer buffer(malloc(100), 100); + ReadOptions options; + options.offset = 10; + options.length = 10; + raf->rafEntity->filePointer = 20; + + EXPECT_CALL(*uvMock, uv_fs_read(_, _, _, _, _, _, _)).WillOnce(Return(0)); + auto result = raf->ReadSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), true); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_ReadSync_002"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_WriteSync_003 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_WriteSync_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_WriteSync_003"; + + std::string data = "test data"; + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + auto result = raf->WriteSync(data, std::nullopt); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_WriteSync_003"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_WriteSync_004 + * @tc.desc: Test function of WriteSync() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_WriteSync_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_WriteSync_004"; + + std::string data = "test data"; + WriteOptions options; + options.length = 4; + options.offset = 0; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(0)); + auto result = raf->WriteSync(data, options); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_WriteSync_004"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_WriteSync_005 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_WriteSync_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_WriteSync_005"; + + ArrayBuffer buffer(malloc(100), 100); + WriteOptions options; + options.length = 4; + options.offset = 0; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + auto result = raf->WriteSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_WriteSync_005"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_WriteSync_006 + * @tc.desc: Test function of WriteSync() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_WriteSync_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_WriteSync_006"; + + ArrayBuffer buffer(malloc(100), 100); + WriteOptions options; + options.length = 4; + options.offset = 0; + + EXPECT_CALL(*uvMock, uv_fs_write(_, _, _, _, _, _, _)).WillOnce(Return(0)); + auto result = raf->WriteSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), true); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_WriteSync_006"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_CloseSync_007 + * @tc.desc: Test function of CloseSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_CloseSync_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_CloseSync_007"; + + EXPECT_CALL(*uvMock, uv_fs_close(_, _, _, _)).WillOnce(Return(-1)); + auto result = raf->CloseSync(); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_CloseSync_007"; +} + +/** + * @tc.name: FsRandomAccessFileMockTest_CloseSync_008 + * @tc.desc: Test function of CloseSync() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + +*/ +HWTEST_F(FsRandomAccessFileMockTest, FsRandomAccessFileMockTest_CloseSync_008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileMockTest_CloseSync_008"; + + EXPECT_CALL(*uvMock, uv_fs_close(_, _, _, _)).WillOnce(Return(0)); + auto result = raf->CloseSync(); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileMockTest_CloseSync_008"; +} + +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_test.cpp b/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_test.cpp new file mode 100644 index 000000000..5930ef014 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_randomaccessfile/fs_randomaccessfile_test.cpp @@ -0,0 +1,417 @@ +/* + * 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 "file_entity.h" +#include "fs_randomaccessfile.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FsRandomAccessFileTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +protected: + std::unique_ptr rafEntity; + std::unique_ptr raf; +}; + +void FsRandomAccessFileTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsRandomAccessFileTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsRandomAccessFileTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + rafEntity = std::make_unique(); + const int fdValue = 3; + const bool isClosed = false; + rafEntity->fd = std::make_unique(fdValue, isClosed); + rafEntity->filePointer = 0; + raf = std::make_unique(std::move(rafEntity)); +} + +void FsRandomAccessFileTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +// 测试Constructor +/** + * @tc.name: FsRandomAccessFileTest_Constructor_001 + * @tc.desc: Test function of Constructor() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_Constructor_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_Constructor_001"; + + auto result = FsRandomAccessFile::Constructor(); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_Constructor_001"; +} + +// 测试GetFD +/** + * @tc.name: FsRandomAccessFileTest_GetFD_002 + * @tc.desc: Test function of GetFD() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_GetFD_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_GetFD_002"; + + auto result = raf->GetFD(); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_GetFD_002"; +} + +/** + * @tc.name: FsRandomAccessFileTest_GetFD_003 + * @tc.desc: Test function of GetFD() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_GetFD_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_GetFD_003"; + + raf = std::make_unique(nullptr); + auto result = raf->GetFD(); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_GetFD_003"; +} + +// GetFPointer +/** + * @tc.name: FsRandomAccessFileTest_GetFPointer_004 + * @tc.desc: Test function of GetFPointer() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_GetFPointer_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_GetFPointer_004"; + + raf->rafEntity->filePointer = 100; + auto result = raf->GetFPointer(); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_GetFPointer_004"; +} + +/** + * @tc.name: FsRandomAccessFileTest_GetFPointer_005 + * @tc.desc: Test function of GetFPointer() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_GetFPointer_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_GetFPointer_005"; + + raf = std::make_unique(nullptr); + auto result = raf->GetFPointer(); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_GetFPointer_005"; +} + +// SetFilePointerSync +/** + * @tc.name: FsRandomAccessFileTest_SetFilePointerSync_006 + * @tc.desc: Test function of SetFilePointerSync() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_SetFilePointerSync_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_SetFilePointerSync_006"; + + auto result = raf->SetFilePointerSync(50); + EXPECT_EQ(result.IsSuccess(), true); + EXPECT_EQ(raf->rafEntity->filePointer, 50); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_SetFilePointerSync_006"; +} + +/** + * @tc.name: FsRandomAccessFileTest_SetFilePointerSync_007 + * @tc.desc: Test function of SetFilePointerSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_SetFilePointerSync_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_SetFilePointerSync_007"; + + raf = std::make_unique(nullptr); + auto result = raf->SetFilePointerSync(50); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_SetFilePointerSync_007"; +} + +// ReadSync +/** + * @tc.name: FsRandomAccessFileTest_ReadSync_008 + * @tc.desc: Test function of ReadSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_ReadSync_008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_ReadSync_008"; + + raf = std::make_unique(nullptr); + ArrayBuffer buffer(malloc(100), 100); + + auto result = raf->ReadSync(buffer, std::nullopt); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_ReadSync_008"; +} + +/** + * @tc.name: FsRandomAccessFileTest_ReadSync_009 + * @tc.desc: Test function of ReadSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_ReadSync_009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_ReadSync_009"; + + ArrayBuffer buffer(malloc(100), 100); + ReadOptions options; + options.offset = -5; + + auto result = raf->ReadSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_ReadSync_009"; +} + +/** + * @tc.name: FsRandomAccessFileTest_ReadSync_010 + * @tc.desc: Test function of ReadSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_ReadSync_010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_ReadSync_010"; + + ArrayBuffer buffer(malloc(100), 100); + ReadOptions options; + options.length = -1; + + auto result = raf->ReadSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_ReadSync_010"; +} + +// WriteSync +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_011 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_011, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_011"; + + raf = std::make_unique(nullptr); + std::string data = "test data"; + auto result = raf->WriteSync(data, std::nullopt); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_011"; +} + +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_012 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_012, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_012"; + + raf = std::make_unique(nullptr); + ArrayBuffer buffer(malloc(100), 100); + auto result = raf->WriteSync(buffer, std::nullopt); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_012"; +} + +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_013 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_013, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_013"; + + std::string data = "test data"; + WriteOptions options; + options.offset = -5; + + auto result = raf->WriteSync(data, options); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_013"; +} + +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_014 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_014, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_014"; + + ArrayBuffer buffer(malloc(100), 100); + WriteOptions options; + options.offset = -5; + + auto result = raf->WriteSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_014"; +} + +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_015 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_015, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_015"; + + std::string data = "test data"; + WriteOptions options; + options.length = -5; + + auto result = raf->WriteSync(data, options); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_015"; +} + +/** + * @tc.name: FsRandomAccessFileTest_WriteSync_016 + * @tc.desc: Test function of WriteSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_WriteSync_016, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_WriteSync_016"; + + ArrayBuffer buffer(malloc(100), 100); + WriteOptions options; + options.length = -5; + + auto result = raf->WriteSync(buffer, options); + EXPECT_EQ(result.IsSuccess(), false); + free(buffer.buf); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_WriteSync_016"; +} + +// CloseSync +/** + * @tc.name: FsRandomAccessFileTest_CloseSync_017 + * @tc.desc: Test function of CloseSync() interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + + */ +HWTEST_F(FsRandomAccessFileTest, FsRandomAccessFileTest_CloseSync_017, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-begin FsRandomAccessFileTest_CloseSync_017"; + + raf = std::make_unique(nullptr); + auto result = raf->CloseSync(); + EXPECT_EQ(result.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsRandomAccessFileMockTest-end FsRandomAccessFileTest_CloseSync_017"; +} + +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_mock_test.cpp new file mode 100644 index 000000000..734a1d6ab --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_mock_test.cpp @@ -0,0 +1,102 @@ +/* + * 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 "fs_reader_iterator.h" +#include "read_lines_core.h" +#include "uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FsReaderIteratorMockTest : public testing::Test { +public: + static std::filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +filesystem::path FsReaderIteratorMockTest::tempFilePath; + +void FsReaderIteratorMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = std::filesystem::temp_directory_path() / "test_file.txt"; + ofstream tempfile(tempFilePath); + tempfile << ""; + tempfile.close(); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void FsReaderIteratorMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove(tempFilePath); + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void FsReaderIteratorMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FsReaderIteratorMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsReaderIteratorMockTest_Next_001 + * @tc.desc: Test FsReaderIterator::Next for success case + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsReaderIteratorMockTest, FsReaderIteratorMockTest_Next_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsReaderIteratorMockTest-begin FsReaderIteratorMockTest_Next_001"; + + std::string path = tempFilePath.string(); + std::optional option = std::nullopt; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(1)); + + auto result = ReadLinesCore::DoReadLines(path, option); + EXPECT_TRUE(result.IsSuccess()); + + auto iterator = result.GetData().value(); + ASSERT_NE(iterator, nullptr); + + auto nextResult = iterator->Next(); + EXPECT_TRUE(nextResult.IsSuccess()); + EXPECT_TRUE(nextResult.GetData().value().done); + EXPECT_EQ(nextResult.GetData().value().value, ""); + + GTEST_LOG_(INFO) << "FsReaderIteratorMockTest-end FsReaderIteratorMockTest_Next_001"; +} + +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_test.cpp b/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_test.cpp new file mode 100644 index 000000000..91729572d --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_readeriterator/fs_reader_iterator_test.cpp @@ -0,0 +1,80 @@ +/* + * 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 "fs_reader_iterator.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FsReaderIteratorTest : public testing::Test { +public: + static std::filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +filesystem::path FsReaderIteratorTest::tempFilePath; + +void FsReaderIteratorTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = std::filesystem::temp_directory_path() / "fs_reader_iterator_test_file.txt"; + ofstream tempfile(tempFilePath); + tempfile << "Test content\n123\n456"; + tempfile.close(); +} + +void FsReaderIteratorTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove(tempFilePath); +} + +void FsReaderIteratorTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FsReaderIteratorTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsReaderIteratorTest_Constructor_001 + * @tc.desc: Test FsReaderIterator::Constructor for success case + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsReaderIteratorTest, FsReaderIteratorTest_Constructor_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsReaderIteratorTest-begin FsReaderIteratorTest_Constructor_001"; + + auto result = FsReaderIterator::Constructor(); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsReaderIteratorTest-end FsReaderIteratorTest_Constructor_001"; +} + +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_mock_test.cpp index 98093ee64..2de8331e0 100644 --- a/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_mock_test.cpp @@ -38,7 +38,7 @@ public: void FsStatMockTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; - sys = std::make_shared(); + sys = make_shared(); System::ins = sys; } @@ -70,17 +70,17 @@ HWTEST_F(FsStatMockTest, FsStatMockTest_GetLocation_001, testing::ext::TestSize. { GTEST_LOG_(INFO) << "FsStatMockTes-begin FsStatMockTest_GetLocation_001"; - std::unique_ptr statEntity; - std::unique_ptr fsStat; - statEntity = std::make_unique(); - statEntity->fileInfo_ = std::make_unique(); + unique_ptr statEntity; + unique_ptr fsStat; + statEntity = make_unique(); + statEntity->fileInfo_ = make_unique(); statEntity->fileInfo_->isPath = true; int length = 100; - string testPath = "/test/path"; - statEntity->fileInfo_->path = std::make_unique(length); + string testPath = "/test/stat_path"; + statEntity->fileInfo_->path = make_unique(length); strncpy_s(statEntity->fileInfo_->path.get(), length, testPath.c_str(), testPath.size()); statEntity->fileInfo_->path.get()[99] = '\0'; - fsStat = std::make_unique(std::move(statEntity)); + fsStat = make_unique(move(statEntity)); EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillOnce(Return(1)); EXPECT_EQ(fsStat->GetLocation(), 1); @@ -99,15 +99,15 @@ HWTEST_F(FsStatMockTest, FsStatMockTest_GetLocation_002, testing::ext::TestSize. { GTEST_LOG_(INFO) << "FsStatMockTes-begin FsStatMockTest_GetLocation_002"; - std::unique_ptr statEntity; - std::unique_ptr fsStat; - statEntity = std::make_unique(); - statEntity->fileInfo_ = std::make_unique(); + unique_ptr statEntity; + unique_ptr fsStat; + statEntity = make_unique(); + statEntity->fileInfo_ = make_unique(); statEntity->fileInfo_->isPath = false; - const int fdValue = 3; + const int fdValue = 3; //模拟fd为3 const bool isClosed = false; - statEntity->fileInfo_->fdg = std::make_unique(fdValue, isClosed); - fsStat = std::make_unique(std::move(statEntity)); + statEntity->fileInfo_->fdg = make_unique(fdValue, isClosed); + fsStat = make_unique(move(statEntity)); EXPECT_CALL(*sys, fgetxattr(_, _, _, _)).WillOnce(Return(1)); EXPECT_EQ(fsStat->GetLocation(), 1); diff --git a/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_test.cpp b/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_test.cpp index 15a8640f2..3e74ed320 100644 --- a/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/class_stat/fs_stat_test.cpp @@ -17,7 +17,6 @@ #include - namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; using namespace testing::ext; diff --git a/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_mock_test.cpp new file mode 100644 index 000000000..5641bd86b --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_mock_test.cpp @@ -0,0 +1,191 @@ +/* + * 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 "c_mock.h" +#include "create_stream_core.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace std; + +static const string g_streamFilePath = "/data/test/FsStreamCoreTest.txt"; + +class FsStreamMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + CMock::EnableMock(); + int32_t fd = open(g_streamFilePath.c_str(), CREATE | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + CMock::DisableMock(); + rmdir(g_streamFilePath.c_str()); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: FsStreamSeekTest_0001 + * @tc.desc: Test function of Seek() interface for fail fseek. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamMockTest, FsStreamSeekTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamMockTest-begin FsStreamSeekTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(g_streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto mock_ = CMock::GetMock(); + EXPECT_CALL(*mock_, fseek(testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + + auto retSk = result->Seek(1); + EXPECT_FALSE(retSk.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamMockTest-end FsStreamSeekTest_0001"; +} + +/** + * @tc.name: FsStreamSeekTest_0002 + * @tc.desc: Test function of Seek() interface for fail ftell. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamMockTest, FsStreamSeekTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamMockTest-begin FsStreamSeekTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(g_streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto mock_ = CMock::GetMock(); + EXPECT_CALL(*mock_, fseek(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + EXPECT_CALL(*mock_, ftell(testing::_)).WillOnce(testing::Return(-1)); + + auto retSk = result->Seek(1); + EXPECT_FALSE(retSk.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamMockTest-end FsStreamSeekTest_0002"; +} + +/** + * @tc.name: FsStreamWriteTest_0001 + * @tc.desc: Test function of Write() interface for string fail fseek. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamMockTest, FsStreamWriteTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamMockTest-begin FsStreamWriteTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(g_streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto mock_ = CMock::GetMock(); + EXPECT_CALL(*mock_, fseek(testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + + WriteOptions opt; + opt.offset = 5; + auto retWr = result->Write("FsStreamWriteTest_0001", opt); + EXPECT_FALSE(retWr.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamMockTest-end FsStreamWriteTest_0001"; +} + +/** + * @tc.name: FsStreamWriteTest_0002 + * @tc.desc: Test function of Write() interface for ArrayBuffer fail fseek. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamMockTest, FsStreamWriteTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamMockTest-begin FsStreamWriteTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(g_streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto mock_ = CMock::GetMock(); + EXPECT_CALL(*mock_, fseek(testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + + WriteOptions opt; + opt.offset = 5; + string buf = "FsStreamWriteTest_0002"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), buf.length()), opt); + EXPECT_FALSE(retWr.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamMockTest-end FsStreamWriteTest_0002"; +} + +/** + * @tc.name: FsStreamReadTest_0001 + * @tc.desc: Test function of Read() interface for fail fseek. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamMockTest, FsStreamReadTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamMockTest-begin FsStreamReadTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(g_streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + + auto mock_ = CMock::GetMock(); + EXPECT_CALL(*mock_, fseek(testing::_, testing::_, testing::_)).WillOnce(testing::Return(-1)); + + ReadOptions opt; + opt.offset = 5; + auto retRd = result->Read(arrayBuffer, opt); + EXPECT_FALSE(retRd.IsSuccess()); + + free(buffer); + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamMockTest-end FsStreamReadTest_0001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_test.cpp b/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_test.cpp new file mode 100644 index 000000000..770069c81 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_stream/fs_stream_test.cpp @@ -0,0 +1,791 @@ +/* + * 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 "create_stream_core.h" +#include "fs_utils.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; + +static const string streamFilePath = "/data/test/FsStreamCoreTest.txt"; + +class FsStreamTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(streamFilePath.c_str(), CREATE | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(streamFilePath.c_str()); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** + * @tc.name: FsStreamCloseTest_0001 + * @tc.desc: Test function of Close() interface for close success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamCloseTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamCloseTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamCloseTest_0001"; +} + +/** + * @tc.name: FsStreamCloseTest_0002 + * @tc.desc: Test function of Close() interface for close fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamCloseTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamCloseTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + retCs = result->Close(); + EXPECT_FALSE(retCs.IsSuccess()); + auto err = retCs.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900005); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamCloseTest_0002"; +} + +/** + * @tc.name: FsStreamFlushTest_0001 + * @tc.desc: Test function of Flush() interface for null fp. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamFlushTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamFlushTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + auto retFl = result->Flush(); + EXPECT_FALSE(retFl.IsSuccess()); + auto err = retFl.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900005); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamFlushTest_0001"; +} + +/** + * @tc.name: FsStreamFlushTest_0002 + * @tc.desc: Test function of Flush() interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamFlushTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamFlushTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retFl = result->Flush(); + ASSERT_TRUE(retFl.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamFlushTest_0002"; +} + +/** + * @tc.name: FsStreamSeekTest_0001 + * @tc.desc: Test function of Seek() interface for null fp. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamSeekTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamSeekTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + auto retSk = result->Seek(0); + EXPECT_FALSE(retSk.IsSuccess()); + auto err = retSk.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamSeekTest_0001"; +} + +/** + * @tc.name: FsStreamSeekTest_0002 + * @tc.desc: Test function of Seek() interface for error whence < SEEK_SET (0). + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamSeekTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamSeekTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + optional opt = -1; + auto retSk = result->Seek(0, opt); + EXPECT_FALSE(retSk.IsSuccess()); + auto err = retSk.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamSeekTest_0002"; +} + +/** + * @tc.name: FsStreamSeekTest_0003 + * @tc.desc: Test function of Seek() interface for error whence > SEEK_END (2). + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamSeekTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamSeekTest_0003"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + optional opt = 3; + auto retSk = result->Seek(0, opt); + EXPECT_FALSE(retSk.IsSuccess()); + auto err = retSk.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamSeekTest_0003"; +} + +/** + * @tc.name: FsStreamSeekTest_0004 + * @tc.desc: Test function of Seek() interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamSeekTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamSeekTest_0004"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retSk = result->Seek(1); + ASSERT_TRUE(retSk.IsSuccess()); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamSeekTest_0004"; +} + +/** + * @tc.name: FsStreamWriteTest_0001 + * @tc.desc: Test function of Write() interface for string single argument fail null fp. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + auto retWr = result->Write("FsStreamWriteTest_0001"); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900005); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0001"; +} + +/** + * @tc.name: FsStreamWriteTest_0002 + * @tc.desc: Test function of Write() interface for ArrayBuffer single argument fail null fp. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + string buf = "FsStreamWriteTest_0001"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22)); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900005); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0002"; +} + +/** + * @tc.name: FsStreamWriteTest_0003 + * @tc.desc: Test function of Write() interface for string error offset. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0003"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.offset = -1; + + auto retWr = result->Write("FsStreamWriteTest_0003", opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0003"; +} + +/** + * @tc.name: FsStreamWriteTest_0004 + * @tc.desc: Test function of Write() interface for ArrayBuffer error offset. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0004"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.offset = -1; + + string buf = "FsStreamWriteTest_0004"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22), opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0004"; +} + +/** + * @tc.name: FsStreamWriteTest_0005 + * @tc.desc: Test function of Write() interface for string error encoding. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0005"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.encoding = "utf-16"; + + auto retWr = result->Write("FsStreamWriteTest_0005", opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0005"; +} + +/** + * @tc.name: FsStreamWriteTest_0006 + * @tc.desc: Test function of Write() interface for ArrayBuffer error encoding. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0006"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.encoding = "utf-16"; + + string buf = "FsStreamWriteTest_0006"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22), opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0004"; +} + +#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) || defined(__LP64__) +/** + * @tc.name: FsStreamWriteTest_0007 + * @tc.desc: Test function of Write() interface for string > UINT_MAX. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0007"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + size_t largeLength = static_cast(UINT_MAX) + 1; + string largeString(largeLength, 'a'); + + auto retWr = result->Write(largeString); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0005"; +} + +/** + * @tc.name: FsStreamWriteTest_0008 + * @tc.desc: Test function of Write() interface for ArrayBuffer > UINT_MAX. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0008"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + size_t largeLength = static_cast(UINT_MAX) + 1; + string largeString(largeLength, 'a'); + + auto retWr = result->Write(ArrayBuffer(static_cast(largeString.data()), largeLength)); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0008"; +} +#endif + +/** + * @tc.name: FsStreamWriteTest_0009 + * @tc.desc: Test function of Write() interface for string length < 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0009"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.length = -1; + + auto retWr = result->Write("FsStreamWriteTest_0009", opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0009"; +} + +/** + * @tc.name: FsStreamWriteTest_0010 + * @tc.desc: Test function of Write() interface for ArrayBuffer length < 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0010"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.length = -1; + + string buf = "FsStreamWriteTest_0010"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22), opt); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0010"; +} + +/** + * @tc.name: FsStreamWriteTest_0013 + * @tc.desc: Test function of Write() interface for string no permission. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0013, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0013"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retWr = result->Write("FsStreamWriteTest_0013"); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900005); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0013"; +} + +/** + * @tc.name: FsStreamWriteTest_0014 + * @tc.desc: Test function of Write() interface for ArrayBuffer no permission. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0014, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0014"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + string buf = "FsStreamWriteTest_0014"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22)); + EXPECT_FALSE(retWr.IsSuccess()); + EXPECT_EQ(retWr.GetError().GetErrNo(), 13900005); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0014"; +} + +/** + * @tc.name: FsStreamWriteTest_0015 + * @tc.desc: Test function of Write() interface for string success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0015, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0015"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.offset = 0; + opt.encoding = "utf-8"; + opt.length = 5; + + auto retWr = result->Write("FsStreamWriteTest_0015", opt); + ASSERT_TRUE(retWr.IsSuccess()); + + size_t retLen = retWr.GetData().value(); + EXPECT_EQ(retLen, 5); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0015"; +} + +/** + * @tc.name: FsStreamWriteTest_0016 + * @tc.desc: Test function of Write() interface for ArrayBuffer success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamWriteTest_0016, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamWriteTest_0016"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + WriteOptions opt; + opt.offset = 0; + opt.encoding = "utf-8"; + opt.length = 5; + + string buf = "FsStreamWriteTest_0016"; + auto retWr = result->Write(ArrayBuffer(static_cast(buf.data()), 22), opt); + ASSERT_TRUE(retWr.IsSuccess()); + + size_t retLen = retWr.GetData().value(); + EXPECT_EQ(retLen, 5); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamWriteTest_0016"; +} + +/** + * @tc.name: FsStreamReadTest_0001 + * @tc.desc: Test function of Read() interface for single argument null fp. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + auto retRd = result->Read(arrayBuffer); + EXPECT_FALSE(retRd.IsSuccess()); + EXPECT_EQ(retRd.GetError().GetErrNo(), 13900005); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0001"; +} + +/** + * @tc.name: FsStreamReadTest_0002 + * @tc.desc: Test function of Read() interface for error offset. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + ReadOptions opt; + opt.offset = -1; + + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + auto retRd = result->Read(arrayBuffer, opt); + EXPECT_FALSE(retRd.IsSuccess()); + EXPECT_EQ(retRd.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0002"; +} + +#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) || defined(__LP64__) +/** + * @tc.name: FsStreamReadTest_0003 + * @tc.desc: Test function of Read() interface for bufLen > UINT_MAX. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0003"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + size_t largeLength = static_cast(UINT_MAX) + 1; + + void *buffer = std::malloc(largeLength); + ArrayBuffer arrayBuffer(buffer, largeLength); + auto retRd = result->Read(arrayBuffer); + EXPECT_FALSE(retRd.IsSuccess()); + EXPECT_EQ(retRd.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0003"; +} +#endif + +/** + * @tc.name: FsStreamReadTest_0004 + * @tc.desc: Test function of Read() interface for error length. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0004"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + ReadOptions opt; + opt.length = -1; + + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + auto retRd = result->Read(arrayBuffer, opt); + EXPECT_FALSE(retRd.IsSuccess()); + EXPECT_EQ(retRd.GetError().GetErrNo(), 13900020); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0004"; +} + +/** + * @tc.name: FsStreamReadTest_0005 + * @tc.desc: Test function of Read() interface for no permission. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0005"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "w"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + auto retRd = result->Read(arrayBuffer); + EXPECT_FALSE(retRd.IsSuccess()); + EXPECT_EQ(retRd.GetError().GetErrNo(), 13900005); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0005"; +} + +/** + * @tc.name: FsStreamReadTest_0006 + * @tc.desc: Test function of Read() interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsStreamTest, FsStreamReadTest_0006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsStreamTest-begin FsStreamReadTest_0006"; + auto ret = CreateStreamCore::DoCreateStream(streamFilePath, "r+"); + ASSERT_TRUE(ret.IsSuccess()); + auto result = ret.GetData().value(); + + ReadOptions opt; + opt.offset = 0; + opt.length = 5; + void *buffer = std::malloc(4096); + ArrayBuffer arrayBuffer(buffer, 4096); + + auto retRd = result->Read(arrayBuffer, opt); + ASSERT_TRUE(retRd.IsSuccess()); + + size_t retLen = retRd.GetData().value(); + EXPECT_EQ(retLen, 0); + + auto retCs = result->Close(); + ASSERT_TRUE(retCs.IsSuccess()); + + GTEST_LOG_(INFO) << "FsStreamTest-end FsStreamReadTest_0006"; +} + +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.cpp b/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.cpp new file mode 100644 index 000000000..fa513e4fe --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.cpp @@ -0,0 +1,97 @@ +/* + * 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 "c_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { + +thread_local std::shared_ptr CMock::cMock = nullptr; +thread_local bool CMock::mockable = false; + +std::shared_ptr CMock::GetMock() +{ + if (cMock == nullptr) { + cMock = std::make_shared(); + } + return cMock; +} + +void CMock::EnableMock() +{ + mockable = true; +} + +void CMock::DisableMock() +{ + cMock = nullptr; + mockable = false; +} + +bool CMock::IsMockable() +{ + return mockable; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test + +#ifdef __cplusplus +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int fseek(FILE *stream, long len, int offset) +{ + if (CMock::IsMockable()) { + return CMock::GetMock()->fseek(stream, len, offset); + } + + static int (*realFseek)(FILE *, long, int) = []() { + auto func = (int (*)(FILE *, long, int))dlsym(RTLD_NEXT, "fseek"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real fseek: " << dlerror(); + } + return func; + }(); + + if (!realFseek) { + return -1; + } + + return realFseek(stream, len, offset); +} + +long ftell(FILE *stream) +{ + if (CMock::IsMockable()) { + return CMock::GetMock()->ftell(stream); + } + + static long (*realFtell)(FILE *) = []() { + auto func = (long (*)(FILE *))dlsym(RTLD_NEXT, "ftell"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real ftell: " << dlerror(); + } + return func; + }(); + + if (!realFtell) { + return -1; + } + + return realFtell(stream); +} +} // extern "C" +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.h b/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.h new file mode 100644 index 000000000..9baf3240c --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_stream/mock/c_mock.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_CLASS_STREAM_MOCK_C_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_CLASS_STREAM_MOCK_C_MOCK_H + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { + +class ICMock { +public: + virtual ~ICMock() = default; + virtual int fseek(FILE *, long, int) = 0; + virtual long ftell(FILE *) = 0; +}; + +class CMock : public ICMock { +public: + MOCK_METHOD(int, fseek, (FILE *, long, int), (override)); + MOCK_METHOD(long, ftell, (FILE *), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr cMock; + static thread_local bool mockable; +}; + +} // namespace OHOS::FileManagement::ModuleFileIO::Test +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_CLASS_STREAM_MOCK_C_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/class_tasksignal/fs_task_signal_test.cpp b/interfaces/test/unittest/js/mod_fs/class_tasksignal/fs_task_signal_test.cpp new file mode 100644 index 000000000..923204771 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_tasksignal/fs_task_signal_test.cpp @@ -0,0 +1,202 @@ +/* + * 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 "fs_task_signal.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class Assistant : public TaskSignalListener { +public: + void OnCancel() {} +}; + +class FsTaskSignalTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsTaskSignalTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsTaskSignalTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsTaskSignalTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FsTaskSignalTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsTaskSignalTest_Constructor_001 + * @tc.desc: Test function of FsTaskSignal::Constructor interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_Constructor_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_Constructor_001"; + + FsTaskSignal fsTaskSignal; + shared_ptr taskSignal = nullptr; + shared_ptr signalListener = nullptr; + + auto res = fsTaskSignal.Constructor(taskSignal, signalListener); + + EXPECT_EQ(taskSignal, nullptr); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_Constructor_001"; +} + +/** + * @tc.name: FsTaskSignalTest_Constructor_002 + * @tc.desc: Test function of FsTaskSignal::Constructor interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_Constructor_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_Constructor_002"; + + FsTaskSignal fsTaskSignal; + shared_ptr taskSignal = std::make_shared(); + shared_ptr signalListener = nullptr; + + auto res = fsTaskSignal.Constructor(taskSignal, signalListener); + + EXPECT_NE(taskSignal, nullptr); + EXPECT_EQ(res.IsSuccess(), false); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_Constructor_002"; +} + +/** + * @tc.name: FsTaskSignalTest_Constructor_003 + * @tc.desc: Test function of FsTaskSignal::Constructor interface for True. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_Constructor_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_Constructor_003"; + + FsTaskSignal fsTaskSignal; + shared_ptr taskSignal = std::make_shared(); + shared_ptr signalListener = std::make_shared(); + + auto res = fsTaskSignal.Constructor(taskSignal, signalListener); + + EXPECT_NE(signalListener, nullptr); + EXPECT_EQ(res.IsSuccess(), true); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_Constructor_003"; +} + +/** + * @tc.name: FsTaskSignalTest_Cancel_001 + * @tc.desc: Test function of FsTaskSignal::Cancel interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_Cancel_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_Cancel_001"; + + FsTaskSignal fsTaskSignal; + + auto res = fsTaskSignal.Cancel(); + + EXPECT_EQ(fsTaskSignal.taskSignal_, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_Cancel_001"; +} + +/** + * @tc.name: FsTaskSignalTest_Cancel_002 + * @tc.desc: Test function of FsTaskSignal::Cancel interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_Cancel_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_Cancel_002"; + + FsTaskSignal fsTaskSignal; + fsTaskSignal.taskSignal_ = std::make_shared(); + + auto res = fsTaskSignal.Cancel(); + + EXPECT_NE(fsTaskSignal.taskSignal_, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_Cancel_002"; +} + +/** + * @tc.name: FsTaskSignalTest_OnCancel_001 + * @tc.desc: Test function of FsTaskSignal::OnCancel interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_OnCancel_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_OnCancel_001"; + + FsTaskSignal fsTaskSignal; + + auto res = fsTaskSignal.OnCancel(); + + EXPECT_EQ(fsTaskSignal.taskSignal_, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_OnCancel_001"; +} + +/** + * @tc.name: FsTaskSignalTest_OnCancel_002 + * @tc.desc: Test function of FsTaskSignal::OnCancel interface for False. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsTaskSignalTest, FsTaskSignalTest_OnCancel_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin FsTaskSignalTest_OnCancel_002"; + + FsTaskSignal fsTaskSignal; + fsTaskSignal.taskSignal_ = std::make_shared(); + + auto res = fsTaskSignal.OnCancel(); + + EXPECT_NE(fsTaskSignal.taskSignal_, nullptr); + GTEST_LOG_(INFO) << "NClassTest-end FsTaskSignalTest_OnCancel_002"; +} + +} // OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp new file mode 100644 index 000000000..fe585ef71 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_file_watcher_mock_test.cpp @@ -0,0 +1,1324 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include "eventfd_mock.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" +#include "inotify_mock.h" +#include "mock_watcher_callback.h" +#include "poll_mock.h" +#include "securec.h" +#include "unistd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class FsFileWatcherMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsFileWatcherMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + EventfdMock::EnableMock(); + InotifyMock::EnableMock(); + PollMock::EnableMock(); + UnistdMock::EnableMock(); +} + +void FsFileWatcherMockTest::TearDownTestCase(void) +{ + EventfdMock::DisableMock(); + InotifyMock::DisableMock(); + PollMock::DisableMock(); + UnistdMock::DisableMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsFileWatcherMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void FsFileWatcherMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +inline const int32_t EXPECTED_WD = 100; +inline const int32_t UNEXPECTED_WD = 200; + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyId_001 + * @tc.desc: Test function of FsFileWatcher::GetNotifyId interface. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyId_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyId_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + int32_t expected = -1; + // Do testing + int32_t result = watcher.GetNotifyId(); + // Verify results + EXPECT_EQ(result, expected); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyId_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_001 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto eventfdMock = EventfdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::Return(2)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result); + EXPECT_EQ(watcher.notifyFd_, 1); + EXPECT_EQ(watcher.eventFd_, 2); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_002 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when inotify_init fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_InitNotify_003 + * @tc.desc: Test function of FsFileWatcher::InitNotify interface for FAILURE when eventfd fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_InitNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_InitNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto eventfdMock = EventfdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + bool result = watcher.InitNotify(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_FALSE(result); + EXPECT_EQ(watcher.notifyFd_, 1); + EXPECT_EQ(watcher.eventFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_InitNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_001 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS when path is not watched. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_001"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_001"; + info->events = IN_CREATE | IN_DELETE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + // 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_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_002 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS when path is already watched with same + * events. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_002"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_002"; + info->events = IN_CREATE | IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).Times(0); + // Do testing + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + int32_t result = watcher.StartNotify(info); + // Verify results + EXPECT_EQ(result, ERRNO_NOERR); + EXPECT_EQ(info->wd, EXPECTED_WD); +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_003 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when info is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing with nullptr parameter + int32_t result = watcher.StartNotify(nullptr); + // Verify results + EXPECT_EQ(result, EINVAL); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_004 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when notifyFd_ is invalid. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_004"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; + // Build test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_004"; + info->events = IN_CREATE; + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_005 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for FAILURE when inotify_add_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_005"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + // Build test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_005"; + info->events = IN_DELETE; + // Set mock behaviors for inotify_add_watch failure + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StartNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StartNotify_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StartNotify_006 + * @tc.desc: Test function of FsFileWatcher::StartNotify interface for SUCCESS when path is already watched. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StartNotify_006, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StartNotify_006"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_006"; + info->events = IN_CREATE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + auto cachedInfo = std::make_shared(nullptr); + cachedInfo->fileName = "fakePath/FsFileWatcherMockTest_StartNotify_006"; + cachedInfo->events = IN_DELETE; + cachedInfo->wd = EXPECTED_WD; + watcher.dataCache_.AddWatcherInfo(cachedInfo); + // 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_006"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_001 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_001"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_001"; + info->events = IN_CREATE | IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_002 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when info is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + int32_t result = watcher.StopNotify(nullptr); + // Verify results + EXPECT_EQ(result, EINVAL); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_003 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when notifyFd_ is invalid. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_003"; + info->events = IN_CREATE; + info->wd = EXPECTED_WD; + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_004 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when inotify_rm_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_004"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_004"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_005 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when rm watch fail. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_005"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_005"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set rm watch fail condition + watcher.closed_ = true; + watcher.reading_ = true; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_006 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when having remainingEvents but access + * file failed. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_006"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_006"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_006"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = EXPECTED_WD; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_006"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_007 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for SUCCESS when having remainingEvents and + * NotifyToWatchNewEvents success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_007"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_007"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_007"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = EXPECTED_WD; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(EXPECTED_WD)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, ERRNO_NOERR); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_007"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_008 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when having remainingEvents but + * NotifyToWatchNewEvents fails for inotify_add_watch fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_008"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_008"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_008"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = EXPECTED_WD; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_008"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_009 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when having remainingEvents but + * NotifyToWatchNewEvents fails for inotify_add_watch return another wd. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_009"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_009"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set having remainingEvents condition + auto remainingInfo = std::make_shared(nullptr); + remainingInfo->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_009"; + remainingInfo->events = IN_CREATE; + remainingInfo->wd = EXPECTED_WD; + watcher.dataCache_.AddWatcherInfo(remainingInfo); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(0); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(UNEXPECTED_WD)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_009"; +} + +/** + * @tc.name: FsFileWatcherMockTest_StopNotify_010 + * @tc.desc: Test function of FsFileWatcher::StopNotify interface for FAILURE when CloseNotifyFd fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_StopNotify_010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_StopNotify_010"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_StopNotify_010"; + info->events = IN_DELETE; + info->wd = EXPECTED_WD; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + watcher.eventFd_ = 1; + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).Times(0); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(EIO)); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + // Do testing + int32_t result = watcher.StopNotify(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_EQ(result, EIO); + EXPECT_EQ(watcher.notifyFd_, -1); + EXPECT_EQ(watcher.eventFd_, -1); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_StopNotify_010"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when run_ is true. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = true; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[0].revents has + * POLLNVAL. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([](struct pollfd *fds, nfds_t n, int timeout) { + fds[0].revents = POLLNVAL; + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[0].revents has + * POLLIN. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([](struct pollfd *fds, nfds_t n, int timeout) { + fds[0].revents = POLLIN; + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_004 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret > 0 and fds[1].revents has + * POLLIN. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_004"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + watcher.closed_ = true; // Avoid calling ReadNotifyEvent + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + fds[1].revents = POLLIN; + watcher.run_ = false; // Ensure the loop will exit + return 1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_005 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret == 0. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_005"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + watcher.run_ = false; // Ensure the loop will exit + return 0; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_005"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_006 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret < 0 and errno == EINTR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_006"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + errno = EINTR; + watcher.run_ = false; // Ensure the loop will exit + return -1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_006"; +} + +/** + * @tc.name: FsFileWatcherMockTest_GetNotifyEvent_007 + * @tc.desc: Test function of FsFileWatcher::GetNotifyEvent interface when poll returns ret < 0 and errno != EINTR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_GetNotifyEvent_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_GetNotifyEvent_007"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.run_ = false; + watcher.notifyFd_ = 1; + watcher.eventFd_ = 2; + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](struct pollfd *fds, nfds_t n, int timeout) { + errno = EIO; + watcher.run_ = false; // Ensure the loop will exit + return -1; + }); + // Do testing + watcher.GetNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_FALSE(watcher.run_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_GetNotifyEvent_007"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEventLocked_001 + * @tc.desc: Test ReadNotifyEventLocked when closed_ is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEventLocked_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEventLocked_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.closed_ = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + // Do testing + watcher.ReadNotifyEventLocked(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.reading_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEventLocked_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEventLocked_002 + * @tc.desc: Test ReadNotifyEventLocked when close after read. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEventLocked_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEventLocked_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.closed_ = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([&watcher](int fd, void *buf, size_t count) { + errno = EIO; + watcher.closed_ = true; // Set close after read condition + return 0; + }); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + watcher.ReadNotifyEventLocked(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(watcher.closed_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEventLocked_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for SUCCESS when read valid event data. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + int32_t len = static_cast(sizeof(struct inotify_event)); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(len)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for FAILURE when read returns -1. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, EIO); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_ReadNotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::ReadNotifyEvent interface for SUCCESS when read returns 0 (EOF). + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_ReadNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_ReadNotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + // Do testing + watcher.ReadNotifyEvent(); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, 0); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_ReadNotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_001 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for SUCCESS when valid event without filename. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_001"; + // Prepare test parameters + uint32_t mask = IN_CREATE; + struct inotify_event event = { .wd = EXPECTED_WD, .mask = mask, .cookie = 0, .len = 0 }; + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "fakePath/FsFileWatcherMockTest_NotifyEvent_001"; + info->events = mask; + info->wd = EXPECTED_WD; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); + // Do testing + watcher.NotifyEvent(&event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_002 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for SUCCESS when valid event with filename. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_002"; + // Prepare test parameters + const char *name = "test.txt"; + size_t len = strlen(name); + uint32_t mask = IN_CREATE; + size_t totalSize = sizeof(struct inotify_event) + len + 1; + std::vector buffer(totalSize); + struct inotify_event *event = reinterpret_cast(buffer.data()); + event->wd = EXPECTED_WD; + event->mask = mask; + event->cookie = 0; + event->len = len + 1; + char *namePtr = reinterpret_cast(event + 1); + int ret = memcpy_s(namePtr, len + 1, name, len + 1); + if (ret != 0) { + EXPECT_EQ(ret, 0); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_002"; + return; + } + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "fakePath/FsFileWatcherMockTest_NotifyEvent_002"; + info->events = mask; + info->wd = EXPECTED_WD; + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(1); + // Do testing + watcher.NotifyEvent(event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_003 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for FAILURE when event pointer is NULL. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_003"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + watcher.NotifyEvent(nullptr); + // Verify results + EXPECT_TRUE(watcher.dataCache_.wdFileNameCache_.empty()); + EXPECT_TRUE(watcher.dataCache_.watcherInfoCache_.empty()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_NotifyEvent_004 + * @tc.desc: Test function of FsFileWatcher::NotifyEvent interface for FAILURE when no matched watcher found. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_NotifyEvent_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_NotifyEvent_004"; + // Prepare test parameters + struct inotify_event event = { .wd = EXPECTED_WD, .mask = IN_CREATE, .cookie = 0, .len = 0 }; + // Prepare test condition + auto callback = std::make_shared(); + auto info = std::make_shared(callback); + info->fileName = "fakePath/FsFileWatcherMockTest_NotifyEvent_004"; + info->events = IN_MODIFY; // Not matched mask + info->wd = UNEXPECTED_WD; // Not matched wd + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.dataCache_.AddWatcherInfo(info); + // Set mock behaviors + EXPECT_CALL(*callback, InvokeCallback(testing::_, testing::_, testing::_)).Times(0); + // Do testing + watcher.NotifyEvent(&event); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + EXPECT_FALSE(watcher.dataCache_.wdFileNameCache_.empty()); + EXPECT_FALSE(watcher.dataCache_.watcherInfoCache_.empty()); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_NotifyEvent_004"; +} + +/** + * @tc.name: FsFileWatcherMockTest_AddWatcherInfo_001 + * @tc.desc: Test function of FsFileWatcher::AddWatcherInfo interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_AddWatcherInfo_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_AddWatcherInfo_001"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_001"; + info->events = IN_CREATE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + auto cachedInfo0 = std::make_shared(nullptr); + cachedInfo0->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_001_cachedInfo0"; + watcher.dataCache_.AddWatcherInfo(cachedInfo0); + + auto cachedInfo1 = std::make_shared(nullptr); + cachedInfo1->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_001"; + cachedInfo1->events = IN_DELETE; + watcher.dataCache_.AddWatcherInfo(cachedInfo1); + + auto callback = std::make_shared(); + auto cachedInfo2 = std::make_shared(callback); + cachedInfo2->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_001"; + cachedInfo2->events = IN_CREATE; + watcher.dataCache_.AddWatcherInfo(cachedInfo2); + + // Set mock behaviors + EXPECT_CALL(*callback, IsStrictEquals(testing::_)).Times(1).WillOnce(testing::Return(false)); + // Do testing + bool result = watcher.AddWatcherInfo(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + EXPECT_TRUE(result); + cachedInfo2->callback = nullptr; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_AddWatcherInfo_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_AddWatcherInfo_002 + * @tc.desc: Test function of FsFileWatcher::AddWatcherInfo interface for FAILURE when param is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_AddWatcherInfo_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_AddWatcherInfo_002"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + bool result = watcher.AddWatcherInfo(nullptr); + // Verify results + EXPECT_FALSE(result); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_AddWatcherInfo_002"; +} + +/** + * @tc.name: FsFileWatcherMockTest_AddWatcherInfo_003 + * @tc.desc: Test function of FsFileWatcher::AddWatcherInfo interface for FAILURE when having same info. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_AddWatcherInfo_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_AddWatcherInfo_003"; + // Prepare test parameters + auto info = std::make_shared(nullptr); + info->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_003"; + info->events = IN_CREATE; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + auto callback = std::make_shared(); + auto cachedInfo = std::make_shared(callback); + cachedInfo->fileName = "fakePath/FsFileWatcherMockTest_AddWatcherInfo_003"; + cachedInfo->events = IN_CREATE; + watcher.dataCache_.AddWatcherInfo(cachedInfo); + // Set mock behaviors + EXPECT_CALL(*callback, IsStrictEquals(testing::_)).Times(1).WillOnce(testing::Return(true)); + // Do testing + bool result = watcher.AddWatcherInfo(info); + // Verify results + testing::Mock::VerifyAndClearExpectations(callback.get()); + EXPECT_FALSE(result); + cachedInfo->callback = nullptr; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_AddWatcherInfo_003"; +} + +/** + * @tc.name: FsFileWatcherMockTest_RemoveWatcherInfo_001 + * @tc.desc: Test function of FsFileWatcher::RemoveWatcherInfo interface for FAILURE when param is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsFileWatcherMockTest, FsFileWatcherMockTest_RemoveWatcherInfo_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_RemoveWatcherInfo_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + // Do testing + auto result = watcher.RemoveWatcherInfo(nullptr); + // Verify results + EXPECT_EQ(result, EINVAL); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_RemoveWatcherInfo_001"; +} + +/** + * @tc.name: FsFileWatcherMockTest_DestroyTaskThead_001 + * @tc.desc: Test function of FsFileWatcher::DestroyTaskThead 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) +{ + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-begin FsFileWatcherMockTest_DestroyTaskThead_001"; + // Prepare test condition + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = true; + // Do testing + watcher.DestroyTaskThead(); + // Verify results + EXPECT_FALSE(watcher.taskRunning_); + GTEST_LOG_(INFO) << "FsFileWatcherMockTest-end FsFileWatcherMockTest_DestroyTaskThead_001"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS diff --git a/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp new file mode 100644 index 000000000..805c6af56 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/class_watcher/fs_watcher_mock_test.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "fs_err_code.h" +#include "fs_file_watcher.h" +#include "fs_watcher.h" +#include "inotify_mock.h" +#include "unistd_mock.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class FsWatcherMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void FsWatcherMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + InotifyMock::EnableMock(); + UnistdMock::EnableMock(); +} + +void FsWatcherMockTest::TearDownTestCase(void) +{ + InotifyMock::DisableMock(); + UnistdMock::DisableMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsWatcherMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void FsWatcherMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsWatcherTest_Constructor_001 + * @tc.desc: Test function of FsWatcher::Constructor interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Constructor_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Constructor_001"; + // Do testing + auto result = FsWatcher::Constructor(); + // Verify results + EXPECT_TRUE(result.IsSuccess()); + auto *watcher = result.GetData().value(); + EXPECT_NE(watcher, nullptr); + if (watcher) { + auto *watcherEntity = watcher->GetWatchEntity(); + EXPECT_NE(watcherEntity, nullptr); + } + delete watcher; + watcher = nullptr; + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Constructor_001"; +} + +/** + * @tc.name: FsWatcherTest_Start_001 + * @tc.desc: Test function of FsWatcher::Start interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_001"; + // Prepare test condition + int32_t expectedWd = 100; + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; // Valid notifyFd + watcher.taskRunning_ = true; // Avoid starting thread + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::Return(expectedWd)); + // Do testing + auto result = fsWatcher.Start(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_001"; +} + +/** + * @tc.name: FsWatcherTest_Start_002 + * @tc.desc: Test function of FsWatcher::Start interface for FAILURE when watchEntity is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_002"; + // Prepare test condition + FsWatcher fsWatcher(nullptr); + // Do testing + auto result = fsWatcher.Start(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_INVAL_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_002"; +} + +/** + * @tc.name: FsWatcherTest_Start_003 + * @tc.desc: Test function of FsWatcher::Start interface for FAILURE when StartNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Start_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Start_003"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Do testing + auto result = fsWatcher.Start(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_IO_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Start_003"; +} + +/** + * @tc.name: FsWatcherTest_Stop_001 + * @tc.desc: Test function of FsWatcher::Stop interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_001"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = 1; + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_rm_watch(testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(2).WillRepeatedly(testing::Return(0)); + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_001"; +} + +/** + * @tc.name: FsWatcherTest_Stop_002 + * @tc.desc: Test function of FsWatcher::Stop interface for FAILURE when watchEntity is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_002"; + // Prepare test condition + FsWatcher fsWatcher(nullptr); + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_INVAL_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_002"; +} + +/** + * @tc.name: FsWatcherTest_Stop_003 + * @tc.desc: Test function of FsWatcher::Stop interface for FAILURE when StopNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsWatcherMockTest, FsWatcherTest_Stop_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsWatcherMockTest-begin FsWatcherTest_Stop_003"; + // Prepare test condition + auto watchEntity = CreateUniquePtr(); + FsWatcher fsWatcher(std::move(watchEntity)); + std::shared_ptr info = std::make_shared(nullptr); + fsWatcher.GetWatchEntity()->data_ = info; + // Prepare test condition for FsFileWatcher + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.notifyFd_ = -1; // Invalid notifyFd + // Do testing + auto result = fsWatcher.Stop(); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + auto errCode = result.GetError().GetErrNo(); + EXPECT_EQ(errCode, E_IO_CODE); + GTEST_LOG_(INFO) << "FsWatcherMockTest-end FsWatcherTest_Stop_003"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h b/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h new file mode 100644 index 000000000..7e8a4cbbd --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/common/fs_err_code.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +enum FsErrCode { + E_IO_CODE = 13900005, + E_INVAL_CODE = 13900020, +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_COMMON_FS_ERR_CODE_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp new file mode 100644 index 000000000..1b140d042 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "eventfd_mock.h" + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr EventfdMock::eventfdMock = nullptr; +thread_local bool EventfdMock::mockable = false; + +std::shared_ptr EventfdMock::GetMock() +{ + if (eventfdMock == nullptr) { + eventfdMock = std::make_shared(); + } + return eventfdMock; +} + +void EventfdMock::EnableMock() +{ + mockable = true; +} + +void EventfdMock::DisableMock() +{ + eventfdMock = nullptr; + mockable = false; +} + +bool EventfdMock::IsMockable() +{ + return mockable; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#ifdef __cplusplus +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int eventfd(unsigned int count, int flags) +{ + if (EventfdMock::IsMockable()) { + return EventfdMock::GetMock()->eventfd(count, flags); + } + + static int (*realEventfd)(unsigned int, int) = []() { + auto func = (int (*)(unsigned int, int))dlsym(RTLD_NEXT, "eventfd"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real eventfd: " << dlerror(); + } + return func; + }(); + + if (!realEventfd) { + return -1; + } + + return realEventfd(count, flags); +} + +} // extern "C" +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h new file mode 100644 index 000000000..97dd8430f --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/eventfd_mock.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IEventfdMock { +public: + virtual ~IEventfdMock() = default; + virtual int eventfd(unsigned int, int) = 0; +}; + +class EventfdMock : public IEventfdMock { +public: + MOCK_METHOD(int, eventfd, (unsigned int, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr eventfdMock; + static thread_local bool mockable; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_EVENTFD_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp new file mode 100644 index 000000000..729d21a55 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "inotify_mock.h" + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr InotifyMock::inotifyMock = nullptr; +thread_local bool InotifyMock::mockable = false; + +std::shared_ptr InotifyMock::GetMock() +{ + if (inotifyMock == nullptr) { + inotifyMock = std::make_shared(); + } + return inotifyMock; +} + +void InotifyMock::EnableMock() +{ + mockable = true; +} + +void InotifyMock::DisableMock() +{ + inotifyMock = nullptr; + mockable = false; +} + +bool InotifyMock::IsMockable() +{ + return mockable; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#ifdef __cplusplus +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int inotify_init() +{ + if (InotifyMock::IsMockable()) { + return InotifyMock::GetMock()->inotify_init(); + } + + static int (*realInotifyInit)() = []() { + auto func = (int (*)())dlsym(RTLD_NEXT, "inotify_init"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real inotify_init: " << dlerror(); + } + return func; + }(); + + if (!realInotifyInit) { + return -1; + } + + return realInotifyInit(); +} + +int inotify_add_watch(int fd, const char *pathname, uint32_t mask) +{ + if (InotifyMock::IsMockable()) { + return InotifyMock::GetMock()->inotify_add_watch(fd, pathname, mask); + } + + static int (*realInotifyAddWatch)(int, const char *, uint32_t) = []() { + auto func = (int (*)(int, const char *, uint32_t))dlsym(RTLD_NEXT, "inotify_add_watch"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real inotify_add_watch: " << dlerror(); + } + return func; + }(); + + if (!realInotifyAddWatch) { + return -1; + } + + return realInotifyAddWatch(fd, pathname, mask); +} + +int inotify_rm_watch(int fd, int wd) +{ + if (InotifyMock::IsMockable()) { + return InotifyMock::GetMock()->inotify_rm_watch(fd, wd); + } + + static int (*realInotifyRmWatch)(int, int) = []() { + auto func = (int (*)(int, int))dlsym(RTLD_NEXT, "inotify_rm_watch"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real inotify_rm_watch: " << dlerror(); + } + return func; + }(); + + if (!realInotifyRmWatch) { + return -1; + } + + return realInotifyRmWatch(fd, wd); +} + +} // extern "C" +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h new file mode 100644 index 000000000..233403309 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/inotify_mock.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IInotifyMock { +public: + virtual ~IInotifyMock() = default; + virtual int inotify_init() = 0; + virtual int inotify_add_watch(int, const char *, uint32_t) = 0; + virtual int inotify_rm_watch(int, int) = 0; +}; + +class InotifyMock : public IInotifyMock { +public: + MOCK_METHOD(int, inotify_init, (), (override)); + MOCK_METHOD(int, inotify_add_watch, (int, const char *, uint32_t), (override)); + MOCK_METHOD(int, inotify_rm_watch, (int, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr inotifyMock; + static thread_local bool mockable; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_INOTIFY_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/mock_progress_listener.h b/interfaces/test/unittest/js/mod_fs/mock/mock_progress_listener.h new file mode 100644 index 000000000..e7851c98d --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/mock_progress_listener.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_PROGRESS_LISTENER_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_PROGRESS_LISTENER_H + +#include +#include "i_progress_listener.h" + +namespace OHOS::FileManagement::ModuleFileIO { +class MockProgressListener : public IProgressListener { +public: + MOCK_METHOD(void, InvokeListener, (uint64_t progressSize, uint64_t totalSize), (const, override)); +}; +} // namespace OHOS::FileManagement::ModuleFileIO + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_PROGRESS_LISTENER_H diff --git a/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h b/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h new file mode 100644 index 000000000..c1004d84f --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/mock_watcher_callback.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H + +#include +#include +#include "i_watcher_callback.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { +using namespace OHOS::FileManagement::ModuleFileIO; + +class MockWatcherCallback : public IWatcherCallback { +public: + MOCK_METHOD(bool, IsStrictEquals, (const std::shared_ptr &other), (const, override)); + MOCK_METHOD( + void, InvokeCallback, (const std::string &fileName, uint32_t event, uint32_t cookie), (const, override)); + MOCK_METHOD(std::string, GetClassName, (), (const, override)); +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_MOCK_WATCHER_CALLBACK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp new file mode 100644 index 000000000..6e2095ab2 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "poll_mock.h" + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr PollMock::pollMock = nullptr; +thread_local bool PollMock::mockable = false; + +std::shared_ptr PollMock::GetMock() +{ + if (pollMock == nullptr) { + pollMock = std::make_shared(); + } + return pollMock; +} + +void PollMock::EnableMock() +{ + mockable = true; +} + +void PollMock::DisableMock() +{ + pollMock = nullptr; + mockable = false; +} + +bool PollMock::IsMockable() +{ + return mockable; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#ifdef __cplusplus +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int poll(struct pollfd *fds, nfds_t n, int timeout) +{ + if (PollMock::IsMockable()) { + return PollMock::GetMock()->poll(fds, n, timeout); + } + + static int (*realPoll)(struct pollfd * fds, nfds_t n, int timeout) = []() { + auto func = (int (*)(struct pollfd *, nfds_t, int))dlsym(RTLD_NEXT, "poll"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real poll: " << dlerror(); + } + return func; + }(); + + if (!realPoll) { + return -1; + } + + return realPoll(fds, n, timeout); +} + +} // extern "C" +#endif \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h new file mode 100644 index 000000000..da771e4ec --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/poll_mock.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IPollMock { +public: + virtual ~IPollMock() = default; + virtual int poll(struct pollfd *, nfds_t, int) = 0; +}; + +class PollMock : public IPollMock { +public: + MOCK_METHOD(int, poll, (struct pollfd *, nfds_t, int), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr pollMock; + static thread_local bool mockable; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_POLL_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp new file mode 100644 index 000000000..cda59d9bf --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "unistd_mock.h" + +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +thread_local std::shared_ptr UnistdMock::unistdMock = nullptr; +thread_local bool UnistdMock::mockable = false; + +std::shared_ptr UnistdMock::GetMock() +{ + if (unistdMock == nullptr) { + unistdMock = std::make_shared(); + } + return unistdMock; +} + +void UnistdMock::EnableMock() +{ + mockable = true; +} + +void UnistdMock::DisableMock() +{ + unistdMock = nullptr; + mockable = false; +} + +bool UnistdMock::IsMockable() +{ + return mockable; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#ifdef __cplusplus +extern "C" { +using namespace OHOS::FileManagement::ModuleFileIO::Test; + +int access(const char *filename, int amode) +{ + if (UnistdMock::IsMockable()) { + return UnistdMock::GetMock()->access(filename, amode); + } + + static int (*realAccess)(const char *filename, int amode) = []() { + auto func = (int (*)(const char *, int))dlsym(RTLD_NEXT, "access"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real access: " << dlerror(); + } + return func; + }(); + + if (!realAccess) { + return -1; + } + + return realAccess(filename, amode); +} + +int close(int fd) +{ + if (UnistdMock::IsMockable()) { + return UnistdMock::GetMock()->close(fd); + } + + static int (*realClose)(int fd) = []() { + auto func = (int (*)(int))dlsym(RTLD_NEXT, "close"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real close: " << dlerror(); + } + return func; + }(); + + if (!realClose) { + return -1; + } + + return realClose(fd); +} + +ssize_t read(int fd, void *buf, size_t count) +{ + if (UnistdMock::IsMockable()) { + return UnistdMock::GetMock()->read(fd, buf, count); + } + + static ssize_t (*realRead)(int fd, void *buf, size_t count) = []() { + auto func = (ssize_t(*)(int, void *, size_t))dlsym(RTLD_NEXT, "read"); + if (!func) { + GTEST_LOG_(ERROR) << "Failed to resolve real read: " << dlerror(); + } + return func; + }(); + + if (!realRead) { + return 0; + } + + return realRead(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 new file mode 100644 index 000000000..ec6f961e1 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/mock/unistd_mock.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H + +#include +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class IUnistdMock { +public: + virtual ~IUnistdMock() = default; + virtual int access(const char *, int) = 0; + virtual int close(int) = 0; + virtual ssize_t read(int, void *, size_t) = 0; +}; + +class UnistdMock : public IUnistdMock { +public: + MOCK_METHOD(int, access, (const char *, int), (override)); + MOCK_METHOD(int, close, (int), (override)); + MOCK_METHOD(ssize_t, read, (int, void *, size_t), (override)); + +public: + static std::shared_ptr GetMock(); + static void EnableMock(); + static void DisableMock(); + static bool IsMockable(); + +private: + static thread_local std::shared_ptr unistdMock; + static thread_local bool mockable; +}; + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS + +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_MOCK_UNISTD_MOCK_H diff --git a/interfaces/test/unittest/js/mod_fs/properties/access_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/access_core_mock_test.cpp index 4d9355d9c..234800498 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/access_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/access_core_mock_test.cpp @@ -146,27 +146,4 @@ HWTEST_F(AccessCoreMockTest, AccessCoreMockTest_DoAccess_004, testing::ext::Test GTEST_LOG_(INFO) << "NClassTest-end AccessCoreMockTest_DoAccess_004"; } -/** - * @tc.name: AccessCoreMockTest_DoAccess_005 - * @tc.desc: Test function of AccessCore::DoAccess interface for success. - * @tc.size: MEDIUM - * @tc.type: FUNC - * @tc.level Level 1 - */ -HWTEST_F(AccessCoreMockTest, AccessCoreMockTest_DoAccess_005, testing::ext::TestSize.Level1) -{ - GTEST_LOG_(INFO) << "AccessCoreMockTest-begin AccessCoreMockTest_DoAccess_005"; - - std::string path = DISTRIBUTED_FILE_PREFIX; - AccessModeType mode = AccessModeType::EXIST; - AccessFlag flag = LOCAL_FLAG; - - EXPECT_CALL(*uvMock, uv_fs_access(_, _, _, _, _)).WillOnce(Return(0)); - - auto res = AccessCore::DoAccess(path, mode, flag); - EXPECT_EQ(res.IsSuccess(), true); - - GTEST_LOG_(INFO) << "AccessCoreMockTest-end AccessCoreMockTest_DoAccess_005"; -} - } // OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/access_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/access_core_test.cpp index b7966bd3c..17a131590 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/access_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/access_core_test.cpp @@ -24,7 +24,6 @@ namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; using namespace testing::ext; using namespace std; - const mode_t DIR_PERMISSIONS = 0755; class AccessCoreTest : public testing::Test { @@ -74,8 +73,7 @@ bool CreateDirectoryRecursive(const std::string& path) pos++; } - while ((pos = path.find('/', pos)) != std::string::npos) - { + while ((pos = path.find('/', pos)) != std::string::npos) { dir = path.substr(0, pos++); if (dir.empty()) { continue; @@ -87,8 +85,7 @@ bool CreateDirectoryRecursive(const std::string& path) } } - if (mkdir(path.c_str(), DIR_PERMISSIONS) == -1 && errno != EEXIST) - { + if (mkdir(path.c_str(), DIR_PERMISSIONS) == -1 && errno != EEXIST) { return false; } return true; @@ -212,7 +209,7 @@ HWTEST_F(AccessCoreTest, AccessCoreTest_DoAccess_006, testing::ext::TestSize.Lev { GTEST_LOG_(INFO) << "AccessCoreTest-begin AccessCoreTest_DoAccess_006"; - std::string path = "test"; + std::string path = "AccessCoreTest"; AccessModeType mode = AccessModeType::EXIST; AccessFlag flag = LOCAL_FLAG; diff --git a/interfaces/test/unittest/js/mod_fs/properties/close_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/close_core_test.cpp index 866d9cbe0..f61b20fcb 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/close_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/close_core_test.cpp @@ -44,7 +44,6 @@ public: * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(CloseCoreTest, DoCloseTestFd_0001, testing::ext::TestSize.Level1) { @@ -59,13 +58,70 @@ HWTEST_F(CloseCoreTest, DoCloseTestFd_0001, testing::ext::TestSize.Level1) GTEST_LOG_(INFO) << "CloseCoreTest-end DoCloseTestFd_0001"; } +/** +* @tc.name: DoCloseTestFd_0002 +* @tc.desc: Test function of DoClose() interface for sucess. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(CloseCoreTest, DoCloseTestFd_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseCoreTest-begin DoCloseTestFd_0002"; + int32_t fd = open(FILE_PATH, O_RDWR); + if (fd <= 0) { + close(fd); + ASSERT_TRUE(false); + } + + auto ret = CloseCore::DoClose(fd); + EXPECT_TRUE(ret.IsSuccess()); + + int32_t fdEnd = open(FILE_PATH, O_RDWR); + if (fdEnd <= 0) { + close(fdEnd); + ASSERT_TRUE(false); + } + EXPECT_EQ(fdEnd, fd); + + ret = CloseCore::DoClose(fd); + EXPECT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "CloseCoreTest-end DoCloseTestFd_0002"; +} + +/** +* @tc.name: DoCloseTestFd_0003 +* @tc.desc: Test function of DoClose() interface for failed. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(CloseCoreTest, DoCloseTestFd_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CloseCoreTest-begin DoCloseTestFd_0003"; + int32_t fd = open(FILE_PATH, O_RDWR); + if (fd <= 0) { + close(fd); + ASSERT_TRUE(false); + } + auto ret = CloseCore::DoClose(fd); + EXPECT_TRUE(ret.IsSuccess()); + + ret = CloseCore::DoClose(fd); + EXPECT_FALSE(ret.IsSuccess()); + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900008); + + GTEST_LOG_(INFO) << "CloseCoreTest-end DoCloseTestFd_0003"; +} + /** * @tc.name: DoCloseTestFile_0001 * @tc.desc: Test function of DoClose() interface for success. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(CloseCoreTest, DoCloseTestFile_0001, testing::ext::TestSize.Level1) { @@ -87,7 +143,6 @@ HWTEST_F(CloseCoreTest, DoCloseTestFile_0001, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(CloseCoreTest, DoCloseTestFile_0002, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp new file mode 100644 index 000000000..6e832264a --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_core_mock_test.cpp @@ -0,0 +1,548 @@ +/* + * 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 + +#include "copy_core.h" +#include "inotify_mock.h" +#include "mock_progress_listener.h" +#include "mock/uv_fs_mock.h" +#include "poll_mock.h" +#include "unistd_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CopyCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; + + static const string testDir; + static const string srcDir; + static const string destDir; + static const string srcFile; + static const string destFile; + +private: + static constexpr mode_t permission0755 = 0755; + static constexpr mode_t permission0644 = 0644; +}; + +const string CopyCoreMockTest::testDir = "/data/test"; +const string CopyCoreMockTest::srcDir = testDir + "/src"; +const string CopyCoreMockTest::destDir = testDir + "/dest"; +const string CopyCoreMockTest::srcFile = srcDir + "/src.txt"; +const string CopyCoreMockTest::destFile = destDir + "/dest.txt"; + +void CopyCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + mkdir(testDir.c_str(), permission0755); + mkdir(srcDir.c_str(), permission0755); + mkdir(destDir.c_str(), permission0755); + int32_t fd = open(srcFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; + InotifyMock::EnableMock(); + PollMock::EnableMock(); + UnistdMock::EnableMock(); +} + +void CopyCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + int ret = remove(srcFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(srcDir.c_str()); + rmdir(destDir.c_str()); + rmdir(testDir.c_str()); + Uvfs::ins = nullptr; + uvMock = nullptr; + InotifyMock::DisableMock(); + PollMock::DisableMock(); + UnistdMock::DisableMock(); +} + +void CopyCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CopyCoreMockTest::TearDown(void) +{ + CopyCore::callbackMap_.clear(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: CopyCoreMockTest_CopyFile_001 + * @tc.desc: Test function of CopyCore::CopyFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopyFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopyFile_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = CopyCoreMockTest::srcFile; + infos->destPath = CopyCoreMockTest::destFile; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*uvMock, uv_fs_sendfile(_, _, _, _, _, _, _)).WillOnce(Return(-1)); + + auto res = CopyCore::CopyFile(srcFile, destFile, infos); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopyFile_001"; +} + +/** + * @tc.name: CopyCoreMockTest_DoCopy_001 + * @tc.desc: Test function of CopyCore::DoCopy interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_DoCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_DoCopy_001"; + + string srcUri = "file://" + srcFile; + string destUri = "file://" + destFile; + optional options; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*uvMock, uv_fs_sendfile(_, _, _, _, _, _, _)).WillOnce(Return(0)); + + auto res = CopyCore::DoCopy(srcUri, destUri, options); + EXPECT_EQ(res.IsSuccess(), true); + EXPECT_TRUE(filesystem::exists(destFile)); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_DoCopy_001"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_001 + * @tc.desc: Test function of CopyCore::CopySubDir interface for success. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_001"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_002 + * @tc.desc: Test CopyCore::CopySubDir when iter == CopyCore::callbackMap_.end() + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_002"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + CopyCore::callbackMap_.clear(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_002"; +} + +/** + * @tc.name: CopyCoreMockTest_CopySubDir_003 + * @tc.desc: Test CopyCore::CopySubDir when iter->second == nullptr + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CopySubDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CopySubDir_003"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + GTEST_LOG_(INFO) << "Open test file failed! ret: " << fd << ", errno: " << errno; + EXPECT_TRUE(false); + } + close(fd); + + auto inotifyMock = InotifyMock::GetMock(); + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto unistdMock = UnistdMock::GetMock(); + CopyCore::callbackMap_[*infos] = nullptr; + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*inotifyMock, inotify_add_watch(testing::_, testing::_, testing::_)).WillOnce(testing::Return(0)); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, UNKNOWN_ERR); + + int ret = remove(subFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + CopyCore::callbackMap_.clear(); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CopySubDir_003"; +} + +/** + * @tc.name: CopyCoreMockTest_ReceiveComplete_001 + * @tc.desc: Test CopyCore::ReceiveComplete in normal case + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReceiveComplete_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReceiveComplete_001"; + + auto mockListener = std::make_shared(); + auto callback = std::make_shared(mockListener); + callback->maxProgressSize = 50; + auto entry = std::make_shared(callback); + entry->progressSize = 100; + entry->totalSize = 200; + + EXPECT_CALL(*mockListener, InvokeListener(entry->progressSize, entry->totalSize)).Times(1); + CopyCore::ReceiveComplete(entry); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReceiveComplete_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReceiveComplete_002 + * @tc.desc: Test CopyCore::ReceiveComplete when processedSize < entry->callback->maxProgressSize + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReceiveComplete_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReceiveComplete_002"; + + auto mockListener = std::make_shared(); + auto callback = std::make_shared(mockListener); + callback->maxProgressSize = 100; + auto entry = std::make_shared(callback); + entry->progressSize = 50; // Mock valid progressSize + entry->totalSize = 200; // Mock valid totalSize, and progressSize < totalSize + + EXPECT_CALL(*mockListener, InvokeListener(testing::_, testing::_)).Times(0); + CopyCore::ReceiveComplete(entry); + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReceiveComplete_002"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_001 + * @tc.desc: Test function of CopyCoreMockTest::ReadNotifyEvent interface for SUCCESS when read valid event data. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_001"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + int32_t len = static_cast(sizeof(struct inotify_event)); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(len)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_002 + * @tc.desc: Test function of CopyCore::ReadNotifyEvent interface for FAILURE when read returns -1. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_002"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, EIO); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_002"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEvent_003 + * @tc.desc: Test function of CopyCore::ReadNotifyEvent interface for SUCCESS when read returns 0 (EOF). + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEvent_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEvent_003"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce(testing::SetErrnoAndReturn(0, 0)); + // Do testing + CopyCore::ReadNotifyEvent(infos); + // Verify results + EXPECT_NE(callback, nullptr); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_EQ(errno, 0); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEvent_003"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEventLocked_001 + * @tc.desc: Test ReadNotifyEventLocked when closed is false. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEventLocked_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEventLocked_001"; + // Prepare test condition + auto infos = make_shared(); + auto callback = std::make_shared(nullptr); + callback->closed = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).Times(1).WillOnce(testing::Return(0)); + EXPECT_CALL(*unistdMock, close(testing::_)).Times(0); + // Do testing + CopyCore::ReadNotifyEventLocked(infos, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(callback->reading); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEventLocked_001"; +} + +/** + * @tc.name: CopyCoreMockTest_ReadNotifyEventLocked_002 + * @tc.desc: Test ReadNotifyEventLocked when close after read. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_ReadNotifyEventLocked_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_ReadNotifyEventLocked_002"; + // Prepare test condition + auto infos = make_shared(); + auto callback = std::make_shared(nullptr); + callback->closed = false; + // Set mock behaviors + auto unistdMock = UnistdMock::GetMock(); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([callback](int fd, void *buf, size_t count) { + errno = EIO; + callback->closed = true; + return 0; + }); + EXPECT_CALL(*unistdMock, close(testing::_)).WillRepeatedly(testing::Return(0)); + // Do testing + CopyCore::ReadNotifyEventLocked(infos, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); + EXPECT_FALSE(callback->closed); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_ReadNotifyEventLocked_002"; +} + +/** + * @tc.name: CopyCoreMockTest_GetNotifyId_001 + * @tc.desc: Test function of CopyCore::GetNotifyId interface for SUCCESS. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_GetNotifyId_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_GetNotifyId_001"; + // Prepare test condition + auto infos = make_shared(); + infos->run = true; + infos->exceptionCode = ERRNO_NOERR; + infos->eventFd = 1; + infos->notifyFd = 1; + + auto callback = CopyCore::RegisterListener(infos); + // Set mock behaviors + auto pollMock = PollMock::GetMock(); + EXPECT_CALL(*pollMock, poll(testing::_, testing::_, testing::_)) + .Times(1) + .WillOnce([infos](struct pollfd *fds, nfds_t n, int timeout) { + fds[1].revents = POLLIN; + infos->run = false; // Ensure the loop will exit + return 1; + }); + // Do testing + CopyCore::GetNotifyEvent(infos); + // Verify results + testing::Mock::VerifyAndClearExpectations(pollMock.get()); + EXPECT_NE(callback, nullptr); + EXPECT_FALSE(infos->run); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_GetNotifyId_001"; +} + +/** + * @tc.name: CopyCoreMockTest_GetNotifyId_002 + * @tc.desc: Test function of CopyCore::GetNotifyId interface fails when callback is nullptr. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_GetNotifyId_002, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_GetNotifyId_002"; + // Prepare test condition + auto infos = make_shared(); + // Do testing + CopyCore::GetNotifyEvent(infos); + // Verify results + EXPECT_EQ(infos->exceptionCode, EINVAL); + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_GetNotifyId_002"; +} + +/** + * @tc.name: CopyCoreMockTest_CreateFileInfos_001 + * @tc.desc: Test function of CopyCore::CreateFileInfos interface with listener and copySignal. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreMockTest, CopyCoreMockTest_CreateFileInfos_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreMockTest-begin CopyCoreMockTest_CreateFileInfos_001"; + + auto copySignal = std::make_shared(); + copySignal->taskSignal_ = std::make_shared(); + auto options = std::make_optional(); + options->progressListener = std::make_shared(); + options->copySignal = std::move(copySignal); + + auto [errCode, infos] = CopyCore::CreateFileInfos(srcFile, destFile, options); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_NE(infos, nullptr); + if (infos) { + EXPECT_TRUE(infos->hasListener); + EXPECT_NE(infos->listener, nullptr); + EXPECT_NE(infos->taskSignal, nullptr); + } + + GTEST_LOG_(INFO) << "CopyCoreMockTest-end CopyCoreMockTest_CreateFileInfos_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp new file mode 100644 index 000000000..6c9da75ac --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_core_test.cpp @@ -0,0 +1,1145 @@ +/* + * 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 "copy_core.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CopyCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const string testDir; + static const string srcDir; + static const string destDir; + static const string srcFile; + static const string destFile; + +private: + static constexpr mode_t permission0755 = 0755; // rwxr-xr-x + static constexpr mode_t permission0644 = 0644; // rw-r--r-- +}; + +const string CopyCoreTest::testDir = "/data/test"; +const string CopyCoreTest::srcDir = testDir + "/src"; +const string CopyCoreTest::destDir = testDir + "/dest"; +const string CopyCoreTest::srcFile = srcDir + "/src.txt"; +const string CopyCoreTest::destFile = destDir + "/dest.txt"; + +void CopyCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + mkdir(testDir.c_str(), permission0755); + mkdir(srcDir.c_str(), permission0755); + mkdir(destDir.c_str(), permission0755); + int32_t fd = open(srcFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); +} + +void CopyCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + int ret = remove(srcFile.c_str()); + EXPECT_TRUE(ret == 0); + rmdir(srcDir.c_str()); + rmdir(destDir.c_str()); + rmdir(testDir.c_str()); +} + +void CopyCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CopyCoreTest::TearDown(void) +{ + CopyCore::callbackMap_.clear(); + GTEST_LOG_(INFO) << "TearDown"; +} + +inline const int32_t EXPECTED_WD = 100; +inline const int32_t UNEXPECTED_WD = 200; + +/** + * @tc.name: CopyCoreTest_IsValidUri_001 + * @tc.desc: Test function of CopyCore::IsValidUri interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsValidUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsValidUri_001"; + + string validUri = "file://data/test/file.txt"; + auto res = CopyCore::IsValidUri(validUri); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsValidUri_001"; +} + +/** + * @tc.name: CopyCoreTest_IsValidUri_002 + * @tc.desc: Test function of CopyCore::IsValidUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsValidUri_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsValidUri_002"; + + string invalidUri = "invalid://data/test/file.txt"; + auto res = CopyCore::IsValidUri(invalidUri); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsValidUri_002"; +} + +/** + * @tc.name: CopyCoreTest_IsRemoteUri_001 + * @tc.desc: Test function of CopyCore::IsRemoteUri interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsRemoteUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsRemoteUri_001"; + + string remoteUri = "file://data/test/file.txt?networkid=123"; + auto res = CopyCore::IsRemoteUri(remoteUri); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsRemoteUri_001"; +} + +/** + * @tc.name: CopyCoreTest_IsRemoteUri_002 + * @tc.desc: Test function of CopyCore::IsRemoteUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsRemoteUri_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsRemoteUri_002"; + + string localUri = "file://data/test/file.txt"; + auto res = CopyCore::IsRemoteUri(localUri); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsRemoteUri_002"; +} + +/** + * @tc.name: CopyCoreTest_IsDirectory_001 + * @tc.desc: Test function of CopyCore::IsDirectory interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsDirectory_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsDirectory_001"; + + auto res = CopyCore::IsDirectory(srcDir); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsDirectory_001"; +} + +/** + * @tc.name: CopyCoreTest_IsDirectory_002 + * @tc.desc: Test function of CopyCore::IsDirectory interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsDirectory_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsDirectory_002"; + + auto res = CopyCore::IsDirectory(srcFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsDirectory_002"; +} + +/** + * @tc.name: CopyCoreTest_IsFile_001 + * @tc.desc: Test function of CopyCore::IsFile interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsFile_001"; + + auto res = CopyCore::IsFile(srcFile); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsFile_001"; +} + +/** + * @tc.name: CopyCoreTest_IsFile_002 + * @tc.desc: Test function of CopyCore::IsFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsFile_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsFile_002"; + + auto res = CopyCore::IsFile(srcDir); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsFile_002"; +} + +/** + * @tc.name: CopyCoreTest_IsMediaUri_001 + * @tc.desc: Test function of CopyCore::IsMediaUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_IsMediaUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_IsMediaUri_001"; + + auto res = CopyCore::IsMediaUri(srcFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_IsMediaUri_001"; +} + +/** + * @tc.name: CopyCoreTest_GetFileSize_001 + * @tc.desc: Test function of CopyCore::GetFileSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetFileSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetFileSize_001"; + + auto [err, size] = CopyCore::GetFileSize(srcFile); + EXPECT_EQ(err, ERRNO_NOERR); + EXPECT_GE(size, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetFileSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetFileSize_002 + * @tc.desc: Test function of CopyCore::GetFileSize interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetFileSize_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetFileSize_002"; + + string nonExistentFile = "/data/test/non_existent.txt"; + auto [err, size] = CopyCore::GetFileSize(nonExistentFile); + EXPECT_NE(err, ERRNO_NOERR); + EXPECT_EQ(size, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetFileSize_002"; +} + +/** + * @tc.name: CopyCoreTest_CheckOrCreatePath_001 + * @tc.desc: Test function of CopyCore::CheckOrCreatePath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckOrCreatePath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckOrCreatePath_001"; + + auto res = CopyCore::CheckOrCreatePath(srcFile); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckOrCreatePath_001"; +} + +/** + * @tc.name: CopyCoreTest_CheckOrCreatePath_002 + * @tc.desc: Test function of CopyCore::CheckOrCreatePath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckOrCreatePath_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckOrCreatePath_002"; + + string newFile = destDir + "/new_file.txt"; + auto res = CopyCore::CheckOrCreatePath(newFile); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsFile(newFile)); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckOrCreatePath_002"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_001 + * @tc.desc: Test function of CopyCore::MakeDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_001"; + + string newDir = destDir + "/new_dir"; + auto res = CopyCore::MakeDir(newDir); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(newDir)); + + rmdir(newDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_001"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_002 + * @tc.desc: Test function of CopyCore::MakeDir interface for TRUE. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_002"; + + auto res = CopyCore::MakeDir(srcDir); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_002"; +} + +/** + * @tc.name: CopyCoreTest_MakeDir_003 + * @tc.desc: Test function of CopyCore::MakeDir interface for FALSE. + * @tc.size: SMALL + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_MakeDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_MakeDir_003"; + + string invalidPath = "/invalid/path/dir"; + auto res = CopyCore::MakeDir(invalidPath); + EXPECT_NE(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_MakeDir_003"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_001 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_001"; + + string srcFile = "invalid://data/test/src.txt"; + + auto res = CopyCore::ValidParams(srcFile, destFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_001"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_002 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_002"; + + string destFile = "invalid://data/test/dest.txt"; + + auto res = CopyCore::ValidParams(srcFile, destFile); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_002"; +} + +/** + * @tc.name: CopyCoreTest_ValidParams_003 + * @tc.desc: Test function of CopyCore::ValidParams interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ValidParams_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ValidParams_003"; + + string src = "file://data/test/src.txt"; + string dest = "file://data/test/dest.txt"; + + auto res = CopyCore::ValidParams(src, dest); + EXPECT_EQ(res, true); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ValidParams_003"; +} + +/** + * @tc.name: CopyCoreTest_CreateFileInfos_001 + * @tc.desc: Test function of CopyCore::CreateFileInfos interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CreateFileInfos_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CreateFileInfos_001"; + + optional options = std::make_optional(); + + auto [errCode, infos] = CopyCore::CreateFileInfos(srcFile, destFile, options); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_NE(infos, nullptr); + if (infos) { + EXPECT_FALSE(infos->hasListener); + EXPECT_EQ(infos->listener, nullptr); + EXPECT_EQ(infos->taskSignal, nullptr); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CreateFileInfos_001"; +} + +/** + * @tc.name: CopyCoreTest_CopySubDir_001 + * @tc.desc: Test function of CopyCore::CopySubDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopySubDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopySubDir_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + string destSubFile = destSubDir + "/sub_file.txt"; + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(destSubDir)); + EXPECT_TRUE(CopyCore::IsFile(destSubFile)); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopySubDir_001"; +} + +/** + * @tc.name: CopyCoreTest_CopySubDir_002 + * @tc.desc: Test function of CopyCore::CopySubDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopySubDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopySubDir_002"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + infos->notifyFd = 1; + auto res = CopyCore::CopySubDir(subDir, destSubDir, infos); + EXPECT_EQ(res, errno); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopySubDir_002"; +} + +/** + * @tc.name: CopyCoreTest_RecurCopyDir_001 + * @tc.desc: Test function of CopyCore::RecurCopyDir interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RecurCopyDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RecurCopyDir_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/sub_dir"; + auto infos = make_shared(); + auto res = CopyCore::RecurCopyDir(srcDir, destDir, infos); + string destSubFile = destSubDir + "/sub_file.txt"; + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsDirectory(destSubDir)); + EXPECT_TRUE(CopyCore::IsFile(destSubDir + "/sub_file.txt")); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RecurCopyDir_001"; +} + +/** + * @tc.name: CopyCoreTest_CopyDirFunc_001 + * @tc.desc: Test function of CopyCore::CopyDirFunc interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopyDirFunc_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopyDirFunc_001"; + + string subDir = srcDir + "/sub_dir"; + mkdir(subDir.c_str(), permission0755); + string subFile = subDir + "/sub_file.txt"; + int fd = open(subFile.c_str(), O_CREAT | O_RDWR, permission0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + string destSubDir = destDir + "/src/sub_dir"; + string destSubFile = destSubDir + "/sub_file.txt"; + string destSrcDir = destDir + "/src"; + auto infos = make_shared(); + auto res = CopyCore::CopyDirFunc(srcDir, destDir, infos); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_EQ(CopyCore::IsDirectory(destSubDir), false); + EXPECT_EQ(CopyCore::IsFile(destSubDir + "/sub_file.txt"), false); + + remove(subFile.c_str()); + rmdir(subDir.c_str()); + remove(destSubFile.c_str()); + rmdir(destSubDir.c_str()); + rmdir(destSrcDir.c_str()); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopyDirFunc_001"; +} + +/** + * @tc.name: CopyCoreTest_ExecLocal_001 + * @tc.desc: Test function of CopyCore::ExecLocal interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecLocal_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecLocal_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::ExecLocal(infos, callback); + EXPECT_EQ(res, ERRNO_NOERR); + EXPECT_TRUE(CopyCore::IsFile(destFile)); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecLocal_001"; +} + +/** + * @tc.name: CopyCoreTest_ExecLocal_002 + * @tc.desc: Test function of CopyCore::ExecLocal interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecLocal_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecLocal_002"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = srcFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::ExecLocal(infos, callback); + EXPECT_EQ(res, EINVAL); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecLocal_002"; +} + +/** + * @tc.name: CopyCoreTest_RegisterListener_001 + * @tc.desc: Test function of CopyCore::RegisterListener interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RegisterListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RegisterListener_001"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + EXPECT_NE(callback, nullptr); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_NE(iter, CopyCore::callbackMap_.end()); + } + + CopyCore::UnregisterListener(infos); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RegisterListener_001"; +} + +/** + * @tc.name: CopyCoreTest_RegisterListener_002 + * @tc.desc: Test function of CopyCore::RegisterListener interface for the case when the info already exists in + * callbackMap_. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_RegisterListener_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_RegisterListener_002"; + + auto infos = make_shared(); + auto firstCallback = CopyCore::RegisterListener(infos); + EXPECT_NE(firstCallback, nullptr); + auto secondCallback = CopyCore::RegisterListener(infos); + EXPECT_EQ(secondCallback, nullptr); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_NE(iter, CopyCore::callbackMap_.end()); + } + + CopyCore::UnregisterListener(infos); + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_RegisterListener_002"; +} + +/** + * @tc.name: CopyCoreTest_UnregisterListener_001 + * @tc.desc: Test function of CopyCore::UnregisterListener interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UnregisterListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UnregisterListener_001"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + EXPECT_NE(callback, nullptr); + + CopyCore::UnregisterListener(infos); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_EQ(iter, CopyCore::callbackMap_.end()); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UnregisterListener_001"; +} + +/** + * @tc.name: CopyCoreTest_UnregisterListener_002 + * @tc.desc: Test function of CopyCore::UnregisterListener interface for the case when the info is not registered in + * callbackMap_. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UnregisterListener_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UnregisterListener_002"; + + auto infos = make_shared(); + + CopyCore::UnregisterListener(infos); + + { + std::lock_guard lock(CopyCore::mutex_); + auto iter = CopyCore::callbackMap_.find(*infos); + EXPECT_EQ(iter, CopyCore::callbackMap_.end()); + } + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UnregisterListener_002"; +} + +/** + * @tc.name: CopyCoreTest_DoCopy_001 + * @tc.desc: Test function of CopyCore::DoCopy interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_DoCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_DoCopy_001"; + + string src = "invalid:/" + srcFile; + string dest = "invalid:/" + destFile; + optional options; + + auto res = CopyCore::DoCopy(src, dest, options); + EXPECT_FALSE(res.IsSuccess()); + auto err = res.GetError(); + EXPECT_EQ(err.GetErrNo(), E_PARAMS); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_DoCopy_001"; +} + +/** + * @tc.name: CopyCoreTest_DoCopy_002 + * @tc.desc: Test function of CopyCore::DoCopy interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_DoCopy_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_DoCopy_002"; + + string src = "file:///data/test/src/src.txt"; + string dest = "file:///data/test/dest/dest.txt"; + optional options; + + auto res = CopyCore::DoCopy(src, dest, options); + EXPECT_TRUE(res.IsSuccess()); + int ret = remove(destFile.c_str()); + EXPECT_TRUE(ret == 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_DoCopy_002"; +} + +/** + * @tc.name: CopyCoreTest_GetDirSize_001 + * @tc.desc: Test function of CopyCore::GetDirSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetDirSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetDirSize_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::GetDirSize(infos, srcDir); + EXPECT_EQ(res, 0); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetDirSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetUVEntry_001 + * @tc.desc: Test function of CopyCore::GetUVEntry interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetUVEntry_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetUVEntry_001"; + + auto infos = make_shared(); + auto res = CopyCore::GetUVEntry(infos); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetUVEntry_001"; +} + +/** + * @tc.name: CopyCoreTest_CheckFileValid_001 + * @tc.desc: Test function of CopyCore::CheckFileValid interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CheckFileValid_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CheckFileValid_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::CheckFileValid(srcFile, infos); + EXPECT_EQ(res, false); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CheckFileValid_001"; +} + +/** + * @tc.name: CopyCoreTest_UpdateProgressSize_001 + * @tc.desc: Test function of CopyCore::UpdateProgressSize interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_UpdateProgressSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_UpdateProgressSize_001"; + + auto receivedInfo = make_shared(); + auto callback = make_shared(nullptr); + + auto res = CopyCore::UpdateProgressSize(srcFile, receivedInfo, callback); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_UpdateProgressSize_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRegisteredListener_001 + * @tc.desc: Test function of CopyCore::GetRegisteredListener interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRegisteredListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRegisteredListener_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + + auto res = CopyCore::GetRegisteredListener(infos); + EXPECT_EQ(res, nullptr); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRegisteredListener_001"; +} + +/** + * @tc.name: CopyCoreTest_SubscribeLocalListener_001 + * @tc.desc: Test function of CopyCore::SubscribeLocalListener interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_SubscribeLocalListener_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_SubscribeLocalListener_001"; + + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = srcFile; + infos->destPath = destFile; + auto callback = make_shared(nullptr); + + auto res = CopyCore::SubscribeLocalListener(infos, callback); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_SubscribeLocalListener_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRealPath_001 + * @tc.desc: Test function of CopyCore::GetRealPath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRealPath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRealPath_001"; + + string path = "./data/test/src/src.txt"; + + auto res = CopyCore::GetRealPath(path); + EXPECT_EQ(res, "data/test/src/src.txt"); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRealPath_001"; +} + +/** + * @tc.name: CopyCoreTest_GetRealPath_002 + * @tc.desc: Test function of CopyCore::GetRealPath interface for TRUE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_GetRealPath_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_GetRealPath_002"; + + string path = "../data/test/src/src.txt"; + + auto res = CopyCore::GetRealPath(path); + EXPECT_EQ(res, "data/test/src/src.txt"); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_GetRealPath_002"; +} + +/** + * @tc.name: CopyCoreTest_ExecCopy_001 + * @tc.desc: Test function of CopyCore::ExecCopy interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_ExecCopy_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_ExecCopy_001"; + + auto infos = make_shared(); + infos->isFile = false; + infos->srcPath = "/data/test/src"; + infos->destPath = "/data/test/dest"; + + auto res = CopyCore::ExecCopy(infos); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_ExecCopy_001"; +} + +/** + * @tc.name: CopyCoreTest_CopyFile_001 + * @tc.desc: Test function of CopyCore::CopyFile interface for file copy FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_CopyFile_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_CopyFile_001"; + + string src = "datashare:///media/src_test.jpg"; + string dest = "datashare:///media/dest_test.jpg"; + auto infos = make_shared(); + infos->isFile = true; + infos->srcPath = src; + infos->destPath = dest; + + auto res = CopyCore::CopyFile(src, dest, infos); + EXPECT_EQ(res, errno); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_CopyFile_001"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_001 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_001"; + + auto infos = make_shared(); + infos->isFile = false; + infos->srcPath = "/data/test/src"; + infos->destPath = "/data/test/dest"; + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, nullptr); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, EINVAL); + EXPECT_FALSE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_001"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_002 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_002"; + + auto infos = make_shared(); + infos->srcPath = srcDir; + infos->destPath = destDir; + infos->isFile = true; + + auto callback = make_shared(nullptr); + + auto receiveInfo = make_shared(); + receiveInfo->path = testDir; + callback->wds.push_back({ UNEXPECTED_WD, receiveInfo }); + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, callback); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, EINVAL); + EXPECT_FALSE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_002"; +} + +/** + * @tc.name: CopyCoreTest_HandleProgress_003 + * @tc.desc: Test function of CopyCore::HandleProgress interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_HandleProgress_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_HandleProgress_003"; + + auto infos = make_shared(); + infos->srcPath = srcDir; + infos->destPath = destDir; + infos->isFile = true; + + auto callback = make_shared(nullptr); + + auto receiveInfo = make_shared(); + receiveInfo->path = srcFile; + callback->wds.push_back({ EXPECTED_WD, receiveInfo }); + + auto event = make_unique(); + event->wd = EXPECTED_WD; + event->mask = IN_MODIFY; + event->len = 0; + + auto [continueProcess, errCode, needSend] = CopyCore::HandleProgress(event.get(), infos, callback); + + EXPECT_TRUE(continueProcess); + EXPECT_EQ(errCode, ERRNO_NOERR); + EXPECT_TRUE(needSend); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_HandleProgress_003"; +} + +/** + * @tc.name: CopyCoreTest_OnFileReceive_001 + * @tc.desc: Test function of CopyCore::OnFileReceive interface fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_OnFileReceive_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_OnFileReceive_001"; + + auto infos = make_shared(); + CopyCore::OnFileReceive(infos); + EXPECT_TRUE(CopyCore::callbackMap_.empty()); + + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_OnFileReceive_001"; +} + +/** + * @tc.name: CopyCoreTest_OnFileReceive_002 + * @tc.desc: Test function of CopyCore::OnFileReceive interface when listener is nullptr. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyCoreTest, CopyCoreTest_OnFileReceive_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyCoreTest-begin CopyCoreTest_OnFileReceive_002"; + + auto infos = make_shared(); + auto callback = CopyCore::RegisterListener(infos); + CopyCore::OnFileReceive(infos); + EXPECT_NE(callback, nullptr); + if (callback) { + EXPECT_EQ(callback->listener, nullptr); + } + GTEST_LOG_(INFO) << "CopyCoreTest-end CopyCoreTest_OnFileReceive_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_dir_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_dir_core_test.cpp new file mode 100644 index 000000000..ad9b034bb --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_dir_core_test.cpp @@ -0,0 +1,295 @@ +/* + * 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 "copy_dir_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CopyDirCoreTest : public testing::Test { +public: + static filesystem::path g_srcPath; + static filesystem::path g_destPath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + void CreateTestFile(const filesystem::path& path, const string& content = "test") + { + ofstream file(path); + file << content; + } +}; + +filesystem::path CopyDirCoreTest::g_srcPath; +filesystem::path CopyDirCoreTest::g_destPath; + +void CopyDirCoreTest::SetUpTestCase(void) +{ + g_srcPath = filesystem::temp_directory_path() / "src/"; + g_destPath = filesystem::temp_directory_path() / "dest/"; + filesystem::create_directory(g_srcPath); + filesystem::create_directory(g_destPath); + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void CopyDirCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove_all(g_srcPath); + filesystem::remove_all(g_destPath); +} + +void CopyDirCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CopyDirCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_001 + * @tc.desc: Test function of DoCopyDir() interface for SUCCESS with empty directory. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_001"; + + string src = g_srcPath.string() + "/test01"; + string dest = g_destPath.string(); + filesystem::create_directories(src); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_001"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_002 + * @tc.desc: Test function of DoCopyDir() interface for FAILED with invalid mode. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_002"; + + string src = g_srcPath.string() + "/test02"; + string dest = g_destPath.string(); + filesystem::create_directories(src); + + int invalidMode = COPYMODE_MAX + 1; + auto result = CopyDirCore::DoCopyDir(src, dest, optional(invalidMode)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_002"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_003 + * @tc.desc: Test function of DoCopyDir() interface for FAILED with non-existent source. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_003"; + + string src = g_srcPath.string() + "/non_existent"; + string dest = g_destPath.string(); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_003"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_004 + * @tc.desc: Test function of DoCopyDir() interface for FAILED with invalid destination. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_004"; + + string src = g_srcPath.string(); + string dest = g_destPath.string() + "/invalid_file.txt"; + filesystem::path(dest).remove_filename(); + filesystem::create_directories(filesystem::path(dest).parent_path()); + ofstream(dest).close(); // 创建文件而非目录 + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_004"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_005 + * @tc.desc: Test function of DoCopyDir() interface for FAILED with same source and destination. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_005"; + + string src = g_srcPath.string(); + string dest = g_srcPath.string(); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_005"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_006 + * @tc.desc: Test function of DoCopyDir() interface for SUCCESS with files. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_006"; + + string src = g_srcPath.string() + "/test06"; + string dest = g_destPath.string(); + filesystem::create_directories(src); + CreateTestFile(src + "/file1.txt", "content1"); + CreateTestFile(src + "/file2.txt", "content2"); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_006"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_007 + * @tc.desc: Test function of DoCopyDir() interface for SUCCESS with subdirectories. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_007"; + + string src = g_srcPath.string() + "/test07"; + string dest = g_destPath.string(); + filesystem::create_directories(src + "/subdir1"); + filesystem::create_directories(src + "/subdir2"); + CreateTestFile(src + "/subdir1/file1.txt", "sub1_content1"); + CreateTestFile(src + "/subdir2/file2.txt", "sub2_content2"); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional()); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_007"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_008 + * @tc.desc: Test function of DoCopyDir() interface for FAILED with existing files (throw error mode). + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_008"; + + string src = g_srcPath.string() + "/test08"; + string dest = g_destPath.string(); + filesystem::create_directories(src); + CreateTestFile(src + "/file1.txt", "content1"); + + string destDir = dest + "/" + filesystem::path(src).filename().string(); + filesystem::create_directories(destDir); + CreateTestFile(destDir + "/file1.txt", "existing_content"); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional(DIRMODE_FILE_COPY_THROW_ERR)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_TRUE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_008"; +} + +/** + * @tc.name: CopyDirCoreTest_DoCopyDir_009 + * @tc.desc: Test function of DoCopyDir() interface for SUCCESS with existing files (overwrite mode). + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CopyDirCoreTest, CopyDirCoreTest_DoCopyDir_009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CopyDirCoreTest-begin CopyDirCoreTest_DoCopyDir_009"; + + string src = g_srcPath.string() + "/test09"; + string dest = g_destPath.string(); + filesystem::create_directories(src); + CreateTestFile(src + "/file1.txt", "content1"); + + string destDir = dest + "/" + filesystem::path(src).filename().string(); + filesystem::create_directories(destDir); + CreateTestFile(destDir + "/file1.txt", "existing_content"); + + auto result = CopyDirCore::DoCopyDir(src, dest, optional(DIRMODE_FILE_COPY_REPLACE)); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "CopyDirCoreTest-end CopyDirCoreTest_DoCopyDir_009"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_mock_test.cpp index af533602a..0988ca22a 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_mock_test.cpp @@ -23,7 +23,7 @@ using namespace testing; using namespace testing::ext; using namespace std; -class CopyFileCoreTest : public testing::Test { +class CopyFileCoreMockTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -32,40 +32,40 @@ public: static inline shared_ptr uvfs = nullptr; }; -void CopyFileCoreTest::SetUpTestCase(void) +void CopyFileCoreMockTest::SetUpTestCase(void) { uvfs = std::make_shared(); Uvfs::ins = uvfs; GTEST_LOG_(INFO) << "SetUpTestCase"; } -void CopyFileCoreTest::TearDownTestCase(void) +void CopyFileCoreMockTest::TearDownTestCase(void) { Uvfs::ins = nullptr; uvfs = nullptr; GTEST_LOG_(INFO) << "TearDownTestCase"; } -void CopyFileCoreTest::SetUp(void) +void CopyFileCoreMockTest::SetUp(void) { GTEST_LOG_(INFO) << "SetUp"; } -void CopyFileCoreTest::TearDown(void) +void CopyFileCoreMockTest::TearDown(void) { GTEST_LOG_(INFO) << "TearDown"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_001 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_001 * @tc.desc: Test function of CopyFileCore::ValidMode interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_001, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_001, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_001"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_001"; FileInfo src; FileInfo dest; @@ -74,19 +74,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_001, testing::ext::TestSi auto res = CopyFileCore::DoCopyFile(src, dest, mode); EXPECT_EQ(res.IsSuccess(), false); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_001"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_001"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_003 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_003 * @tc.desc: Test function of CopyFileCore::OpenFile.OpenCore interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_003, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_003, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_003"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_003"; FileInfo src; FileInfo dest; @@ -98,44 +98,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_003, testing::ext::TestSi auto res = CopyFileCore::DoCopyFile(src, dest); EXPECT_EQ(res.IsSuccess(), false); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_003"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_003"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_004 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_005 * @tc.desc: Test function of CopyFileCore::OpenFile.OpenCore interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_004, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_005, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_004"; - - FileInfo src; - FileInfo dest; - src.isPath = true; - dest.isPath = false; - src.fdg = make_unique(1); - - EXPECT_CALL(*uvfs, uv_fs_open(_, _, _, _, _, _)).Times(1).WillOnce(Return(1)); - - auto res = CopyFileCore::DoCopyFile(src, dest); - EXPECT_EQ(res.IsSuccess(), false); - - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_004"; -} - -/** - * @tc.name: CopyFileCoreTest_DoCopyFile_005 - * @tc.desc: Test function of CopyFileCore::OpenFile.OpenCore interface for FALSE. - * @tc.size: MEDIUM - * @tc.type: FUNC - * @tc.level Level 1 - */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_005, testing::ext::TestSize.Level1) -{ - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_005"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_005"; FileInfo src; FileInfo dest; @@ -151,19 +126,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_005, testing::ext::TestSi EXPECT_EQ(res.IsSuccess(), false); close(fd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_005"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_005"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_006 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_006 * @tc.desc: Test function of CopyFileCore::OpenFile.OpenCore interface for SUCCESS. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_006, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_006, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_006"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_006"; FileInfo src; FileInfo dest; @@ -179,19 +154,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_006, testing::ext::TestSi EXPECT_EQ(res.IsSuccess(), true); close(fd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_006"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_006"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_007 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_007 * @tc.desc: Test function of CopyFileCore::OpenFile.TruncateCore interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_007, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_007, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_007"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_007"; FileInfo src; FileInfo dest; @@ -208,19 +183,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_007, testing::ext::TestSi EXPECT_EQ(res.IsSuccess(), false); close(fd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_007"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_007"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_008 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_008 * @tc.desc: Test function of CopyFileCore::OpenFile.TruncateCore interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_008, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_008, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_008"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_008"; FileInfo src; FileInfo dest; @@ -237,19 +212,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_008, testing::ext::TestSi EXPECT_EQ(res.IsSuccess(), false); close(fd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_008"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_008"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_009 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_009 * @tc.desc: Test function of CopyFileCore::OpenFile.TruncateCore interface for SUCCESS. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_009, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_009, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_009"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_009"; FileInfo src; FileInfo dest; @@ -270,19 +245,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_009, testing::ext::TestSi close(srcfd); close(destfd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_009"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_009"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_0010 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_0010 * @tc.desc: Test function of CopyFileCore::OpenFile.SendFileCore interface for false. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0010, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_0010, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_0010"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_0010"; FileInfo src; FileInfo dest; @@ -303,19 +278,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0010, testing::ext::TestS EXPECT_EQ(res.IsSuccess(), false); close(srcfd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_0010"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_0010"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_0011 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_0011 * @tc.desc: Test function of CopyFileCore::OpenFile.SendFileCore interface for false. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0011, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_0011, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_0011"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_0011"; FileInfo src; FileInfo dest; @@ -336,19 +311,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0011, testing::ext::TestS EXPECT_EQ(res.IsSuccess(), false); close(srcfd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_0011"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_0011"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_0012 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_0012 * @tc.desc: Test function of CopyFileCore::OpenFile.SendFileCore interface for SUCCESS. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0012, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_0012, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_0012"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_0012"; FileInfo src; FileInfo dest; @@ -369,19 +344,19 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0012, testing::ext::TestS EXPECT_EQ(res.IsSuccess(), true); close(srcfd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_0012"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_0012"; } /** - * @tc.name: CopyFileCoreTest_DoCopyFile_0013 + * @tc.name: CopyFileCoreMockTest_DoCopyFile_0013 * @tc.desc: Test function of CopyFileCore::OpenFile.SendFileCore interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0013, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_0013, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_0013"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_0013"; FileInfo src; FileInfo dest; @@ -402,7 +377,7 @@ HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_0013, testing::ext::TestS EXPECT_EQ(res.IsSuccess(), false); close(srcfd); - GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_0013"; + GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_0013"; } } // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_test.cpp index 8d14cda0e..343446bc7 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/copy_file_core_test.cpp @@ -22,7 +22,7 @@ using namespace testing; using namespace testing::ext; using namespace std; -class CopyFileCoreMockTest : public testing::Test { +class CopyFileCoreTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -30,36 +30,36 @@ public: void TearDown(); }; -void CopyFileCoreMockTest::SetUpTestCase(void) +void CopyFileCoreTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; } -void CopyFileCoreMockTest::TearDownTestCase(void) +void CopyFileCoreTest::TearDownTestCase(void) { GTEST_LOG_(INFO) << "TearDownTestCase"; } -void CopyFileCoreMockTest::SetUp(void) +void CopyFileCoreTest::SetUp(void) { GTEST_LOG_(INFO) << "SetUp"; } -void CopyFileCoreMockTest::TearDown(void) +void CopyFileCoreTest::TearDown(void) { GTEST_LOG_(INFO) << "TearDown"; } /** - * @tc.name: CopyFileCoreMockTest_DoCopyFile_001 + * @tc.name: CopyFileCoreTest_DoCopyFile_001 * @tc.desc: Test function of CopyFileCore::ValidMode interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_001, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_001, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_001"; + GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_001"; FileInfo src; FileInfo dest; @@ -68,19 +68,19 @@ HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_001, testing::ext auto res = CopyFileCore::DoCopyFile(src, dest, mode); EXPECT_EQ(res.IsSuccess(), false); - GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_001"; + GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_001"; } /** - * @tc.name: CopyFileCoreMockTest_DoCopyFile_002 + * @tc.name: CopyFileCoreTest_DoCopyFile_002 * @tc.desc: Test function of CopyFileCore::ValidMode interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_002, testing::ext::TestSize.Level1) +HWTEST_F(CopyFileCoreTest, CopyFileCoreTest_DoCopyFile_002, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "CopyFileCoreMockTest-begin CopyFileCoreMockTest_DoCopyFile_002"; + GTEST_LOG_(INFO) << "CopyFileCoreTest-begin CopyFileCoreTest_DoCopyFile_002"; FileInfo src; FileInfo dest; @@ -92,7 +92,7 @@ HWTEST_F(CopyFileCoreMockTest, CopyFileCoreMockTest_DoCopyFile_002, testing::ext auto res = CopyFileCore::DoCopyFile(src, dest); EXPECT_EQ(res.IsSuccess(), false); - GTEST_LOG_(INFO) << "CopyFileCoreMockTest-end CopyFileCoreMockTest_DoCopyFile_002"; + GTEST_LOG_(INFO) << "CopyFileCoreTest-end CopyFileCoreTest_DoCopyFile_002"; } } // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_mock_test.cpp new file mode 100644 index 000000000..2dc12961c --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_mock_test.cpp @@ -0,0 +1,108 @@ +/* + * 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 "create_randomaccessfile_core.h" +#include "uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CreateRandomAccessFileCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void CreateRandomAccessFileCoreMockTest::SetUpTestCase(void) +{ + uvMock = std::make_shared(); + Uvfs::ins = uvMock; + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void CreateRandomAccessFileCoreMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvMock = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void CreateRandomAccessFileCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CreateRandomAccessFileCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_001 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreMockTest, CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_001, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_001"; + + string path = "/test/path.txt"; + int32_t mode = 0; + optional options = nullopt; + + EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(-1)); + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, options); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_001"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_002 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreMockTest, CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_002, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_002"; + + string path = "/test/path.txt"; + int32_t mode = 0; + RandomAccessFileOptions opts; + opts.start = 0; + opts.end = 100; + + EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(0)); + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, opts); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreMockTest_DoCreateRandomAccessFile_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_test.cpp new file mode 100644 index 000000000..848d97672 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/create_randomaccessfile_core_test.cpp @@ -0,0 +1,189 @@ +/* + * 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 "create_randomaccessfile_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class CreateRandomAccessFileCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void CreateRandomAccessFileCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void CreateRandomAccessFileCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void CreateRandomAccessFileCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void CreateRandomAccessFileCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_001 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile to verify an invalid mode. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_001, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_001"; + + string path = "/test/path.txt"; + int32_t mode = -5; + optional options = nullopt; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, options); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_001"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_002 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_002, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_002"; + + string path = "/test/path.txt"; + int32_t mode = 0; + RandomAccessFileOptions opts; + opts.start = -1; + opts.end = 100; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, opts); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_002"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_003 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_003, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_003"; + + string path = "/test/path.txt"; + int32_t mode = 0; + RandomAccessFileOptions opts; + opts.start = 10; + opts.end = -1; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, opts); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_003"; +} + +/**' + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_004 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_004, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_004"; + + int fd = -1; + optional opts = nullopt; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(fd, opts); + EXPECT_EQ(res.IsSuccess(), false); + auto err = res.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_004"; +} + +/**' + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_005 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile to verify the path is invalid. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_005, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_005"; + + string path = ""; + int32_t mode = 0; + optional options = nullopt; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(path, mode, options); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_005"; +} + +/** + * @tc.name: CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_006 + * @tc.desc: Test function of CreateRandomAccessFileCore::DoCreateRandomAccessFile interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(CreateRandomAccessFileCoreTest, CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_006, + testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "Test-begin CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_006"; + + int fd = 3; + optional opts = nullopt; + + auto res = CreateRandomAccessFileCore::DoCreateRandomAccessFile(fd, opts); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "Test-end CreateRandomAccessFileCoreTest_DoCreateRandomAccessFile_006"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/create_stream_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/create_stream_core_test.cpp new file mode 100644 index 000000000..30e1ad522 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/create_stream_core_test.cpp @@ -0,0 +1,81 @@ +/* +* 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 "create_stream_core.h" + +#define CREATE_STREAM_FILE_PATH "/data/test/CreateStreamCoreTest.txt" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +class CreateStreamCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(CREATE_STREAM_FILE_PATH, CREATE | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(CREATE_STREAM_FILE_PATH); + }; + void SetUp() {}; + void TearDown() {}; +}; +/** +* @tc.name: DoCreateStreamTest_0001 +* @tc.desc: Test function of DoCreateStream() interface for success. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(CreateStreamCoreTest, DoCreateStreamTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateStreamCoreTest-begin DoCreateStreamTest_0001"; + auto ret = CreateStreamCore::DoCreateStream(CREATE_STREAM_FILE_PATH, "r"); + ASSERT_TRUE(ret.IsSuccess()); + + auto stream = ret.GetData().value(); + ASSERT_NE(stream, nullptr); + auto retClose = stream->Close(); + EXPECT_TRUE(retClose.IsSuccess()); + + GTEST_LOG_(INFO) << "CreateStreamCoreTest-end DoCreateStreamTest_0001"; +} + +/** +* @tc.name: DoCreateStreamTest_0002 +* @tc.desc: Test function of DoCreateStream() interface for fail. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(CreateStreamCoreTest, DoCreateStreamTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CreateStreamCoreTest-begin DoCreateStreamTest_0002"; + auto ret = CreateStreamCore::DoCreateStream(CREATE_STREAM_FILE_PATH, "ssss"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "CreateStreamCoreTest-end DoCreateStreamTest_0002"; +} + +} +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/dup_core_mock_test.cpp new file mode 100644 index 000000000..826208e31 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/dup_core_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 "dup_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DupCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void DupCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void DupCoreMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvMock = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DupCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DupCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: DupCoreMockTest_DoDup_001 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreMockTest, DupCoreMockTest_DoDup_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DupCoreMockTest-begin DupCoreMockTest_DoDup_001"; + + int32_t fd = 1; + + EXPECT_CALL(*uvMock, uv_fs_readlink(_, _, _, _)).WillOnce(Return(-1)); + auto res = DupCore::DoDup(fd); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "DupCoreMockTest-end DupCoreMockTest_DoDup_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp new file mode 100644 index 000000000..e622a27f6 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/dup_core_test.cpp @@ -0,0 +1,94 @@ +/* + * 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 "dup_core.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class DupCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DupCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void DupCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void DupCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void DupCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: DupCoreTest_DoDup_001 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreTest, DupCoreTest_DoDup_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin DupCoreTest_DoDup_001"; + int32_t fd = -1; + auto res = DupCore::DoDup(fd); + + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "NClassTest-end DupCoreTest_DoDup_001"; +} + +/** + * @tc.name: DupCoreTest_DoDup_002 + * @tc.desc: Test function of DupCore::DoDup interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(DupCoreTest, DupCoreTest_DoDup_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "NClassTest-begin DupCoreTest_DoDup_002"; + int32_t fd = open("temp_file.txt", O_CREAT | O_RDWR, 0666); + ASSERT_NE(fd, -1); + close(fd); + + auto res = DupCore::DoDup(fd); + + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "NClassTest-end DupCoreTest_DoDup_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/fdatasync_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/fdatasync_core_mock_test.cpp new file mode 100644 index 000000000..c6308de50 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/fdatasync_core_mock_test.cpp @@ -0,0 +1,102 @@ +/* + * 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 "fdatasync_core.h" +#include "mock/uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FDataSyncCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void FDataSyncCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void FDataSyncCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void FDataSyncCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FDataSyncCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FDataSyncCoreMockTest_DoFDataSync_001 + * @tc.desc: Test function of FDataSyncCore::DoFDataSync interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FDataSyncCoreMockTest, FDataSyncCoreMockTest_DoFDataSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FDataSyncCoreMockTest-begin FDataSyncCoreMockTest_DoFDataSync_001"; + + int fd = 3; + + EXPECT_CALL(*uvMock, uv_fs_fdatasync(_, _, _, _)).WillOnce(Return(1)); + auto res = FDataSyncCore::DoFDataSync(fd); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FDataSyncCoreMockTest-end FDataSyncCoreMockTest_DoFDataSync_001"; +} + +/** + * @tc.name: FDataSyncCoreMockTest_DoFDataSync_002 + * @tc.desc: Test function of FDataSyncCore::DoFDataSync interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FDataSyncCoreMockTest, FDataSyncCoreMockTest_DoFDataSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FDataSyncCoreMockTest-begin FDataSyncCoreMockTest_DoFDataSync_002"; + + int fd = 3; + + EXPECT_CALL(*uvMock, uv_fs_fdatasync(_, _, _, _)).WillOnce(Return(-1)); + auto res = FDataSyncCore::DoFDataSync(fd); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FDataSyncCoreMockTest-end FDataSyncCoreMockTest_DoFDataSync_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/fdopen_stream_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/fdopen_stream_core_test.cpp new file mode 100644 index 000000000..f3be0e56b --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/fdopen_stream_core_test.cpp @@ -0,0 +1,117 @@ +/* +* 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 "fdopen_stream_core.h" + +#define FDOPEN_STREAM_FILE_PATH "/data/test/FdopenStreamCoreTest.txt" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +class FdopenStreamCoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + int32_t fd = open(FDOPEN_STREAM_FILE_PATH, CREATE | O_RDWR, 0644); + close(fd); + }; + static void TearDownTestCase() + { + rmdir(FDOPEN_STREAM_FILE_PATH); + }; + void SetUp() {}; + void TearDown() {}; +}; + +/** +* @tc.name: DoFdopenStreamTest_0001 +* @tc.desc: Test function of DoFdopenStream() interface for success. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(FdopenStreamCoreTest, DoFdopenStreamTest_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-begin DoFdopenStreamTest_0001"; + int32_t fd = open(FDOPEN_STREAM_FILE_PATH, O_RDWR); + if (fd <= 0) { + close(fd); + ASSERT_TRUE(false); + } + + auto ret = FdopenStreamCore::DoFdopenStream(fd, "r"); + ASSERT_TRUE(ret.IsSuccess()); + + auto stream = ret.GetData().value(); + ASSERT_NE(stream, nullptr); + auto retClose = stream->Close(); + EXPECT_TRUE(retClose.IsSuccess()); + + close(fd); + + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-end DoFdopenStreamTest_0001"; +} + +/** +* @tc.name: DoFdopenStreamTest_0002 +* @tc.desc: Test function of DoFdopenStream() interface for fd < 0. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(FdopenStreamCoreTest, DoFdopenStreamTest_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-begin DoFdopenStreamTest_0002"; + auto ret = FdopenStreamCore::DoFdopenStream(-1, "r"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-end DoFdopenStreamTest_0002"; +} + +/** +* @tc.name: DoFdopenStreamTest_0003 +* @tc.desc: Test function of DoFdopenStream() interface for fail. +* @tc.size: MEDIUM +* @tc.type: FUNC +* @tc.level Level 1 +*/ +HWTEST_F(FdopenStreamCoreTest, DoFdopenStreamTest_0003, testing::ext::TestSize.Level1) +{ + int32_t fd = open(FDOPEN_STREAM_FILE_PATH, O_RDWR); + if (fd <= 0) { + close(fd); + ASSERT_TRUE(false); + } + + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-begin DoFdopenStreamTest_0003"; + auto ret = FdopenStreamCore::DoFdopenStream(fd, "sssssss"); + EXPECT_FALSE(ret.IsSuccess()); + + auto err = ret.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + + close(fd); + + GTEST_LOG_(INFO) << "FdopenStreamCoreTest-end DoFdopenStreamTest_0003"; +} + +} +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/fsync_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/fsync_core_mock_test.cpp new file mode 100644 index 000000000..688a5bca0 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/fsync_core_mock_test.cpp @@ -0,0 +1,98 @@ +/* + * 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 "fsync_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class FsyncCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvfs = nullptr; +}; + +void FsyncCoreMockTest::SetUpTestCase(void) +{ + uvfs = std::make_shared(); + Uvfs::ins = uvfs; + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void FsyncCoreMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvfs = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void FsyncCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void FsyncCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: FsyncCoreMockTest_DoFsync_001 + * @tc.desc: Test function of RenameCore::DoFsync interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsyncCoreMockTest, FsyncCoreMockTest_DoFsync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsyncCoreMockTest-begin FsyncCoreMockTest_DoFsync_001"; + + EXPECT_CALL(*uvfs, uv_fs_fsync(_, _, _, _)).WillOnce(Return(-1)); + + auto res = FsyncCore::DoFsync(1); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "FsyncCoreMockTest-end FsyncCoreMockTest_DoFsync_001"; +} + +/** + * @tc.name: FsyncCoreMockTest_DoFsync_002 + * @tc.desc: Test function of RenameCore::DoFsync interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(FsyncCoreMockTest, FsyncCoreMockTest_DoFsync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FsyncCoreMockTest-begin FsyncCoreMockTest_DoFsync_002"; + + EXPECT_CALL(*uvfs, uv_fs_fsync(_, _, _, _)).WillOnce(Return(1)); + + auto res = FsyncCore::DoFsync(1); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "FsyncCoreMockTest-end FsyncCoreMockTest_DoFsync_002"; +} + + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp index dbea771a4..64387d5b4 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/listfile_core_test.cpp @@ -90,7 +90,6 @@ public: * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0001, testing::ext::TestSize.Level1) { @@ -117,7 +116,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0001, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0002, testing::ext::TestSize.Level1) { @@ -144,7 +142,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0002, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0003, testing::ext::TestSize.Level1) { @@ -167,7 +164,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0003, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0004, testing::ext::TestSize.Level1) { @@ -195,7 +191,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0004, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0005, testing::ext::TestSize.Level1) { @@ -223,7 +218,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0005, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0006, testing::ext::TestSize.Level1) { @@ -251,7 +245,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0006, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0007, testing::ext::TestSize.Level1) { @@ -278,7 +271,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0007, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0008, testing::ext::TestSize.Level1) { @@ -305,7 +297,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0008, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0009, testing::ext::TestSize.Level1) { @@ -330,7 +321,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0009, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0010, testing::ext::TestSize.Level1) { @@ -355,7 +345,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0010, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0011, testing::ext::TestSize.Level1) { @@ -379,7 +368,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0011, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0012, testing::ext::TestSize.Level1) { @@ -399,7 +387,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0012, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0013, testing::ext::TestSize.Level1) { @@ -422,7 +409,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0013, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0014, testing::ext::TestSize.Level1) { @@ -442,7 +428,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0014, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0015, testing::ext::TestSize.Level1) { @@ -476,7 +461,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0015, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0016, testing::ext::TestSize.Level1) { @@ -503,7 +487,6 @@ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0016, testing::ext::TestSize.Level * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ListFileCoreTest, DoListFileCoreTest_0017, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_fs/properties/lseek_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/lseek_core_test.cpp new file mode 100644 index 000000000..f5bd78bb7 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/lseek_core_test.cpp @@ -0,0 +1,115 @@ +/* + * 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 "lseek_core.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class LseekCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void LseekCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void LseekCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void LseekCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void LseekCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: LseekCoreTest_DoLseek_001 + * @tc.desc: Test function of LseekCore::DoLseek interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LseekCoreTest, LseekCoreTest_DoLseek_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LseekCoreTest-begin LseekCoreTest_DoLseek_001"; + + int32_t fd = -1; + int64_t offset = 0; + + auto res = LseekCore::DoLseek(fd, offset); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "LseekCoreTest-end LseekCoreTest_DoLseek_001"; +} + +/** + * @tc.name: LseekCoreTest_DoLseek_002 + * @tc.desc: Test function of LseekCore::DoLseek interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LseekCoreTest, LseekCoreTest_DoLseek_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LseekCoreTest-begin LseekCoreTest_DoLseek_002"; + + int32_t fd = 1; + int64_t offset = 0; + optional pos = std::make_optional(static_cast(-1)); + + auto res = LseekCore::DoLseek(fd, offset, pos); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "LseekCoreTest-end LseekCoreTest_DoLseek_002"; +} + +/** + * @tc.name: LseekCoreTest_DoLseek_003 + * @tc.desc: Test function of LseekCore::DoLseek interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LseekCoreTest, LseekCoreTest_DoLseek_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LseekCoreTest-begin LseekCoreTest_DoLseek_003"; + + int32_t fd = 1; + int64_t offset = 0; + optional pos = std::make_optional(SeekPos::CURRENT); + + auto res = LseekCore::DoLseek(fd, offset, pos); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "LseekCoreTest-end LseekCoreTest_DoLseek_003"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/lstat_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/lstat_core_mock_test.cpp new file mode 100644 index 000000000..691f2b3de --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/lstat_core_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 +#include + +#include "lstat_core.h" +#include "uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class LstatCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void LstatCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = make_shared(); + Uvfs::ins = uvMock; +} + +void LstatCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void LstatCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void LstatCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: LstatCoreMockTest_DoLstat_001 + * @tc.desc: Test function of LstatCore::DoLstat interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LstatCoreMockTest, LstatCoreMockTest_DoLstat_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LstatCoreMockTest-begin LstatCoreMockTest_DoLstat_001"; + + EXPECT_CALL(*uvMock, uv_fs_lstat(_, _, _, _)).WillOnce(Return(-1)); + + auto res = LstatCore::DoLstat("/data/test/lstat.txt"); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "LstatCoreMockTest-end LstatCoreMockTest_DoLstat_001"; +} + +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/lstat_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/lstat_core_test.cpp new file mode 100644 index 000000000..c40e99f2f --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/lstat_core_test.cpp @@ -0,0 +1,94 @@ +/* + * 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 "lstat_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class LstatCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void LstatCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + int32_t fd = open("/data/test/lstat.txt", CREATE | O_RDWR, 0644); + if (fd <= 0) { + ASSERT_TRUE(false); + } + close(fd); +} + +void LstatCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + rmdir("/data/test/lstat.txt"); +} + +void LstatCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void LstatCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: LstatCoreTest_DoLstat_001 + * @tc.desc: Test function of LstatCore::DoLstat interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LstatCoreTest, LstatCoreTest_DoLstat_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LstatCoreTest-begin LstatCoreTest_DoLstat_001"; + + auto res = LstatCore::DoLstat("/invalid/test/lstat.txt"); + EXPECT_EQ(res.IsSuccess(), false); + auto err = res.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "LstatCoreTest-end LstatCoreTest_DoLstat_001"; +} + +/** + * @tc.name: LstatCoreTest_DoLstat_002 + * @tc.desc: Test function of LstatCore::DoLstat interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(LstatCoreTest, LstatCoreTest_DoLstat_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "LstatCoreTest-begin LstatCoreTest_DoLstat_002"; + + auto res = LstatCore::DoLstat("/data/test/lstat.txt"); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "LstatCoreTest-end LstatCoreTest_DoLstat_002"; +} +} \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp index 34c0d40b5..a50211973 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/mkdir_core_mock_test.cpp @@ -15,11 +15,11 @@ #include #include -#include #include +#include #include "mkdir_core.h" -#include "mock/uv_fs_mock.h" +#include "uv_fs_mock.h" namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; @@ -41,7 +41,7 @@ filesystem::path MkdirCoreMockTest::tempFilePath; void MkdirCoreMockTest::SetUpTestCase(void) { GTEST_LOG_(INFO) << "SetUpTestCase"; - tempFilePath = filesystem::temp_directory_path() / "test"; + tempFilePath = filesystem::temp_directory_path() / "mkdir_test"; std::filesystem::create_directory(tempFilePath); uvMock = std::make_shared(); Uvfs::ins = uvMock; @@ -71,7 +71,6 @@ void MkdirCoreMockTest::TearDown(void) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0001, testing::ext::TestSize.Level1) { @@ -92,7 +91,6 @@ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0001, testing::ext::TestSi * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0002, testing::ext::TestSize.Level1) { @@ -109,11 +107,10 @@ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0002, testing::ext::TestSi /** * @tc.name: MkdirCoreMockTest_DoMkdir_0003 - * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.desc: Test function of DoMkdir() interface is FAILED for uv_fs_mkdir return 1. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0003, testing::ext::TestSize.Level1) { @@ -130,11 +127,10 @@ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0003, testing::ext::TestSi /** * @tc.name: MkdirCoreMockTest_DoMkdir_0004 - * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.desc: Test function of DoMkdir() interface is FAILED for file exists. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0004, testing::ext::TestSize.Level1) { @@ -156,11 +152,10 @@ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0004, testing::ext::TestSi /** * @tc.name: MkdirCoreMockTest_DoMkdir_0005 - * @tc.desc: Test function of DoMkdir() interface for FAILED. + * @tc.desc: Test function of DoMkdir() interface is FAILED for no such file or directory. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(MkdirCoreMockTest, MkdirCoreMockTest_DoMkdir_0005, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_fs/properties/mkdtemp_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/mkdtemp_core_mock_test.cpp new file mode 100644 index 000000000..d207773de --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/mkdtemp_core_mock_test.cpp @@ -0,0 +1,114 @@ +/* + * 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 "mkdtemp_core.h" +#include "mock/uv_fs_mock.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class MkdtempCoreMockTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +filesystem::path MkdtempCoreMockTest::tempFilePath; + +void MkdtempCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = filesystem::temp_directory_path() / "test"; + std::filesystem::create_directory(tempFilePath); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void MkdtempCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove_all(tempFilePath); + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void MkdtempCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void MkdtempCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: MkdtempCoreMockTest_DoMkdtemp_0001 + * @tc.desc: Test function of DoMkdtemp() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MkdtempCoreMockTest, MkdtempCoreMockTest_DoMkdtemp_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdtempCoreMockTest-begin MkdtempCoreMockTest_DoMkdtemp_0001"; + + uv_fs_t mock_req; + mock_req.path = const_cast("/data/local/tmp/test/XXXXXX"); + + EXPECT_CALL(*uvMock, uv_fs_mkdtemp(_, _, _, _)) + .WillOnce(Invoke([&](uv_loop_t*, uv_fs_t* req, const char*, uv_fs_cb) { + *req = mock_req; + return 0; + })); + + auto ret = MkdtempCore::DoMkdtemp("/data/local/tmp/test/XXXXXX"); + EXPECT_EQ(ret.IsSuccess(), true); + + GTEST_LOG_(INFO) << "MkdtempCoreMockTest-end MkdtempCoreMockTest_DoMkdtemp_0001"; +} + +/** + * @tc.name: MkdtempCoreMockTest_DoMkdtemp_0002 + * @tc.desc: Test function of DoMkdtemp() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MkdtempCoreMockTest, MkdtempCoreMockTest_DoMkdtemp_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MkdtempCoreMockTest-begin MkdtempCoreMockTest_DoMkdtemp_0002"; + + string path = tempFilePath.string() + "/XXXXXX"; + + EXPECT_CALL(*uvMock, uv_fs_mkdtemp(_, _, _, _)).WillOnce(Return(-1)); + auto ret = MkdtempCore::DoMkdtemp(path); + EXPECT_EQ(ret.IsSuccess(), false); + + GTEST_LOG_(INFO) << "MkdtempCoreMockTest-end MkdtempCoreMockTest_DoMkdtemp_0002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp index 5878a9304..189edf925 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.cpp @@ -23,7 +23,7 @@ int setxattr(const char *path, const char *name, const void *value, size_t size, return System::ins->setxattr(path, name, value, size, flags); } -int getxattr(const char *path, const char *name, void *value, size_t size) +ssize_t getxattr(const char *path, const char *name, void *value, size_t size) { return System::ins->getxattr(path, name, value, size); } diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h index 3ff74be78..dad578b09 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/system_mock.h @@ -29,7 +29,7 @@ public: public: virtual ~System() = default; virtual int setxattr(const char *path, const char *name, const void *value, size_t size, int flags) = 0; - virtual int getxattr(const char *path, const char *name, void *value, size_t size) = 0; + virtual ssize_t getxattr(const char *path, const char *name, void *value, size_t size) = 0; virtual int fgetxattr(int filedes, const char *name, void *value, size_t size) = 0; virtual int flock(int fd, int operation) = 0; }; @@ -37,7 +37,7 @@ public: class SystemMock : public System { public: MOCK_METHOD5(setxattr, int(const char *path, const char *name, const void *value, size_t size, int flags)); - MOCK_METHOD4(getxattr, int(const char *path, const char *name, void *value, size_t size)); + MOCK_METHOD4(getxattr, ssize_t(const char *path, const char *name, void *value, size_t size)); MOCK_METHOD4(fgetxattr, int(int filedes, const char *name, void *value, size_t size)); MOCK_METHOD2(flock, int(int fd, int operation)); }; diff --git a/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h index 1fa703a0f..a94f2dc32 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h +++ b/interfaces/test/unittest/js/mod_fs/properties/mock/uv_fs_mock.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef UV_FS_READ_MOCK_H -#define UV_FS_READ_MOCK_H +#ifndef INTERFACES_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_UV_FS_MOCK_H +#define INTERFACES_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_UV_FS_MOCK_H #include "uv.h" @@ -88,4 +88,4 @@ public: }; } // OHOS::FileManagement::ModuleFileIO -#endif \ No newline at end of file +#endif // INTERFACES_TEST_UNITTEST_JS_MOD_FS_PROPERTIES_MOCK_UV_FS_MOCK_H \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/movedir_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/movedir_core_test.cpp new file mode 100644 index 000000000..3e578db2e --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/movedir_core_test.cpp @@ -0,0 +1,333 @@ +/* + * 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 "movedir_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class MoveDirCoreTest : public testing::Test { +public: + static filesystem::path srcPath; + static filesystem::path destPath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +filesystem::path MoveDirCoreTest::srcPath; +filesystem::path MoveDirCoreTest::destPath; + +void MoveDirCoreTest::SetUpTestCase(void) +{ + srcPath = filesystem::temp_directory_path() / "src/"; + destPath = filesystem::temp_directory_path() / "dest/"; + std::filesystem::create_directory(srcPath); + std::filesystem::create_directory(destPath); + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void MoveDirCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove_all(srcPath); + filesystem::remove_all(destPath); +} + +void MoveDirCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void MoveDirCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0001 + * @tc.desc: Test function of DoMoveDir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0001"; + + string src = srcPath.string() + "/test01"; + string dest = destPath.string(); + filesystem::create_directories(src); + + auto result = MoveDirCore::DoMoveDir(src, dest, optional()); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0001"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0002 + * @tc.desc: Test function of DoMoveDir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0002"; + + string src = srcPath.string() + "/test02"; + string dest = destPath.string(); + filesystem::create_directories(src); + + int invalidMode = DIRMODE_MAX + 1; + auto result = MoveDirCore::DoMoveDir(src, dest, optional(invalidMode)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + auto err = result.fsResult.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0002"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0003 + * @tc.desc: Test function of DoMoveDir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0002"; + + string src = srcPath.string() + "/test03"; + string dest = destPath.string(); + + auto result = MoveDirCore::DoMoveDir(src, dest, optional(DIRMODE_DIRECTORY_REPLACE)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + auto err = result.fsResult.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0003"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0004 + * @tc.desc: Test function of DoMoveDir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0002"; + + string src = srcPath.string(); + string dest = destPath.string() + "/test04"; + + auto result = MoveDirCore::DoMoveDir(src, dest, optional(DIRMODE_DIRECTORY_REPLACE)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + auto err = result.fsResult.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900020); + EXPECT_FALSE(result.errFiles.has_value()); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0004"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0005 + * @tc.desc: Test function of DoMoveDir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0005"; + + string src = "/data/local/test05/src/src/src/test05"; + string dest = destPath.string() + "/src"; + filesystem::create_directories(src); + filesystem::create_directories(dest); + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test05/", destPath.string(), optional(DIRMODE_DIRECTORY_THROW_ERR)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + auto err = result.fsResult.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900032); + EXPECT_FALSE(result.errFiles.has_value()); + + filesystem::remove_all("/data/local/test05"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0005"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0006 + * @tc.desc: Test function of DoMoveDir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0006, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0006"; + + string src = "/data/local/test06/src/src/src/test06"; + string dest = destPath.string() + "/src"; + filesystem::create_directories(src); + filesystem::create_directories(dest); + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test06/src", destPath.string(), optional(DIRMODE_DIRECTORY_REPLACE)); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + + filesystem::remove_all("/data/local/test06"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0006"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0007 + * @tc.desc: Test function of DoMoveDir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0007"; + + filesystem::create_directories("/data/local/test07/src"); + filesystem::create_directories("/data/local/test07/dest"); + filesystem::path srcFile = "/data/local/test07/src/test_file.txt"; + ofstream(srcFile) << "Test content\n123\n456"; + filesystem::path destFile = "/data/local/test07/dest/test_file.txt"; + ofstream(destFile) << "Test content\ndest"; + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test07/src/", "/data/local/test07/dest/", optional(DIRMODE_FILE_THROW_ERR)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + auto err = result.fsResult.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900015); + EXPECT_TRUE(result.errFiles.has_value()); + + filesystem::remove_all("/data/local/test07"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0007"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0008 + * @tc.desc: Test function of DoMoveDir() interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0008, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0008"; + + filesystem::create_directories("/data/local/test08/src"); + filesystem::create_directories("/data/local/test08/dest/test_file/test_file"); + filesystem::path srcFile = "/data/local/test08/src/test_file"; + ofstream(srcFile) << "Test content\n123\n456"; + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test08/src/", "/data/local/test08/dest/test_file/", optional(DIRMODE_FILE_REPLACE)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_TRUE(result.errFiles.has_value()); + + filesystem::remove_all("/data/local/test08"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0008"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0009 + * @tc.desc: Test function of DoMoveDir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0009, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0009"; + + filesystem::create_directories("/data/local/test09/src"); + filesystem::create_directories("/data/local/test09/dest"); + filesystem::path srcFile = "/data/local/test09/src/test_file.txt"; + ofstream(srcFile) << "Test content\n123\n456"; + filesystem::path destFile = "/data/local/test09/dest/test_file.txt"; + ofstream(destFile) << "Test content\ndest"; + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test09/src/", "/data/local/test09/dest/", optional(DIRMODE_FILE_REPLACE)); + + EXPECT_TRUE(result.fsResult.IsSuccess()); + EXPECT_FALSE(result.errFiles.has_value()); + + filesystem::remove_all("/data/local/test09"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0009"; +} + +/** + * @tc.name: MoveDirCoreTest_DoMoveDir_0010 + * @tc.desc: Test function of DoMoveDir() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(MoveDirCoreTest, MoveDirCoreTest_DoMoveDir_0010, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "MoveDirCoreTest-begin MoveDirCoreTest_DoMoveDir_0010"; + + filesystem::create_directories("/data/local/test09/src/test_file.txt"); + filesystem::create_directories("/data/local/test09/dest"); + filesystem::path destFile = "/data/local/test09/dest/test_file.txt"; + ofstream(destFile) << "Test content\ndest"; + + auto result = MoveDirCore::DoMoveDir( + "/data/local/test09/src/", "/data/local/test09/dest/", optional(DIRMODE_FILE_REPLACE)); + + EXPECT_FALSE(result.fsResult.IsSuccess()); + EXPECT_TRUE(result.errFiles.has_value()); + + filesystem::remove_all("/data/local/test09"); + + GTEST_LOG_(INFO) << "MoveDirCoreTest-end MoveDirCoreTest_DoMoveDir_0010"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp index 27cd72731..abee054b1 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/open_core_mock_test.cpp @@ -13,14 +13,15 @@ * limitations under the License. */ -#include "open_core.h" -#include "mock/uv_fs_mock.h" - #include #include #include #include +#include "mock/uv_fs_mock.h" +#include "open_core.h" +#include "unistd_mock.h" + namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; using namespace testing::ext; @@ -32,6 +33,8 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + +private: static inline shared_ptr uvMock = nullptr; }; @@ -40,6 +43,7 @@ void OpenCoreMockTest::SetUpTestCase(void) GTEST_LOG_(INFO) << "SetUpTestCase"; uvMock = std::make_shared(); Uvfs::ins = uvMock; + UnistdMock::EnableMock(); } void OpenCoreMockTest::TearDownTestCase(void) @@ -47,6 +51,7 @@ void OpenCoreMockTest::TearDownTestCase(void) GTEST_LOG_(INFO) << "TearDownTestCase"; Uvfs::ins = nullptr; uvMock = nullptr; + UnistdMock::DisableMock(); } void OpenCoreMockTest::SetUp(void) @@ -60,19 +65,19 @@ void OpenCoreMockTest::TearDown(void) } /** -* @tc.name: OpenCoreMockTest_DoOpen_001 -* @tc.desc: Test function of OpenCore::DoOpen interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreMockTest_DoOpen_001 + * @tc.desc: Test function of OpenCore::DoOpen interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_001, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_001"; - string path = "/test/open_test.txt"; + string path = "/test/OpenCoreMockTest_DoOpen_001"; int32_t mode = 0; - + EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(0)); auto res = OpenCore::DoOpen(path, mode); EXPECT_EQ(res.IsSuccess(), true); @@ -81,59 +86,67 @@ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_001, testing::ext::TestSize.L } /** -* @tc.name: OpenCoreMockTest_DoOpen_002 -* @tc.desc: Test function of OpenCore::DoOpen interface for SUCCESS. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreMockTest_DoOpen_002 + * @tc.desc: Test function of OpenCore::DoOpen interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_002, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_002"; - string path = "file://test/open_test.txt"; + string path = "file://test/OpenCoreMockTest_DoOpen_002"; int32_t mode = 0; + auto unistdMock = UnistdMock::GetMock(); EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(0)); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).WillRepeatedly(testing::Return(0)); auto res = OpenCore::DoOpen(path, mode); + testing::Mock::VerifyAndClearExpectations(unistdMock.get()); EXPECT_EQ(res.IsSuccess(), true); GTEST_LOG_(INFO) << "OpenCoreMockTest-end OpenCoreMockTest_DoOpen_002"; } /** -* @tc.name: OpenCoreMockTest_DoOpen_003 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreMockTest_DoOpen_003 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_003, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_003"; - string path = "file://test/open_test.txt"; + string path = "file://test/OpenCoreMockTest_DoOpen_003"; int32_t mode = 0; + auto unistdMock = UnistdMock::GetMock(); EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(-1)); + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*unistdMock, access(testing::_, testing::_)).WillRepeatedly(testing::Return(0)); auto res = OpenCore::DoOpen(path, mode); + testing::Mock::VerifyAndClearExpectations(&unistdMock); EXPECT_EQ(res.IsSuccess(), false); GTEST_LOG_(INFO) << "OpenCoreMockTest-end OpenCoreMockTest_DoOpen_003"; } /** -* @tc.name: OpenCoreMockTest_DoOpen_004 -* @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreMockTest_DoOpen_004 + * @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreMockTest, OpenCoreMockTest_DoOpen_004, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreMockTest-begin OpenCoreMockTest_DoOpen_004"; - string path = "/test/open_test.txt"; + string path = "/test/OpenCoreMockTest_DoOpen_004"; int32_t mode = 0; EXPECT_CALL(*uvMock, uv_fs_open(_, _, _, _, _, _)).WillOnce(Return(-1)); diff --git a/interfaces/test/unittest/js/mod_fs/properties/open_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/open_core_test.cpp index fcfc9019b..a6cad138a 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/open_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/open_core_test.cpp @@ -13,10 +13,10 @@ * limitations under the License. */ -#include - #include "open_core.h" +#include + namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; using namespace testing::ext; @@ -51,12 +51,12 @@ void OpenCoreTest::TearDown(void) } /** -* @tc.name: OpenCoreTest_DoOpen_001 -* @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_001 + * @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_001, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_001"; @@ -71,12 +71,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_001, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_002 -* @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_002 + * @tc.desc: Test function of OpenCore::DoOpen interface for ERROR. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_002, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_002"; @@ -91,12 +91,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_002, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_003 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_003 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_003, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_003"; @@ -111,12 +111,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_003, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_004 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_004 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_004, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_004"; @@ -131,12 +131,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_004, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_005 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_005 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_005, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_005"; @@ -151,12 +151,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_005, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_006 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_006 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_006, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_006"; @@ -171,12 +171,12 @@ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_006, testing::ext::TestSize.Level1) } /** -* @tc.name: OpenCoreTest_DoOpen_007 -* @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. -* @tc.size: MEDIUM -* @tc.type: FUNC -* @tc.level Level 1 -*/ + * @tc.name: OpenCoreTest_DoOpen_007 + * @tc.desc: Test function of OpenCore::DoOpen interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ HWTEST_F(OpenCoreTest, OpenCoreTest_DoOpen_007, testing::ext::TestSize.Level1) { GTEST_LOG_(INFO) << "OpenCoreTest-begin OpenCoreTest_DoOpen_007"; diff --git a/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_mock_test.cpp new file mode 100644 index 000000000..118e5e28a --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_mock_test.cpp @@ -0,0 +1,133 @@ +/* + * 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 "mock/uv_fs_mock.h" +#include "read_lines_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class ReadLinesCoreMockTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +filesystem::path ReadLinesCoreMockTest::tempFilePath; + +void ReadLinesCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = filesystem::temp_directory_path() / "read_lines_test_file.txt"; + ofstream(tempFilePath) << "Test content\n123\n456"; + ofstream(tempFilePath).close(); + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void ReadLinesCoreMockTest::TearDownTestCase(void) +{ + filesystem::remove(tempFilePath); + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void ReadLinesCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void ReadLinesCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: ReadLinesCoreMockTest_DoReadLines_001 + * @tc.desc: Test function of ReadLinesCore::DoReadLines interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadLinesCoreMockTest, ReadLinesCoreMockTest_DoReadLines_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-begin ReadLinesCoreMockTest_DoReadLines_001"; + + string path = tempFilePath.string(); + Options option; + option.encoding = "utf-8"; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(1)); + auto res = ReadLinesCore::DoReadLines(path, option); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-end ReadLinesCoreMockTest_DoReadLines_001"; +} + +/** + * @tc.name: ReadLinesCoreMockTest_DoReadLines_002 + * @tc.desc: Test function of ReadLinesCore::DoReadLines interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadLinesCoreMockTest, ReadLinesCoreMockTest_DoReadLines_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-begin ReadLinesCoreMockTest_DoReadLines_002"; + + string path = tempFilePath.string(); + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(1)); + auto res = ReadLinesCore::DoReadLines(path); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-end ReadLinesCoreMockTest_DoReadLines_002"; +} + +/** + * @tc.name: ReadLinesCoreMockTest_DoReadLines_003 + * @tc.desc: Test function of ReadLinesCore::DoReadLines interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadLinesCoreMockTest, ReadLinesCoreMockTest_DoReadLines_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-begin ReadLinesCoreMockTest_DoReadLines_003"; + + string path = tempFilePath.string(); + Options option; + option.encoding = "utf-8"; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(-1)); + auto res = ReadLinesCore::DoReadLines(path, option); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "ReadLinesCoreMockTest-end ReadLinesCoreMockTest_DoReadLines_003"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_test.cpp new file mode 100644 index 000000000..92e4f19b4 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/read_lines_core_test.cpp @@ -0,0 +1,102 @@ +/* + * 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 "read_lines_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class ReadLinesCoreTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +filesystem::path ReadLinesCoreTest::tempFilePath; + +void ReadLinesCoreTest::SetUpTestCase(void) +{ + tempFilePath = filesystem::temp_directory_path() / "read_lines_test_file.txt"; + ofstream(tempFilePath) << "Test content\n123\n456"; + ofstream(tempFilePath).close(); + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void ReadLinesCoreTest::TearDownTestCase(void) +{ + filesystem::remove(tempFilePath); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void ReadLinesCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void ReadLinesCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: ReadLinesCoreTest_DoReadLines_001 + * @tc.desc: Test function of ReadLinesCore::DoReadLines interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadLinesCoreTest, ReadLinesCoreTest_DoReadLines_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadLinesCoreTest-begin ReadLinesCoreTest_DoReadLines_001"; + + string path = "ReadLinesCoreTest_DoReadLines_001"; + Options option; + option.encoding = "utf-8"; + auto res = ReadLinesCore::DoReadLines(path, option); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "ReadLinesCoreTest-end ReadLinesCoreTest_DoReadLines_001"; +} + +/** + * @tc.name: ReadLinesCoreTest_DoReadLines_002 + * @tc.desc: Test function of ReadLinesCore::DoReadLines interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(ReadLinesCoreTest, ReadLinesCoreTest_DoReadLines_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "ReadLinesCoreTest-begin ReadLinesCoreTest_DoReadLines_002"; + + string path = "ReadLinesCoreTest_DoReadLines_002"; + Options option; + option.encoding = "utf-16"; + auto res = ReadLinesCore::DoReadLines(path, option); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "ReadLinesCoreTest-end ReadLinesCoreTest_DoReadLines_002"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp index 56b6e4bb3..92b0c643d 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/read_text_core_test.cpp @@ -47,7 +47,6 @@ public: * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0001, testing::ext::TestSize.Level1) { @@ -68,7 +67,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0001, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0002, testing::ext::TestSize.Level1) { @@ -90,7 +88,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0002, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0003, testing::ext::TestSize.Level1) { @@ -112,7 +109,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0003, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0004, testing::ext::TestSize.Level1) { @@ -134,7 +130,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0004, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0005, testing::ext::TestSize.Level1) { @@ -156,7 +151,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0005, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0006, testing::ext::TestSize.Level1) { @@ -176,7 +170,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0006, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0007, testing::ext::TestSize.Level1) { @@ -198,7 +191,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0007, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0008, testing::ext::TestSize.Level1) { @@ -221,7 +213,6 @@ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0008, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 -* @tc.require: AR000IGDNF */ HWTEST_F(ReadTextCoreTest, DoReadTextTest_0009, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_fs/properties/rename_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/rename_core_mock_test.cpp new file mode 100644 index 000000000..910487a21 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/rename_core_mock_test.cpp @@ -0,0 +1,102 @@ +/* + * 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_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class RenameCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvfs = nullptr; +}; + +void RenameCoreMockTest::SetUpTestCase(void) +{ + uvfs = std::make_shared(); + Uvfs::ins = uvfs; + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void RenameCoreMockTest::TearDownTestCase(void) +{ + Uvfs::ins = nullptr; + uvfs = nullptr; + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void RenameCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void RenameCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: RenameCoreMockTest_DoRename_001 + * @tc.desc: Test function of RenameCore::DoRename interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(RenameCoreMockTest, RenameCoreMockTest_DoRename_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "RenameCoreMockTest-begin RenameCoreMockTest_DoRename_001"; + string src; + string dest; + + EXPECT_CALL(*uvfs, uv_fs_rename(_, _, _, _, _)).WillOnce(Return(-1)); + + auto res = RenameCore::DoRename(src, dest); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "RenameCoreMockTest-end RenameCoreMockTest_DoRename_001"; +} + +/** + * @tc.name: RenameCoreMockTest_DoRename_002 + * @tc.desc: Test function of RenameCore::DoRename interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(RenameCoreMockTest, RenameCoreMockTest_DoRename_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "RenameCoreMockTest-begin RenameCoreMockTest_DoRename_002"; + string src; + string dest; + + EXPECT_CALL(*uvfs, uv_fs_rename(_, _, _, _, _)).WillOnce(Return(1)); + + auto res = RenameCore::DoRename(src, dest); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "RenameCoreMockTest-end RenameCoreMockTest_DoRename_002"; +} + + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/stat_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/stat_core_mock_test.cpp index 2fd8bd7f5..2a3133bdb 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/stat_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/stat_core_mock_test.cpp @@ -13,10 +13,10 @@ * limitations under the License. */ -#include "securec.h" #include "stat_core.h" #include "uv_fs_mock.h" +#include #include namespace OHOS::FileManagement::ModuleFileIO::Test { @@ -59,7 +59,7 @@ void StatCoreMockTest::TearDown(void) /** * @tc.name: StatCoreMockTest_DoStat_001 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.desc: Test function of StatCore::DoStat interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 @@ -82,7 +82,7 @@ HWTEST_F(StatCoreMockTest, StatCoreMockTest_DoStat_001, testing::ext::TestSize.L /** * @tc.name: StatCoreMockTest_DoStat_002 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.desc: Test function of StatCore::DoStat interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 @@ -105,7 +105,7 @@ HWTEST_F(StatCoreMockTest, StatCoreMockTest_DoStat_002, testing::ext::TestSize.L /** * @tc.name: StatCoreMockTest_DoStat_003 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.desc: Test function of StatCore::DoStat interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 @@ -127,30 +127,27 @@ HWTEST_F(StatCoreMockTest, StatCoreMockTest_DoStat_003, testing::ext::TestSize.L } /** - * @tc.name: StatCoreMockTest_DoStat_005 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.name: StatCoreMockTest_DoStat_004 + * @tc.desc: Test function of StatCore::DoStat interface for SUCCESS. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 */ -HWTEST_F(StatCoreMockTest, StatCoreMockTest_DoStat_005, testing::ext::TestSize.Level1) +HWTEST_F(StatCoreMockTest, StatCoreMockTest_DoStat_004, testing::ext::TestSize.Level1) { - GTEST_LOG_(INFO) << "StatCoreMockTest-begin StatCoreMockTest_DoStat_005"; + GTEST_LOG_(INFO) << "StatCoreMockTest-begin StatCoreMockTest_DoStat_004"; FileInfo fileinfo; - string buffer = "Hello, World!"; - int pathLength = buffer.size() + 1; - fileinfo.path = std::make_unique(pathLength); - memcpy_s(fileinfo.path.get(), pathLength, buffer.c_str(), buffer.size()); - fileinfo.fdg = std::make_unique(-1); - fileinfo.isPath = true; + fileinfo.path = std::make_unique(1); + fileinfo.fdg = std::make_unique(1); + fileinfo.isPath = false; EXPECT_CALL(*uvfs, uv_fs_stat(_, _, _, _)).WillOnce(Return(-1)); auto res = StatCore::DoStat(fileinfo); - EXPECT_EQ(res.IsSuccess(), false); + EXPECT_EQ(res.IsSuccess(), true); - GTEST_LOG_(INFO) << "StatCoreMockTest-end StatCoreMockTest_DoStat_005"; + GTEST_LOG_(INFO) << "StatCoreMockTest-end StatCoreMockTest_DoStat_004"; } } // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/stat_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/stat_core_test.cpp index 5ad93fbf9..f11d92625 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/stat_core_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/stat_core_test.cpp @@ -52,7 +52,7 @@ void StatCoreTest::TearDown(void) /** * @tc.name: StatCoreTest_DoStat_001 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.desc: Test function of StatCore::DoStat interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 @@ -71,7 +71,7 @@ HWTEST_F(StatCoreTest, StatCoreTest_DoStat_001, testing::ext::TestSize.Level1) /** * @tc.name: StatCoreTest_DoStat_002 - * @tc.desc: Test function of FsyncCore::DoStat interface for FALSE. + * @tc.desc: Test function of StatCore::DoStat interface for FALSE. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 diff --git a/interfaces/test/unittest/js/mod_fs/properties/symlink_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/symlink_core_mock_test.cpp new file mode 100644 index 000000000..dd6e4b43b --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/symlink_core_mock_test.cpp @@ -0,0 +1,104 @@ +/* + * 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 "symlink_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class SymlinkCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void SymlinkCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void SymlinkCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void SymlinkCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void SymlinkCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: SymlinkCoreMockTest_DoSymlink_001 + * @tc.desc: Test function of SymlinkCore::DoSymlink interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(SymlinkCoreMockTest, SymlinkCoreMockTest_DoSymlink_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SymlinkCore-begin SymlinkCoreMockTest_DoSymlink_001"; + + string target; + string srcPath; + + EXPECT_CALL(*uvMock, uv_fs_symlink(_, _, _, _, _, _)).WillOnce(Return(-1)); + + auto res = SymlinkCore::DoSymlink(target, srcPath); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "SymlinkCore-end SymlinkCoreMockTest_DoSymlink_001"; +} + +/** + * @tc.name: SymlinkCoreMockTest_DoSymlink_002 + * @tc.desc: Test function of SymlinkCore::DoSymlink interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(SymlinkCoreMockTest, SymlinkCoreMockTest_DoSymlink_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SymlinkCore-begin SymlinkCoreMockTest_DoSymlink_002"; + + string target; + string srcPath; + + EXPECT_CALL(*uvMock, uv_fs_symlink(_, _, _, _, _, _)).WillOnce(Return(1)); + + auto res = SymlinkCore::DoSymlink(target, srcPath); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "SymlinkCore-end SymlinkCoreMockTest_DoSymlink_002"; +} + +} // OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp new file mode 100644 index 000000000..dbda35d77 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp @@ -0,0 +1,237 @@ +/* + * 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 "trans_listener_core.h" + +#include +#include +#include + +#include "copy_core.h" +#include "unistd_mock.h" + +using namespace OHOS; +using namespace OHOS::Storage::DistributedFile; + +class MockDistributedFileDaemonManager final : public DistributedFileDaemonManager { +public: + MOCK_METHOD(int32_t, PrepareSession, + (const std::string &srcUri, const std::string &dstUri, const std::string &srcDeviceId, + const sptr &listener, HmdfsInfo &info), + (override)); + + int32_t OpenP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo) override + { + return 0; + } + int32_t CloseP2PConnection(const DistributedHardware::DmDeviceInfo &deviceInfo) override + { + return 0; + } + int32_t OpenP2PConnectionEx(const std::string &networkId, sptr remoteReverseObj) override + { + return 0; + } + int32_t CloseP2PConnectionEx(const std::string &networkId) override + { + return 0; + } + int32_t CancelCopyTask(const std::string &sessionName) override + { + return 0; + } + int32_t PushAsset( + int32_t userId, const sptr &assetObj, const sptr &sendCallback) override + { + return 0; + } + int32_t RegisterAssetCallback(const sptr &recvCallback) override + { + return 0; + } + int32_t UnRegisterAssetCallback(const sptr &recvCallback) override + { + return 0; + } + int32_t GetSize(const std::string &uri, bool isSrcUri, uint64_t &size) override + { + return 0; + } + int32_t IsDirectory(const std::string &uri, bool isSrcUri, bool &isDirectory) override + { + return 0; + } + int32_t Copy(const std::string &srcUri, const std::string &destUri, ProcessCallback processCallback) override + { + return 0; + } + int32_t Cancel(const std::string &srcUri, const std::string &destUri) override + { + return 0; + } + int32_t Cancel() override + { + return 0; + } + + MockDistributedFileDaemonManager() = default; + ~MockDistributedFileDaemonManager() = default; + +public: + static std::shared_ptr GetMock(); + static void DisableMock(); + +private: + static thread_local std::shared_ptr managerMock; +}; + +thread_local std::shared_ptr MockDistributedFileDaemonManager::managerMock = nullptr; + +std::shared_ptr MockDistributedFileDaemonManager::GetMock() +{ + if (managerMock == nullptr) { + managerMock = std::make_shared(); + } + return managerMock; +} + +void MockDistributedFileDaemonManager::DisableMock() +{ + managerMock = nullptr; +} + +class MockTaskSignalListener : public OHOS::DistributedFS::ModuleTaskSignal::TaskSignalListener { +public: + MOCK_METHOD(void, OnCancel, (), (override)); +}; + +#ifdef ENABLE_DISTRIBUTED_FILE_MOCK +DistributedFileDaemonManager &DistributedFileDaemonManager::GetInstance() +{ + return *MockDistributedFileDaemonManager::GetMock(); +} +#endif + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +string g_path = "/data/test/TransListenerCoreMockTest.txt"; +const string FILE_MANAGER_AUTHORITY = "docs"; +const string MEDIA_AUTHORITY = "media"; + +class IProgressListenerTest : public IProgressListener { +public: + void InvokeListener(uint64_t progressSize, uint64_t totalSize) const override {} +}; + +class TransListenerCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void TransListenerCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + int32_t fd = open(g_path.c_str(), O_CREAT | O_RDWR, 0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + UnistdMock::EnableMock(); +} + +void TransListenerCoreMockTest::TearDownTestCase(void) +{ + rmdir(g_path.c_str()); + MockDistributedFileDaemonManager::DisableMock(); + UnistdMock::DisableMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void TransListenerCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void TransListenerCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: TransListenerCoreMockTest_PrepareCopySession_001 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreMockTest, TransListenerCoreMockTest_PrepareCopySession_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreMockTest-begin TransListenerCoreMockTest_PrepareCopySession_001"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = FILE_MANAGER_AUTHORITY; + info.authority = MEDIA_AUTHORITY; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + string disSandboxPath = "disSandboxPath"; + auto unistdMock = UnistdMock::GetMock(); + auto managerMock = MockDistributedFileDaemonManager::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*managerMock, PrepareSession(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(ERRNO_NOERR)); + auto result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "TransListenerCoreMockTest-end TransListenerCoreMockTest_PrepareCopySession_001"; +} + +/** + * @tc.name: TransListenerCoreMockTest_CopyFileFromSoftBus_001 + * @tc.desc: Test function of TransListenerCore::CopyFileFromSoftBus interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreMockTest, TransListenerCoreMockTest_CopyFileFromSoftBus_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreMockTest-begin TransListenerCoreMockTest_CopyFileFromSoftBus_001"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = FILE_MANAGER_AUTHORITY; + + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + std::shared_ptr transListener = std::make_shared(); + std::shared_ptr infos = std::make_shared(); + auto unistdMock = UnistdMock::GetMock(); + auto managerMock = MockDistributedFileDaemonManager::GetMock(); + + EXPECT_CALL(*unistdMock, read(testing::_, testing::_, testing::_)).WillRepeatedly(testing::Return(1)); + EXPECT_CALL(*managerMock, PrepareSession(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(ERRNO_NOERR)); + + auto res = transListener->CopyFileFromSoftBus(srcUri, "destUri", infos, nullptr); + EXPECT_EQ(res, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreMockTest-end TransListenerCoreMockTest_CopyFileFromSoftBus_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/trans_listener_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_test.cpp new file mode 100644 index 000000000..5e6dca235 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_test.cpp @@ -0,0 +1,577 @@ +/* + * 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 "trans_listener_core.h" + +#include +#include + +#include "copy_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +string g_path = "/data/test/TransListenerCoreTest.txt"; +const string FILE_MANAGER_AUTHORITY = "docs"; +const string MEDIA_AUTHORITY = "media"; + +class IProgressListenerTest : public IProgressListener { +public: + void InvokeListener(uint64_t progressSize, uint64_t totalSize) const override {} +}; + +class TransListenerCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void TransListenerCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + int32_t fd = open(g_path.c_str(), O_CREAT | O_RDWR, 0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); +} + +void TransListenerCoreTest::TearDownTestCase(void) +{ + rmdir(g_path.c_str()); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void TransListenerCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void TransListenerCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: TransListenerCoreTest_CreateDfsCopyPath_001 + * @tc.desc: Test function of TransListenerCore::CreateDfsCopyPath interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CreateDfsCopyPath_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CreateDfsCopyPath_001"; + + string result = TransListenerCore::CreateDfsCopyPath(); + EXPECT_FALSE(result.empty()); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CreateDfsCopyPath_001"; +} + +/** + * @tc.name: TransListenerCoreTest_HandleCopyFailure_001 + * @tc.desc: Test function of TransListenerCore::HandleCopyFailure interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_HandleCopyFailure_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_HandleCopyFailure_001"; + + string path = "/data/test/TransListenerCoreTest_HandleCopyFailure_001.txt"; + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + CopyEvent event; + event.errorCode = 0; + int result = TransListenerCore::HandleCopyFailure(event, info, path, ""); + EXPECT_EQ(result, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_HandleCopyFailure_001"; +} + +/** + * @tc.name: TransListenerCoreTest_HandleCopyFailure_002 + * @tc.desc: Test function of TransListenerCore::HandleCopyFailure interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_HandleCopyFailure_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_HandleCopyFailure_002"; + + string path = "/data/test/TransListenerCoreTest_HandleCopyFailure_002.txt"; + int32_t fd = open(path.c_str(), O_CREAT | O_RDWR, 0644); + if (fd < 0) { + EXPECT_TRUE(false); + } + close(fd); + + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + CopyEvent event; + event.errorCode = SOFTBUS_TRANS_FILE_EXISTED; + int result = TransListenerCore::HandleCopyFailure(event, info, path, ""); + EXPECT_EQ(result, EEXIST); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_HandleCopyFailure_002"; +} + +/** + * @tc.name: TransListenerCoreTest_HandleCopyFailure_003 + * @tc.desc: Test function of TransListenerCore::HandleCopyFailure interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_HandleCopyFailure_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_HandleCopyFailure_003"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = MEDIA_AUTHORITY; + CopyEvent event; + event.errorCode = DFS_CANCEL_SUCCESS; + int result = TransListenerCore::HandleCopyFailure(event, info, "", ""); + EXPECT_EQ(result, ECANCELED); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_HandleCopyFailure_003"; +} + +/** + * @tc.name: TransListenerCoreTest_WaitForCopyResult_001 + * @tc.desc: Test function of TransListenerCore::WaitForCopyResult interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_WaitForCopyResult_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_WaitForCopyResult_001"; + + std::shared_ptr transListener = std::make_shared(); + transListener->copyEvent_.copyResult = FAILED; + int result = TransListenerCore::WaitForCopyResult(transListener.get()); + EXPECT_EQ(result, 2); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_WaitForCopyResult_001"; +} + +/** + * @tc.name: TransListenerCoreTest_WaitForCopyResult_002 + * @tc.desc: Test function of TransListenerCore::WaitForCopyResult interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_WaitForCopyResult_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_WaitForCopyResult_002"; + + int result = TransListenerCore::WaitForCopyResult(nullptr); + EXPECT_TRUE(result); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_WaitForCopyResult_002"; +} + +/** + * @tc.name: TransListenerCoreTest_PrepareCopySession_001 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_PrepareCopySession_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_PrepareCopySession_001"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = MEDIA_AUTHORITY; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + string disSandboxPath = "disSandboxPath"; + + int result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_PrepareCopySession_001"; +} + +/** + * @tc.name: TransListenerCoreTest_PrepareCopySession_002 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_PrepareCopySession_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_PrepareCopySession_002"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + + string disSandboxPath = "disSandboxPath"; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + int result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, ENOENT); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_PrepareCopySession_002"; +} + +/** + * @tc.name: TransListenerCoreTest_PrepareCopySession_003 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_PrepareCopySession_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_PrepareCopySession_003"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + info.sandboxPath = "abc"; + + string disSandboxPath = "disSandboxPath"; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + int result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, ENOENT); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_PrepareCopySession_003"; +} + +/** + * @tc.name: TransListenerCoreTest_PrepareCopySession_004 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_PrepareCopySession_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_PrepareCopySession_004"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + info.sandboxPath = "/data/test/PrepareCopySession_004.txt"; + + string disSandboxPath = "disSandboxPath"; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + int result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, ENOENT); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_PrepareCopySession_004"; +} + +/** + * @tc.name: TransListenerCoreTest_PrepareCopySession_005 + * @tc.desc: Test function of TransListenerCore::PrepareCopySession interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_PrepareCopySession_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_PrepareCopySession_005"; + + Storage::DistributedFile::HmdfsInfo info; + info.authority = "abc"; + info.sandboxPath = "/data/test/PrepareCopySession_004.txt"; + int32_t fd = open(info.sandboxPath.c_str(), O_CREAT | O_RDWR, 0644); + close(fd); + + string disSandboxPath = "disSandboxPath"; + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + int result = TransListenerCore::PrepareCopySession(srcUri, "destUri", nullptr, info, disSandboxPath); + EXPECT_EQ(result, ENOENT); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_PrepareCopySession_005"; +} + +/** + * @tc.name: TransListenerCoreTest_CopyToSandBox_001 + * @tc.desc: Test function of TransListenerCore::CopyToSandBox interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CopyToSandBox_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CopyToSandBox_001"; + + string disSandboxPath = "disSandboxPath"; + string sandboxPath = "sandboxPath"; + string currentId = "currentId"; + + int result = TransListenerCore::CopyToSandBox("srcUri", disSandboxPath, sandboxPath, currentId); + EXPECT_EQ(result, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CopyToSandBox_001"; +} + +/** + * @tc.name: TransListenerCoreTest_CopyToSandBox_002 + * @tc.desc: Test function of TransListenerCore::CopyToSandBox interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CopyToSandBox_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CopyToSandBox_002"; + + string disSandboxPath = g_path; + string sandboxPath = "/data/test"; + string currentId = "currentId"; + + int result = TransListenerCore::CopyToSandBox("srcUri", disSandboxPath, sandboxPath, currentId); + EXPECT_EQ(result, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CopyToSandBox_002"; +} + +/** + * @tc.name: TransListenerCoreTest_GetFileName_001 + * @tc.desc: Test function of TransListenerCore::GetFileName interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_GetFileName_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_GetFileName_001"; + + string path = "abc"; + + auto result = TransListenerCore::GetFileName(path); + EXPECT_EQ(result, ""); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_GetFileName_001"; +} + +/** + * @tc.name: TransListenerCoreTest_GetFileName_002 + * @tc.desc: Test function of TransListenerCore::GetFileName interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_GetFileName_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_GetFileName_002"; + + auto result = TransListenerCore::GetFileName(g_path); + EXPECT_EQ(result, "/TransListenerCoreTest.txt"); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_GetFileName_002"; +} + +/** + * @tc.name: TransListenerCoreTest_GetNetworkIdFromUri_001 + * @tc.desc: Test function of TransListenerCore::GetNetworkIdFromUri interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_GetNetworkIdFromUri_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_GetNetworkIdFromUri_001"; + + string uri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + + auto result = TransListenerCore::GetNetworkIdFromUri(uri); + EXPECT_EQ(result, "AD125AD1CF"); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_GetNetworkIdFromUri_001"; +} + +/** + * @tc.name: TransListenerCoreTest_CallbackComplete_001 + * @tc.desc: Test function of TransListenerCore::CallbackComplete interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CallbackComplete_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CallbackComplete_001"; + + TransListenerCore::CallbackComplete(nullptr); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CallbackComplete_001"; +} + +/** + * @tc.name: TransListenerCoreTest_CallbackComplete_002 + * @tc.desc: Test function of TransListenerCore::CallbackComplete interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CallbackComplete_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CallbackComplete_002"; + + auto entry = make_shared(make_shared(std::make_shared())); + entry->callback = nullptr; + TransListenerCore::CallbackComplete(entry); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CallbackComplete_002"; +} + +/** + * @tc.name: TransListenerCoreTest_CallbackComplete_003 + * @tc.desc: Test function of TransListenerCore::CallbackComplete interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CallbackComplete_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CallbackComplete_003"; + + auto entry = make_shared(make_shared(std::make_shared())); + entry->callback->listener = nullptr; + TransListenerCore::CallbackComplete(entry); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CallbackComplete_003"; +} + +/** + * @tc.name: TransListenerCoreTest_CallbackComplete_004 + * @tc.desc: Test function of TransListenerCore::CallbackComplete interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CallbackComplete_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CallbackComplete_004"; + + auto entry = make_shared(make_shared(std::make_shared())); + TransListenerCore::CallbackComplete(entry); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CallbackComplete_004"; +} + +/** + * @tc.name: TransListenerCoreTest_OnFileReceive_001 + * @tc.desc: Test function of TransListenerCore::OnFileReceive interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_OnFileReceive_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_OnFileReceive_001"; + + std::shared_ptr transListener = std::make_shared(); + transListener->callback_ = nullptr; + auto res = transListener->OnFileReceive(0, 0); + EXPECT_EQ(res, ENOMEM); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_OnFileReceive_001"; +} + +/** + * @tc.name: TransListenerCoreTest_OnFileReceive_002 + * @tc.desc: Test function of TransListenerCore::OnFileReceive interface for SUCC. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_OnFileReceive_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_OnFileReceive_002"; + + std::shared_ptr transListener = std::make_shared(); + transListener->callback_ = make_shared(std::make_shared()); + auto res = transListener->OnFileReceive(0, 0); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_OnFileReceive_002"; +} + +/** + * @tc.name: TransListenerCoreTest_OnFinished_001 + * @tc.desc: Test function of TransListenerCore::OnFinished interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_OnFinished_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_OnFinished_001"; + + std::shared_ptr transListener = std::make_shared(); + auto res = transListener->OnFinished("sessionName"); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_OnFinished_001"; +} + +/** + * @tc.name: TransListenerCoreTest_OnFailed_001 + * @tc.desc: Test function of TransListenerCore::OnFailed interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_OnFailed_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_OnFailed_001"; + + std::shared_ptr transListener = std::make_shared(); + auto res = transListener->OnFailed("sessionName", 0); + EXPECT_EQ(res, ERRNO_NOERR); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_OnFailed_001"; +} + +/** + * @tc.name: TransListenerCoreTest_CopyFileFromSoftBus_001 + * @tc.desc: Test function of TransListenerCore::CopyFileFromSoftBus interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(TransListenerCoreTest, TransListenerCoreTest_CopyFileFromSoftBus_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "TransListenerCoreTest-begin TransListenerCoreTest_CopyFileFromSoftBus_001"; + + string srcUri = "http://translistener.preparecopysession?networkid=AD125AD1CF"; + std::shared_ptr transListener = std::make_shared(); + std::shared_ptr infos = std::make_shared(); + transListener->copyEvent_.copyResult = FAILED; + + auto res = transListener->CopyFileFromSoftBus(srcUri, "destUri", infos, nullptr); + EXPECT_EQ(res, EIO); + + GTEST_LOG_(INFO) << "TransListenerCoreTest-end TransListenerCoreTest_CopyFileFromSoftBus_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp index d6103bee9..a602df5c8 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/unlink_core_mock_test.cpp @@ -15,11 +15,12 @@ #include #include -#include + #include +#include -#include "mock/uv_fs_mock.h" #include "unlink_core.h" +#include "uv_fs_mock.h" namespace OHOS::FileManagement::ModuleFileIO::Test { using namespace testing; diff --git a/interfaces/test/unittest/js/mod_fs/properties/utimes_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/utimes_core_mock_test.cpp new file mode 100644 index 000000000..c7d7e60c2 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/utimes_core_mock_test.cpp @@ -0,0 +1,124 @@ +/* + * 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 "utimes_core.h" +#include "uv_fs_mock.h" + +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class UtimesCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr uvMock = nullptr; +}; + +void UtimesCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + uvMock = std::make_shared(); + Uvfs::ins = uvMock; +} + +void UtimesCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + Uvfs::ins = nullptr; + uvMock = nullptr; +} + +void UtimesCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void UtimesCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: UtimesCoreMockTest_DoUtimes_001 + * @tc.desc: Test function of UtimesCore::DoUtimes interface for Failed. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UtimesCoreMockTest, UtimesCoreMockTest_DoUtimes_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "UtimesCoreMockTest-begin UtimesCoreMockTest_DoUtimes_001"; + + string path; + double mtime = 1; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(-1)); + auto res = UtimesCore::DoUtimes(path, mtime); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "UtimesCoreMockTest-end UtimesCoreMockTest_DoUtimes_001"; +} + +/** + * @tc.name: UtimesCoreMockTest_DoUtimes_002 + * @tc.desc: Test function of UtimesCore::DoUtimes interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UtimesCoreMockTest, UtimesCoreMockTest_DoUtimes_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "UtimesCoreMockTest-begin UtimesCoreMockTest_DoUtimes_002"; + + string path; + double mtime = 1; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(1)); + EXPECT_CALL(*uvMock, uv_fs_utime(_, _, _, _, _, _)).WillOnce(Return(-1)); + auto res = UtimesCore::DoUtimes(path, mtime); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "UtimesCoreMockTest-end UtimesCoreMockTest_DoUtimes_002"; +} + +/** + * @tc.name: UtimesCoreMockTest_DoUtimes_003 + * @tc.desc: Test function of UtimesCore::DoUtimes interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UtimesCoreMockTest, UtimesCoreMockTest_DoUtimes_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "UtimesCoreMockTest-begin UtimesCoreMockTest_DoUtimes_003"; + + string path; + double mtime = 1; + + EXPECT_CALL(*uvMock, uv_fs_stat(_, _, _, _)).WillOnce(Return(1)); + EXPECT_CALL(*uvMock, uv_fs_utime(_, _, _, _, _, _)).WillOnce(Return(1)); + auto res = UtimesCore::DoUtimes(path, mtime); + EXPECT_EQ(res.IsSuccess(), true); + + GTEST_LOG_(INFO) << "UtimesCoreMockTest-end UtimesCoreMockTest_DoUtimes_003"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/utimes_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/utimes_core_test.cpp new file mode 100644 index 000000000..54ee576cc --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/utimes_core_test.cpp @@ -0,0 +1,73 @@ +/* + * 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 "utimes_core.h" + +#include + + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class UtimesCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void UtimesCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void UtimesCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void UtimesCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void UtimesCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: UtimesCoreTest_DoUtimes_001 + * @tc.desc: Test function of UtimesCore::DoUtimes interface for Failed. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(UtimesCoreTest, UtimesCoreTest_DoUtimes_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "UtimesCoreTest-begin UtimesCoreTest_DoUtimes_001"; + + string path; + double mtime = -1; + auto res = UtimesCore::DoUtimes(path, mtime); + EXPECT_EQ(res.IsSuccess(), false); + + GTEST_LOG_(INFO) << "UtimesCoreTest-end UtimesCoreTest_DoUtimes_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test diff --git a/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp new file mode 100644 index 000000000..680a2ce32 --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/watcher_core_mock_test.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "eventfd_mock.h" +#include "filemgmt_libhilog.h" +#include "fs_file_watcher.h" +#include "inotify_mock.h" +#include "mock_watcher_callback.h" +#include "watcher_core.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +namespace Test { + +class WatcherCoreMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void WatcherCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + EventfdMock::EnableMock(); + InotifyMock::EnableMock(); +} + +void WatcherCoreMockTest::TearDownTestCase(void) +{ + EventfdMock::DisableMock(); + InotifyMock::DisableMock(); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void WatcherCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; + errno = 0; // Reset errno +} + +void WatcherCoreMockTest::TearDown(void) +{ + FsFileWatcher &watcher = FsFileWatcher::GetInstance(); + watcher.taskRunning_ = false; + watcher.run_ = false; + watcher.reading_ = false; + watcher.closed_ = false; + watcher.notifyFd_ = -1; + watcher.eventFd_ = -1; + watcher.dataCache_.ClearCache(); + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_001 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 0 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_001, testing::ext::TestSize.Level0) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_001"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_001"; + int32_t events = IN_CREATE; + std::shared_ptr callback = std::make_shared(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + auto eventfdMock = EventfdMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::Return(1)); + EXPECT_CALL(*eventfdMock, eventfd(testing::_, testing::_)).Times(1).WillOnce(testing::Return(2)); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + testing::Mock::VerifyAndClearExpectations(eventfdMock.get()); + EXPECT_TRUE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_001"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_002 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when InitNotify fails. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_002"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_002"; + int32_t events = IN_CREATE; + std::shared_ptr callback = std::make_shared(); + // Set mock behaviors + auto inotifyMock = InotifyMock::GetMock(); + EXPECT_CALL(*inotifyMock, inotify_init()).Times(1).WillOnce(testing::SetErrnoAndReturn(EIO, -1)); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + testing::Mock::VerifyAndClearExpectations(inotifyMock.get()); + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_002"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_003 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when events are invalid. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_003"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_003"; + int32_t events = -1; + std::shared_ptr callback = std::make_shared(); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_003"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_004 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when CheckEventValid false. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_004"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_004"; + int32_t invalidEvents = ~IN_ALL_EVENTS; + std::shared_ptr callback = std::make_shared(); + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, invalidEvents, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_004"; +} + +/** + * @tc.name: WatcherCoreMockTest_DoCreateWatcher_005 + * @tc.desc: Test function of WatcherCore::DoCreateWatcher interface for FAILURE when callback is null. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(WatcherCoreMockTest, WatcherCoreMockTest_DoCreateWatcher_005, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "WatcherCoreMockTest-begin WatcherCoreMockTest_DoCreateWatcher_005"; + // Prepare test parameters + std::string path = "/test/WatcherCoreMockTest_DoCreateWatcher_005"; + int32_t events = IN_CREATE; + std::shared_ptr callback = nullptr; + // Do testing + auto result = WatcherCore::DoCreateWatcher(path, events, callback); + // Verify results + EXPECT_FALSE(result.IsSuccess()); + GTEST_LOG_(INFO) << "WatcherCoreMockTest-end WatcherCoreMockTest_DoCreateWatcher_005"; +} + +} // namespace Test +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp new file mode 100644 index 000000000..e34ff3bdf --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_mock_test.cpp @@ -0,0 +1,179 @@ +/* + * 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 + +#include "system_mock.h" +#include "xattr_core.h" + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class XattrCoreMockTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline shared_ptr sys = nullptr; +}; + +filesystem::path XattrCoreMockTest::tempFilePath; + +void XattrCoreMockTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + tempFilePath = "/data/local/tmp/xattr_test_file.txt"; + ofstream tempfile(tempFilePath); + tempfile << "Test content\n123\n456"; + tempfile.close(); + sys = make_shared(); + System::ins = sys; +} + +void XattrCoreMockTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + filesystem::remove(tempFilePath); + System::ins = nullptr; + sys = nullptr; +} + +void XattrCoreMockTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void XattrCoreMockTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: XattrCoreMockTest_DoSetXattr_001 + * @tc.desc: Test function of XattrCore::DoSetXattr interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoSetXattr_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreMockTest-begin XattrCoreMockTest_DoSetXattr_001"; + + string path = tempFilePath.string(); + string key = "test_key"; + string value = "test_value"; + + EXPECT_CALL(*sys, setxattr(_, _, _, _, _)).WillOnce(SetErrnoAndReturn(EIO, -1)); + auto ret = XattrCore::DoSetXattr(path, key, value); + EXPECT_FALSE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "XattrCoreMockTest-end XattrCoreMockTest_DoSetXattr_001"; +} + +/** + * @tc.name: XattrCoreMockTest_DoSetXattr_002 + * @tc.desc: Test function of XattrCore::DoSetXattr interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoSetXattr_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreMockTest-begin XattrCoreMockTest_DoSetXattr_002"; + + string path = tempFilePath.string(); + string key = "test_key"; + string value = "test_value"; + + EXPECT_CALL(*sys, setxattr(_, _, _, _, _)).WillOnce(Return(0)); + auto ret = XattrCore::DoSetXattr(path, key, value); + EXPECT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "XattrCoreMockTest-end XattrCoreMockTest_DoSetXattr_002"; +} + +/** + * @tc.name: XattrCoreMockTest_DoGetXattr_001 + * @tc.desc: Test function of XattrCore::DoGetXattr interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoGetXattr_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreMockTest-begin XattrCoreMockTest_DoGetXattr_001"; + + string path = tempFilePath.string(); + string key = "test_key"; + + EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillRepeatedly(SetErrnoAndReturn(EIO, -1)); + auto ret = XattrCore::DoGetXattr(path, key); + EXPECT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "XattrCoreMockTest-end XattrCoreMockTest_DoGetXattr_001"; +} + +/** + * @tc.name: XattrCoreMockTest_DoGetXattr_002 + * @tc.desc: Test function of XattrCore::DoGetXattr interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoGetXattr_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreMockTest-begin XattrCoreMockTest_DoGetXattr_002"; + + string path = tempFilePath.string(); + string key = "test_key"; + + EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillOnce(Return(1)).WillOnce(SetErrnoAndReturn(EIO, -1)); + auto ret = XattrCore::DoGetXattr(path, key); + EXPECT_FALSE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "XattrCoreMockTest-end XattrCoreMockTest_DoGetXattr_002"; +} + +/** + * @tc.name: XattrCoreMockTest_DoGetXattr_003 + * @tc.desc: Test function of XattrCore::DoGetXattr interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreMockTest, XattrCoreMockTest_DoGetXattr_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreMockTest-begin XattrCoreMockTest_DoGetXattr_003"; + + string path = tempFilePath.string(); + string key = "test_key"; + + EXPECT_CALL(*sys, getxattr(_, _, _, _)).WillOnce(Return(1)).WillOnce(Return(1)); + auto ret = XattrCore::DoGetXattr(path, key); + EXPECT_TRUE(ret.IsSuccess()); + + GTEST_LOG_(INFO) << "XattrCoreMockTest-end XattrCoreMockTest_DoGetXattr_003"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_fs/properties/xattr_core_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_test.cpp new file mode 100644 index 000000000..febfd1c1e --- /dev/null +++ b/interfaces/test/unittest/js/mod_fs/properties/xattr_core_test.cpp @@ -0,0 +1,143 @@ +/* + * 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 "xattr_core.h" + +#define MAX_LEN 4096 + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class XattrCoreTest : public testing::Test { +public: + static filesystem::path tempFilePath; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +filesystem::path XattrCoreTest::tempFilePath; + +void XattrCoreTest::SetUpTestCase(void) +{ + tempFilePath = "/data/local/tmp/xattr_test_file.txt"; + ofstream tempfile(tempFilePath); + tempfile << "Test content\n123\n456"; + tempfile.close(); + GTEST_LOG_(INFO) << "SetUpTestCase"; +} + +void XattrCoreTest::TearDownTestCase(void) +{ + filesystem::remove(tempFilePath); + GTEST_LOG_(INFO) << "TearDownTestCase"; +} + +void XattrCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void XattrCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: XattrCoreTest_DoSetXattr_001 + * @tc.desc: Test function of XattrCore::DoSetXattr interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreTest, XattrCoreTest_DoSetXattr_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreTest-begin XattrCoreTest_DoSetXattr_001"; + + string path = tempFilePath.string(); + std::string key = "test_key"; + std::string value(MAX_LEN + 1, 'a'); + + auto ret = XattrCore::DoSetXattr(path, key, value); + + EXPECT_FALSE(ret.IsSuccess()); + auto err = ret.GetError(); + int errCode = err.GetErrNo(); + EXPECT_EQ(errCode, 13900020); + auto msg = err.GetErrMsg(); + EXPECT_EQ(msg, "Invalid argument"); + + GTEST_LOG_(INFO) << "XattrCoreTest-end XattrCoreTest_DoSetXattr_001"; +} + +/** + * @tc.name: XattrCoreTest_DoSetXattr_002 + * @tc.desc: Test function of XattrCore::DoSetXattr interface for FAILED. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreTest, XattrCoreTest_DoSetXattr_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreTest-begin XattrCoreTest_DoSetXattr_002"; + + string path = tempFilePath.string(); + std::string key(MAX_LEN + 1, 'a'); + std::string value = "test_value"; + + auto ret = XattrCore::DoSetXattr(path, key, value); + + EXPECT_FALSE(ret.IsSuccess()); + auto err = ret.GetError(); + int errCode = err.GetErrNo(); + EXPECT_EQ(errCode, 13900020); + auto msg = err.GetErrMsg(); + EXPECT_EQ(msg, "Invalid argument"); + + GTEST_LOG_(INFO) << "XattrCoreTest-end XattrCoreTest_DoSetXattr_002"; +} + +/** + * @tc.name: XattrCoreTest_DoGetXattr_001 + * @tc.desc: Test function of XattrCore::DoGetXattr interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(XattrCoreTest, XattrCoreTest_DoGetXattr_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "XattrCoreTest-begin XattrCoreTest_DoGetXattr_001"; + + std::string path = "/data/local/tmp/nonexistent_file"; + string key = "test_key"; + + auto ret = XattrCore::DoGetXattr(path, key); + + ASSERT_TRUE(ret.IsSuccess()); + EXPECT_EQ(ret.GetData().value(), ""); + + GTEST_LOG_(INFO) << "XattrCoreTest-end XattrCoreTest_DoGetXattr_001"; +} + +} // namespace OHOS::FileManagement::ModuleFileIO::Test \ No newline at end of file diff --git a/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp b/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp index 069a3230e..0f343b77b 100644 --- a/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp +++ b/interfaces/test/unittest/js/mod_hash/hash_core_test.cpp @@ -45,7 +45,6 @@ public: * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(HashCoreTest, DoHashTest_0001, testing::ext::TestSize.Level1) { @@ -66,7 +65,6 @@ HWTEST_F(HashCoreTest, DoHashTest_0001, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(HashCoreTest, DoHashTest_0002, testing::ext::TestSize.Level1) { @@ -83,7 +81,6 @@ HWTEST_F(HashCoreTest, DoHashTest_0002, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(HashCoreTest, DoHashTest_0003, testing::ext::TestSize.Level1) { @@ -100,7 +97,6 @@ HWTEST_F(HashCoreTest, DoHashTest_0003, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(HashCoreTest, DoHashTest_0004, testing::ext::TestSize.Level1) { @@ -117,7 +113,6 @@ HWTEST_F(HashCoreTest, DoHashTest_0004, testing::ext::TestSize.Level1) * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(HashCoreTest, DoHashTest_0005, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp b/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp index f320af037..e0447335e 100644 --- a/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp +++ b/interfaces/test/unittest/js/mod_securitylabel/securitylabel_core_test.cpp @@ -48,7 +48,6 @@ public: * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0001, testing::ext::TestSize.Level1) { @@ -68,7 +67,6 @@ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0001, testing::ext::TestSize. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0002, testing::ext::TestSize.Level1) { @@ -88,7 +86,6 @@ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0002, testing::ext::TestSize. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0003, testing::ext::TestSize.Level1) { @@ -105,7 +102,6 @@ HWTEST_F(SecurityLabelCoreTest, DoSetSecurityLabel_0003, testing::ext::TestSize. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(SecurityLabelCoreTest, DoGetSecurityLabel_0001, testing::ext::TestSize.Level1) { @@ -125,7 +121,6 @@ HWTEST_F(SecurityLabelCoreTest, DoGetSecurityLabel_0001, testing::ext::TestSize. * @tc.size: MEDIUM * @tc.type: FUNC * @tc.level Level 1 - * @tc.require: AR000IGDNF */ HWTEST_F(SecurityLabelCoreTest, DoGetSecurityLabel_0002, testing::ext::TestSize.Level1) { diff --git a/interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp b/interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp new file mode 100644 index 000000000..82316d884 --- /dev/null +++ b/interfaces/test/unittest/js/mod_statvfs/statvfs_core_test.cpp @@ -0,0 +1,142 @@ +/* + * 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 "statvfs_core.h" + +#include +#include +#include + +namespace OHOS::FileManagement::ModuleFileIO::Test { +using namespace testing; +using namespace testing::ext; +using namespace std; + +class StatvFsCoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void StatvFsCoreTest::SetUpTestCase(void) +{ + GTEST_LOG_(INFO) << "SetUpTestCase"; + int32_t fd = open("/data/test/statvfs.txt", O_CREAT | O_RDWR, 0644); + if (fd <= 0) { + close(fd); + ASSERT_TRUE(false); + } + close(fd); +} + +void StatvFsCoreTest::TearDownTestCase(void) +{ + GTEST_LOG_(INFO) << "TearDownTestCase"; + rmdir("/data/test/statvfs.txt"); +} + +void StatvFsCoreTest::SetUp(void) +{ + GTEST_LOG_(INFO) << "SetUp"; +} + +void StatvFsCoreTest::TearDown(void) +{ + GTEST_LOG_(INFO) << "TearDown"; +} + +/** + * @tc.name: StatvFsCoreTest_DoGetFreeSize_001 + * @tc.desc: Test function of DoGetFreeSize interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(StatvFsCoreTest, StatvFsCoreTest_DoGetFreeSize_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StatvFsCoreTest-begin StatvFsCoreTest_DoGetFreeSize_001"; + + struct statvfs diskInfo; + diskInfo.f_bsize = 2; + diskInfo.f_bfree = 1; + + auto result = ModuleStatvfs::StatvfsCore::DoGetFreeSize("/data/test/statvfs.txt"); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "StatvFsCoreTest-end StatvFsCoreTest_DoGetFreeSize_001"; +} + +/** + * @tc.name: StatvFsCoreTest_DoGetFreeSize_002 + * @tc.desc: Test function of DoGetFreeSize interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(StatvFsCoreTest, StatvFsCoreTest_DoGetFreeSize_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StatvFsCoreTest-begin StatvFsCoreTest_DoGetFreeSize_002"; + + auto result = ModuleStatvfs::StatvfsCore::DoGetFreeSize("/test/path"); + EXPECT_EQ(result.IsSuccess(), false); + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "StatvFsCoreTest-end StatvFsCoreTest_DoGetFreeSize_002"; +} + +/** + * @tc.name: StatvFsCoreTest_DoGetTotalSize_003 + * @tc.desc: Test function of DoGetTotalSize interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(StatvFsCoreTest, StatvFsCoreTest_DoGetTotalSize_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StatvFsCoreTest-begin StatvFsCoreTest_DoGetTotalSize_003"; + + struct statvfs diskInfo; + diskInfo.f_bsize = 2; + diskInfo.f_blocks = 1; + + auto result = ModuleStatvfs::StatvfsCore::DoGetTotalSize("/data/test/statvfs.txt"); + EXPECT_EQ(result.IsSuccess(), true); + + GTEST_LOG_(INFO) << "StatvFsCoreTest-end StatvFsCoreTest_DoGetTotalSize_003"; +} + +/** + * @tc.name: StatvFsCoreTest_DoGetTotalSize_004 + * @tc.desc: Test function of DoGetTotalSize interface for FALSE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + */ +HWTEST_F(StatvFsCoreTest, StatvFsCoreTest_DoGetTotalSize_004, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "StatvFsCoreTest-begin StatvFsCoreTest_DoGetTotalSize_004"; + + auto result = ModuleStatvfs::StatvfsCore::DoGetTotalSize("/test/path"); + EXPECT_EQ(result.IsSuccess(), false); + auto err = result.GetError(); + EXPECT_EQ(err.GetErrNo(), 13900002); + + GTEST_LOG_(INFO) << "StatvFsCoreTest-end StatvFsCoreTest_DoGetTotalSize_004"; +} + +} \ No newline at end of file diff --git a/utils/filemgmt_libn/include/n_error.h b/utils/filemgmt_libn/include/n_error.h index 616855141..e4f624e2b 100644 --- a/utils/filemgmt_libn/include/n_error.h +++ b/utils/filemgmt_libn/include/n_error.h @@ -160,9 +160,7 @@ enum ErrCodeSuffixOfDistributedFile { E_NETWORK_ERR, E_BATTERY_WARNING, E_EXCEED_MAX_LIMIT, - E_INNER_ERROR, - E_OTHER_TASK_RUNNING, - E_VERSION_FILE_NO_EXIST, + E_DATABASE_FAILED }; enum CommonErrCode { @@ -275,8 +273,7 @@ static inline std::unordered_map> errCodeTa { EBADFD, { FILEIO_SYS_CAP_TAG + E_BADFD, "File descriptor in bad state" } }, { ERESTART, { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, { EDQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, - { UNKROWN_ERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error. Possible causes: 1.Insufficient memory." - "2.Memory operation error. 3.Null pointer. 4.Failed to obtain expected resources." } }, + { UNKROWN_ERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, { ENOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, { ENETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, { ECONNECTIONFAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, @@ -327,8 +324,7 @@ static inline std::unordered_map> errCodeTa { FILEIO_SYS_CAP_TAG + E_RESTART, { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, { FILEIO_SYS_CAP_TAG + E_DQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, - { FILEIO_SYS_CAP_TAG + E_UKERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error. Possible causes:" - "1.Insufficient memory. 2.Memory operation error. 3.Null pointer. 4.Failed to obtain expected resources." } }, + { FILEIO_SYS_CAP_TAG + E_UKERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, { FILEIO_SYS_CAP_TAG + E_NOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, { FILEIO_SYS_CAP_TAG + E_CONNECTION_FAIL, "Connection failed" } }, @@ -361,8 +357,7 @@ static inline std::unordered_map> errCodeTa "Member not exist" } }, { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, { USER_FILE_MANAGER_SYS_CAP_TAG + E_INPUT, "Wrong input parameter" } }, - { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, - "IPC error. Possible causes: 1.IPC failed or timed out. 2.Failed to load the service" } }, + { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, { STORAGE_SERVICE_SYS_CAP_TAG + E_IPCSS, "IPC error" } }, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, { STORAGE_SERVICE_SYS_CAP_TAG + E_NOTSUPPORTEDFS, "Not supported filesystem" } }, { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, { STORAGE_SERVICE_SYS_CAP_TAG + E_MOUNT, "Failed to mount" } }, @@ -417,14 +412,8 @@ static inline std::unordered_map> errCodeTa E_BATTERY_WARNING, "Battery level warning" } }, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_EXCEED_MAX_LIMIT, "Exceed the maximum limit" } }, - { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_INNER_ERROR, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + - E_INNER_ERROR, "Inner error. Possible causes: 1.Failed to access the database or execute the SQL statement." - "2.System error, such as a null pointer, insufficient memory or a JS engine exception." } }, - { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_OTHER_TASK_RUNNING, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + - E_OTHER_TASK_RUNNING, "The same task is already in progress" } }, - { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_VERSION_FILE_NO_EXIST, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + - E_VERSION_FILE_NO_EXIST, "The version file specified to replace the original file does not exist." } }, - + { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + E_DATABASE_FAILED, { DISTRIBUTEDFILE_SERVICE_SYS_CAP_TAG + + E_DATABASE_FAILED, "Database operation failed" } }, }; class NError { -- Gitee From fa673ecef8eceb92c43fcaa419f4bf0aa93f9d88 Mon Sep 17 00:00:00 2001 From: liyuke Date: Wed, 9 Jul 2025 10:53:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E7=BC=96=E8=AF=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3276e39a949d858c8048f4f6f3396acf325de924 Signed-off-by: zxl <1554188414@qq.com> --- .../randomaccessfile_entity.h | 2 +- .../src/mod_fs/class_watcher/fs_watch_entity.h | 6 +++--- .../js/src/mod_fs/class_watcher/fs_watcher.cpp | 4 ++-- .../src/mod_fs/properties/ani/listfile_ani.cpp | 4 ++-- .../js/src/mod_fs/properties/watcher_core.cpp | 2 +- .../class_watcher/fs_watcher_mock_test.cpp | 8 ++++---- .../properties/trans_listener_mock_test.cpp | 16 ++++++++++++++++ 7 files changed, 29 insertions(+), 13 deletions(-) diff --git a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h index cc0f26609..9f9313566 100644 --- a/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h +++ b/interfaces/kits/js/src/mod_fs/class_randomaccessfile/randomaccessfile_entity.h @@ -19,7 +19,7 @@ #include #include "fd_guard.h" -#include "n_val.h" +#include "filemgmt_libhilog.h" namespace OHOS { namespace FileManagement { 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 88fe92b18..83184bb48 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 @@ -36,14 +36,14 @@ struct WatcherInfo { explicit WatcherInfo(std::shared_ptr callback) : callback(std::move(callback)) {} - void TriggerCallback(const std::string &fileName, uint32_t event, uint32_t cookie) const + void TriggerCallback(const std::string &eventFileName, uint32_t event, uint32_t cookie) const { - callback->InvokeCallback(fileName, event, cookie); + callback->InvokeCallback(eventFileName, event, cookie); } }; struct FsWatchEntity { - std::shared_ptr data_; + std::shared_ptr watherInfo; }; } // 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 6be590065..73dd1d830 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->data_); + int ret = FsFileWatcher::GetInstance().StopNotify(watchEntity->watherInfo); 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->data_; + shared_ptr info = watchEntity->watherInfo; int ret = FsFileWatcher::GetInstance().StartNotify(info); if (ret != ERRNO_NOERR) { HILOGE("Failed to startNotify."); diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp index 65e0f545e..ac1ec9039 100644 --- a/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/ani/listfile_ani.cpp @@ -65,7 +65,7 @@ tuple ParseIntParam(ani_env *env, ani_object obj, string tag) } ani_int resultRefRes; if (ANI_OK != env->Object_CallMethodByName_Int( - static_cast(result_ref), "toInt", nullptr, &result_ref_res)) { + static_cast(resultRef), "toInt", nullptr, &resultRefRes)) { result = -1; return { false, result }; } @@ -87,7 +87,7 @@ tuple> ParseDoubleParam(ani_env *env, ani_object obj, str ani_double resultRefRes; if (ANI_OK != env->Object_CallMethodByName_Double( - static_cast(result_ref), "toDouble", nullptr, &result_ref_res)) { + static_cast(resultRef), "toDouble", nullptr, &resultRefRes)) { return { false, nullopt }; } double result = static_cast(resultRefRes); 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 1ea4a713a..2b78a7c91 100644 --- a/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/watcher_core.cpp @@ -96,7 +96,7 @@ FsResult WatcherCore::DoCreateWatcher( return FsResult::Error(EIO); } - watchEntity->data_ = info; + watchEntity->watherInfo = info; bool ret = FsFileWatcher::GetInstance().AddWatcherInfo(info); if (!ret) { 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 805c6af56..6894647ea 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()->data_ = info; + fsWatcher.GetWatchEntity()->watherInfo = 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()->data_ = info; + fsWatcher.GetWatchEntity()->watherInfo = 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()->data_ = info; + fsWatcher.GetWatchEntity()->watherInfo = 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()->data_ = info; + fsWatcher.GetWatchEntity()->watherInfo = info; // Prepare test condition for FsFileWatcher FsFileWatcher &watcher = FsFileWatcher::GetInstance(); watcher.notifyFd_ = -1; // Invalid notifyFd diff --git a/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp index dbda35d77..7a9d56704 100644 --- a/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp +++ b/interfaces/test/unittest/js/mod_fs/properties/trans_listener_mock_test.cpp @@ -52,6 +52,22 @@ public: { return 0; } + int32_t CancelCopyTask(const std::string &srcUri, const std::string &dstUri) + { + return 0; + } + int32_t GetDfsSwitchStatus(const std::string &networkId, int32_t &switchStatus) + { + return 0; + } + int32_t UpdateDfsSwitchStatus(int32_t switchStatus) + { + return 0; + } + int32_t GetConnectedDeviceList(std::vector &deviceList) + { + return 0; + } int32_t PushAsset( int32_t userId, const sptr &assetObj, const sptr &sendCallback) override { -- Gitee